From 7387b9c55c43acbfd710d38590a077ff2e409ea1 Mon Sep 17 00:00:00 2001 From: waynemwashuma <94756970+waynemwashuma@users.noreply.github.com> Date: Wed, 3 Jun 2026 02:31:41 +0300 Subject: [PATCH 1/3] Simplify asset server and its systems --- src/asset/plugins/assetServer.js | 16 +- src/asset/resources/assetserver.js | 246 ++++++++++------------------ src/asset/systems/events.js | 45 +---- src/asset/systems/server.js | 108 +++++++++--- src/asset/tests/assetserver.test.js | 80 ++++++++- 5 files changed, 264 insertions(+), 231 deletions(-) diff --git a/src/asset/plugins/assetServer.js b/src/asset/plugins/assetServer.js index 6e49a80b..e0c77452 100644 --- a/src/asset/plugins/assetServer.js +++ b/src/asset/plugins/assetServer.js @@ -2,7 +2,7 @@ import { App, Plugin } from '../../app/index.js' import { EventPlugin } from '../../event/index.js' import { AssetServer } from '../resources/index.js' import { AssetLoadFail, AssetLoadSuccess, AssetSaveSuccess } from '../events/index.js' -import { updateAssets, updateAssetLoadEvents, updateAssetSaveEvents, logFailedLoads, registerAssetServerTypes } from '../systems/index.js' +import { updateAssets, logFailedLoads, registerAssetServerTypes } from '../systems/index.js' import { AppSchedule, CoreSystems } from '../../core/index.js' export class AssetServerPlugin extends Plugin { @@ -22,10 +22,16 @@ export class AssetServerPlugin extends Plugin { .registerPlugin(new EventPlugin({ event: AssetLoadFail })) - .registerSystem({ schedule: AppSchedule.Startup, systemGroup: CoreSystems.Start, system: registerAssetServerTypes }) - .registerSystem({ schedule: AppSchedule.Update, systemGroup: CoreSystems.End, system: updateAssets }) - .registerSystem({ schedule: AppSchedule.Update, systemGroup: CoreSystems.End, system: updateAssetLoadEvents }) - .registerSystem({ schedule: AppSchedule.Update, systemGroup: CoreSystems.End, system: updateAssetSaveEvents }) + .registerSystem({ + schedule: AppSchedule.Startup, + systemGroup: CoreSystems.Start, + system: registerAssetServerTypes + }) + .registerSystem({ + schedule: AppSchedule.Update, + systemGroup: CoreSystems.PostMain, + system: updateAssets + }) .registerSystem({ schedule: AppSchedule.Update, systemGroup: CoreSystems.End, system: logFailedLoads }) } } diff --git a/src/asset/resources/assetserver.js b/src/asset/resources/assetserver.js index 9dba33b4..e894c106 100644 --- a/src/asset/resources/assetserver.js +++ b/src/asset/resources/assetserver.js @@ -4,7 +4,7 @@ import { typeid } from '../../type/index.js' import { assert, warn } from '../../logger/index.js' import { getFileExtension, swapRemove } from '../../utils/index.js' import { Assets, Handle, Parser, Exporter } from '../core/index.js' -import { AssetLoadSuccess, AssetSaveSuccess, AssetLoadFail, AssetLoadOperation } from '../events/index.js' +import { AssetLoadOperation } from '../events/index.js' /** * @typedef {number} ParserId @@ -149,6 +149,7 @@ export class Exporters { return /** @type {Exporter} */(exporter) } } + export class AssetServer { /** @@ -188,26 +189,15 @@ export class AssetServer { /** * @private - * @type {UntypedAsset[]} - */ - loadedAssets = [] - - /** - * @private - * @type {AssetLoadSuccess[]} + * @type {AssetLoadRequest[]} */ - loaded = [] + loadRequests = [] /** * @private - * @type {AssetSaveSuccess[]} - */ - saved = [] - - /** - * @type {AssetLoadFail[]} + * @type {AssetSaveRequest[]} */ - failed = [] + saveRequests = [] /** * @template T @@ -265,7 +255,7 @@ export class AssetServer { const newAssetInfo = new AssetInfo(completePath, assetId) this.assetInfos.add(newAssetInfo) - this.fetch(assetId, typeId, completePath, newAssetInfo) + this.loadRequests.push(new AssetLoadRequest(typeId, assetId, completePath, newAssetInfo)) return handle } @@ -282,138 +272,40 @@ export class AssetServer { const targetPath = path ?? info?.path if (!targetPath) { - this.recordFailure( + this.saveRequests.push(new AssetSaveRequest( typeId, assetId, path || '', - 'The given asset handle does not have a registered asset path.', - AssetLoadOperation.Saving - ) - + 'The given asset handle does not have a registered asset path.' + )) return } - return this.post(assetId, typeId, targetPath) - } - - /** - * @param {AssetId} assetId - * @param {TypeId} typeId - * @param {string} path - * @param {AssetInfo} info - */ - async fetch(assetId, typeId, path, info) { - try { - const asset = await this.internalFetch(assetId, typeId, path) - - this.loaded.push(new AssetLoadSuccess(typeId, assetId, path)) - this.loadedAssets.push(asset) - info.loadstate = LoadState.Loaded - } catch(error) { - this.recordFailure(typeId, assetId, path, error) - info.loadstate = LoadState.Failed - } + this.saveRequests.push(new AssetSaveRequest(typeId, assetId, targetPath)) } /** - * @private - * @param {AssetId} assetId - * @param {TypeId} typeId - * @param {string} path - */ - async post(assetId, typeId, path) { - try { - const response = await fetch(path, { - method: 'POST', - body: await this.serialize(assetId, typeId, path) - }) - - if (!response.ok) { - this.recordFailure(typeId, assetId, path, response.statusText, AssetLoadOperation.Saving) - } else { - this.saved.push(new AssetSaveSuccess(typeId, assetId, path)) - } - } catch(error) { - let message = 'Could not export the asset.' - - if (typeof error === 'string') { - message = error - } else if (error instanceof Error) { - const { message: errorMessage } = error - - message = errorMessage - } - - this.recordFailure(typeId, assetId, path, message, AssetLoadOperation.Saving) - } - } - - /** - * @private - * @param {AssetId} assetId + * @template T * @param {TypeId} typeId * @param {string} path - * @returns {Promise} + * @returns {Parser} */ - async serialize(assetId, typeId, path) { + getParser(typeId, path) { const extension = getFileExtension(path) - const assets = this.assets.get(typeId) - const exporter = this.exporters.get(typeId, extension) - - assert(assets, `No assets registered for the asset type \`${typeId}\` on \`AssetServer\``) - - const asset = assets.getByAssetId(assetId) - if (asset === undefined) { - throw 'Could not find the asset to export.' - } - - return exporter.serialize(asset) + return this.parsers.get(typeId, extension) } /** - * @private - * @param {TypeId} typeId - * @param {AssetId} assetId - * @param {string} path - * @param {string} message - * @param {number} [operation=AssetLoadOperation.Loading] - */ - recordFailure(typeId, assetId, path, message, operation = AssetLoadOperation.Loading) { - this.failed.push(new AssetLoadFail( - typeId, - assetId, - path, - message, - operation - )) - } - - /** - * @private - * @param {AssetId} assetId + * @template T * @param {TypeId} typeId * @param {string} path - * @throws {string | Error} - * @returns {Promise} + * @returns {Exporter} */ - async internalFetch(assetId, typeId, path) { + getExporter(typeId, path) { const extension = getFileExtension(path) - const parser = this.parsers.get(typeId, extension) - - const response = await fetch(path) - - if (!response.ok) { - throw response.statusText - } - - const result = await parser.parse(response) - if (!result) { - throw 'Could not parse the asset.' - } - - return new UntypedAsset(typeId, assetId, result) + return this.exporters.get(typeId, extension) } /** @@ -454,51 +346,65 @@ export class AssetServer { } /** - * @returns {readonly AssetLoadSuccess[]} + * @returns {readonly AssetLoadRequest[]} */ - flushLoadSuccess() { - const buffer = this.loaded + flushLoadRequests() { + const buffer = this.loadRequests - this.loaded = [] + this.loadRequests = [] return buffer } /** - * @returns {readonly AssetSaveSuccess[]} + * @returns {readonly AssetSaveRequest[]} */ - flushSaveSuccess() { - const buffer = this.saved + flushSaveRequests() { + const buffer = this.saveRequests - this.saved = [] + this.saveRequests = [] return buffer } /** - * @returns {readonly AssetLoadFail[]} + * @param {AssetInfo} info + * @param {number} state */ - flushLoadFail() { - const buffer = this.failed + setLoadState(info, state) { + info.loadstate = state + } +} - this.failed = [] +class AssetInfo { - return buffer - } + /** + * @readonly + * @type {AssetId} + */ + id /** - * @returns {readonly UntypedAsset[]} + * @type {LoadState} */ - flushLoadedAssets() { - const buffer = this.loadedAssets + loadstate = LoadState.Loading - this.loadedAssets = [] + /** + * @type {string} + */ + path - return buffer + /** + * @param {string} path + * @param {AssetId} assetId + */ + constructor(path, assetId) { + this.path = path + this.id = assetId } } -class UntypedAsset { +class AssetLoadRequest { /** * @readonly @@ -514,47 +420,67 @@ class UntypedAsset { /** * @readonly - * @type {unknown} + * @type {string} + */ + path + + /** + * @readonly + * @type {AssetInfo} */ - asset + info /** * @param {TypeId} typeId * @param {AssetId} assetId - * @param {unknown} asset + * @param {string} path + * @param {AssetInfo} info */ - constructor(typeId, assetId, asset) { + constructor(typeId, assetId, path, info) { this.typeId = typeId - this.asset = asset this.assetId = assetId + this.path = path + this.info = info } } -class AssetInfo { +class AssetSaveRequest { /** * @readonly - * @type {AssetId} + * @type {TypeId} */ - id + typeId /** - * @type {LoadState} + * @readonly + * @type {AssetId} */ - loadstate = LoadState.Loading + assetId /** + * @readonly * @type {string} */ path /** - * @param {string} path + * @readonly + * @type {string | undefined} + */ + reason + + /** + * @param {TypeId} typeId * @param {AssetId} assetId + * @param {string} path + * @param {string} [reason] */ - constructor(path, assetId) { + constructor(typeId, assetId, path, reason) { + this.typeId = typeId + this.assetId = assetId this.path = path - this.id = assetId + this.reason = reason } } diff --git a/src/asset/systems/events.js b/src/asset/systems/events.js index 03af7ccd..c90c564f 100644 --- a/src/asset/systems/events.js +++ b/src/asset/systems/events.js @@ -4,9 +4,8 @@ import { Assets } from '../core/index.js' import { Events } from '../../event/index.js' import { typeid, typeidGeneric } from '../../type/index.js' -import { AssetServer } from '../resources/index.js' -import { AssetAdded, AssetDropped, AssetModified, AssetLoadSuccess, AssetSaveSuccess, AssetLoadFail } from '../events/index.js' -import { warnOnce } from '../../logger/index.js' +import { AssetAdded, AssetDropped, AssetModified, AssetLoadFail, AssetLoadOperation } from '../events/index.js' +import { error, warnOnce } from '../../logger/index.js' /** * @template T @@ -55,44 +54,18 @@ export function updateAssetEvents(assetType, eventType) { } /** - * @template T * @param {World} world * @returns {void} */ -export function updateAssetLoadEvents(world) { - const server = world.getResource(AssetServer) - - /** @type {Events} */ - const sucessEvents = world.getResourceByTypeId(typeidGeneric(Events, [AssetLoadSuccess])) +export function logFailedLoads(world) { /** @type {Events} */ - const failEvents = world.getResourceByTypeId(typeidGeneric(Events, [AssetLoadFail])) - - const succeeded = server.flushLoadSuccess() - const failed = server.flushLoadFail() - - for (let i = 0; i < succeeded.length; i++) { - sucessEvents.write(succeeded[i]) - } + const events = world.getResourceByTypeId(typeidGeneric(Events, [AssetLoadFail])) - for (let i = 0; i < failed.length; i++) { - failEvents.write(failed[i]) - } -} + events.each((event) => { + const { data } = event + const operation = data.operation === AssetLoadOperation.Saving ? 'saving' : 'loading' -/** - * @param {World} world - * @returns {void} - */ -export function updateAssetSaveEvents(world) { - const server = world.getResource(AssetServer) - - /** @type {Events} */ - const saveEvents = world.getResourceByTypeId(typeidGeneric(Events, [AssetSaveSuccess])) - - const saved = server.flushSaveSuccess() - - for (let i = 0; i < saved.length; i++) { - saveEvents.write(saved[i]) - } + error(`\`AssetServer\` error ${operation} "${data.path}": ${data.reason}`) + }) } diff --git a/src/asset/systems/server.js b/src/asset/systems/server.js index 65eb4484..6bd4dea5 100644 --- a/src/asset/systems/server.js +++ b/src/asset/systems/server.js @@ -4,9 +4,9 @@ import { Events } from '../../event/index.js' import { typeidGeneric } from '../../type/index.js' import { Assets } from '../core/index.js' -import { AssetServer } from '../resources/index.js' -import { AssetLoadFail, AssetLoadOperation } from '../events/index.js' -import { error } from '../../logger/index.js' +import { AssetServer, LoadState } from '../resources/index.js' +import { AssetLoadFail, AssetLoadOperation, AssetLoadSuccess, AssetSaveSuccess } from '../events/index.js' +import { assert } from '../../logger/index.js' /** * @template T @@ -53,34 +53,98 @@ export function registerAssetExporterOnAssetServer(type, exporter) { /** * @param {World} world */ -export function updateAssets(world) { +export async function updateAssets(world) { const server = world.getResource(AssetServer) - const loaded = server.flushLoadedAssets() + /** @type {Events} */ + const loadSuccessEvents = world.getResourceByTypeId(typeidGeneric(Events, [AssetLoadSuccess])) + /** @type {Events} */ + const saveSuccessEvents = world.getResourceByTypeId(typeidGeneric(Events, [AssetSaveSuccess])) + /** @type {Events} */ + const loadFailEvents = world.getResourceByTypeId(typeidGeneric(Events, [AssetLoadFail])) + + const loadRequests = server.flushLoadRequests() + const saveRequests = server.flushSaveRequests() + + for (let i = 0; i < loadRequests.length; i++) { + const { assetId, info, path, typeId } = loadRequests[i] + + try { + const parser = server.getParser(typeId, path) + const response = await fetch(path) + + if (!response.ok) { + throw response.statusText + } + + const asset = await parser.parse(response) - for (let i = 0; i < loaded.length; i++) { - const { asset, typeId, assetId } = loaded[i] - const assets = server.getAssets(typeId) + if (!asset) { + throw 'Could not parse the asset.' + } - if (!assets) continue + const assets = server.getAssets(typeId) - assets.setUsingAssetId(assetId, asset) + assert(assets, `No assets registered for the asset type \`${typeId}\` on \`AssetServer\``) + + assets.setUsingAssetId(assetId, asset) + server.setLoadState(info, LoadState.Loaded) + loadSuccessEvents.write(new AssetLoadSuccess(typeId, assetId, path)) + } catch(error) { + server.setLoadState(info, LoadState.Failed) + let message = 'Could not load the asset.' + + if (typeof error === 'string') { + message = error + } else if (error instanceof Error) { + message = error.message + } + + loadFailEvents.write(new AssetLoadFail(typeId, assetId, path, message)) + } } -} -/** - * @param {World} world - */ -export function logFailedLoads(world) { + for (let i = 0; i < saveRequests.length; i++) { + const { assetId, path, reason, typeId } = saveRequests[i] - /** @type {Events} */ - const events = world.getResourceByTypeId(typeidGeneric(Events, [AssetLoadFail])) + if (reason) { + loadFailEvents.write(new AssetLoadFail(typeId, assetId, path, reason, AssetLoadOperation.Saving)) + continue + } + + try { + const assets = server.getAssets(typeId) + + assert(assets, `No assets registered for the asset type \`${typeId}\` on \`AssetServer\``) + + const asset = assets.getByAssetId(assetId) - events.each((event) => { - const { data } = event - const operation = data.operation === AssetLoadOperation.Saving ? 'saving' : 'loading' + if (asset === undefined) { + throw 'Could not find the asset to export.' + } - error(`\`AssetServer\` error ${operation} "${data.path}": ${data.reason}`) - }) + const exporter = server.getExporter(typeId, path) + const response = await fetch(path, { + method: 'POST', + body: await exporter.serialize(asset) + }) + + if (!response.ok) { + throw response.statusText + } + + saveSuccessEvents.write(new AssetSaveSuccess(typeId, assetId, path)) + } catch(error) { + let message = 'Could not export the asset.' + + if (typeof error === 'string') { + message = error + } else if (error instanceof Error) { + message = error.message + } + + loadFailEvents.write(new AssetLoadFail(typeId, assetId, path, message, AssetLoadOperation.Saving)) + } + } } /** diff --git a/src/asset/tests/assetserver.test.js b/src/asset/tests/assetserver.test.js index c7ac06be..d8e4e30f 100644 --- a/src/asset/tests/assetserver.test.js +++ b/src/asset/tests/assetserver.test.js @@ -1,7 +1,11 @@ import { deepStrictEqual, notDeepStrictEqual } from "assert"; -import test, { describe,todo } from "node:test"; +import test, { describe } from "node:test"; import { Assets, AssetServer, Exporter, Parser } from "../index.js"; -import { typeid } from "../../type/index.js"; +import { typeid, typeidGeneric } from "../../type/index.js"; +import { World } from "../../ecs/index.js"; +import { updateAssets } from "../systems/index.js"; +import { Events } from "../../event/index.js"; +import { AssetLoadSuccess, AssetSaveSuccess, AssetLoadFail } from "../events/index.js"; class Text { inner = '' @@ -83,17 +87,57 @@ describe('Testing `AssetServer`', () => { }) test('Asset load state cycle.', () => { - todo() + const server = createServer() + const handle = server.load(Text,"/assets/text/sample.txt") + + deepStrictEqual(server.flushLoadRequests().length, 1) + deepStrictEqual(handle.id(), server.getAssetInfo(handle).id) }) - test('Asset save uses exporter.', async () => { - const server = createServer() - const assets = server.getAssets(typeid(Text)) - const handle = assets.add(new Text('hello')) + test('Asset load system parses and stores the asset.', async () => { + const world = createWorld() + const server = world.getResource(AssetServer) + const assets = world.getResourceByTypeId(typeidGeneric(Assets, [Text])) + const loadSuccessEvents = world.getResourceByTypeId(typeidGeneric(Events, [AssetLoadSuccess])) + const handle = server.load(Text,"/assets/text/sample.txt") const originalFetch = globalThis.fetch + let path + + globalThis.fetch = async (requestPath) => { + path = requestPath + + return /**@type {Response}*/({ + ok: true, + statusText: 'OK', + async text() { + return 'hello' + } + }) + } + + try { + await updateAssets(world) + loadSuccessEvents.clear() + deepStrictEqual(path, '/assets/text/sample.txt') + deepStrictEqual(assets.get(handle).inner, 'hello') + deepStrictEqual(loadSuccessEvents.count(), 1) + } finally { + globalThis.fetch = originalFetch + } + }) + + test('Asset save uses exporter through the asset system.', async () => { + const world = createWorld() + const server = world.getResource(AssetServer) + const assets = world.getResourceByTypeId(typeidGeneric(Assets, [Text])) + const saveSuccessEvents = world.getResourceByTypeId(typeidGeneric(Events, [AssetSaveSuccess])) + const handle = assets.add(new Text('hello')) + let body + const originalFetch = globalThis.fetch + globalThis.fetch = async (_path, init) => { body = init.body @@ -104,8 +148,11 @@ describe('Testing `AssetServer`', () => { } try { - await server.save(handle, '/assets/text/sample.txt') + server.save(handle, '/assets/text/sample.txt') + await updateAssets(world) + saveSuccessEvents.clear() deepStrictEqual(body, JSON.stringify({ inner: 'hello' })) + deepStrictEqual(saveSuccessEvents.count(), 1) } finally { globalThis.fetch = originalFetch } @@ -122,3 +169,20 @@ function createServer() { return server } + +function createWorld() { + const world = new World() + const assets = new Assets(Text) + const server = new AssetServer() + + world.setResource(server) + world.setResourceByTypeId(typeidGeneric(Assets, [Text]), assets) + world.setResourceByTypeId(typeidGeneric(Events, [AssetLoadSuccess]), new Events()) + world.setResourceByTypeId(typeidGeneric(Events, [AssetSaveSuccess]), new Events()) + world.setResourceByTypeId(typeidGeneric(Events, [AssetLoadFail]), new Events()) + server.registerAsset(assets) + server.registerParser(Text,new TextParser()) + server.registerExporter(Text,new TextExporter()) + + return world +} From 7a915d194c1215393c71ddaf3fefcd9eacdb75ae Mon Sep 17 00:00:00 2001 From: waynemwashuma <94756970+waynemwashuma@users.noreply.github.com> Date: Wed, 3 Jun 2026 02:52:28 +0300 Subject: [PATCH 2/3] Add second parameter to `Exporter.serialize()`/`Parser.parse()` to pass the type registry --- src/asset/core/exporter.js | 4 +++- src/asset/core/parser.js | 4 +++- src/asset/systems/server.js | 6 ++++-- src/asset/tests/assetserver.test.js | 8 ++++++-- src/audio/resources/parser.js | 4 +++- src/render-core/resources/image.js | 4 +++- 6 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/asset/core/exporter.js b/src/asset/core/exporter.js index 5c275030..d03cc92b 100644 --- a/src/asset/core/exporter.js +++ b/src/asset/core/exporter.js @@ -1,3 +1,4 @@ +/** @import { TypeRegistry } from '../../reflect/resources/index.js' */ /** @import { Constructor } from '../../type/index.js' */ import { throws } from '../../logger/index.js' @@ -22,9 +23,10 @@ export class Exporter { /** * @param {T} _asset + * @param {TypeRegistry} _typeRegistry * @returns {Promise} */ - async serialize(_asset) { + async serialize(_asset, _typeRegistry) { throws(`Implement the method \`serialize\` on \`${this.constructor.name}\``) return undefined diff --git a/src/asset/core/parser.js b/src/asset/core/parser.js index b78b2163..2dc66392 100644 --- a/src/asset/core/parser.js +++ b/src/asset/core/parser.js @@ -1,3 +1,4 @@ +/** @import { TypeRegistry } from '../../reflect/resources/index.js' */ /** @import { Constructor } from '../../type/index.js' */ import { throws } from '../../logger/index.js' @@ -22,9 +23,10 @@ export class Parser { /** * @param {Response} _response + * @param {TypeRegistry} _typeRegistry * @returns {Promise} */ - async parse(_response) { + async parse(_response, _typeRegistry) { throws(`Implement the method \`parse\` on \`${this.constructor.name}\``) return undefined diff --git a/src/asset/systems/server.js b/src/asset/systems/server.js index 6bd4dea5..310a30b6 100644 --- a/src/asset/systems/server.js +++ b/src/asset/systems/server.js @@ -3,6 +3,7 @@ /** @import { AssetDropped, AssetEvent, Parser, Exporter } from '../index.js' */ import { Events } from '../../event/index.js' import { typeidGeneric } from '../../type/index.js' +import { TypeRegistry } from '../../reflect/resources/index.js' import { Assets } from '../core/index.js' import { AssetServer, LoadState } from '../resources/index.js' import { AssetLoadFail, AssetLoadOperation, AssetLoadSuccess, AssetSaveSuccess } from '../events/index.js' @@ -61,6 +62,7 @@ export async function updateAssets(world) { const saveSuccessEvents = world.getResourceByTypeId(typeidGeneric(Events, [AssetSaveSuccess])) /** @type {Events} */ const loadFailEvents = world.getResourceByTypeId(typeidGeneric(Events, [AssetLoadFail])) + const typeRegistry = world.getResource(TypeRegistry) const loadRequests = server.flushLoadRequests() const saveRequests = server.flushSaveRequests() @@ -76,7 +78,7 @@ export async function updateAssets(world) { throw response.statusText } - const asset = await parser.parse(response) + const asset = await parser.parse(response, typeRegistry) if (!asset) { throw 'Could not parse the asset.' @@ -125,7 +127,7 @@ export async function updateAssets(world) { const exporter = server.getExporter(typeId, path) const response = await fetch(path, { method: 'POST', - body: await exporter.serialize(asset) + body: await exporter.serialize(asset, typeRegistry) }) if (!response.ok) { diff --git a/src/asset/tests/assetserver.test.js b/src/asset/tests/assetserver.test.js index d8e4e30f..5f6a68ec 100644 --- a/src/asset/tests/assetserver.test.js +++ b/src/asset/tests/assetserver.test.js @@ -6,6 +6,7 @@ import { World } from "../../ecs/index.js"; import { updateAssets } from "../systems/index.js"; import { Events } from "../../event/index.js"; import { AssetLoadSuccess, AssetSaveSuccess, AssetLoadFail } from "../events/index.js"; +import { TypeRegistry } from "../../reflect/resources/index.js"; class Text { inner = '' @@ -33,8 +34,9 @@ class TextParser extends Parser { /** * @param {Response} response + * @param {import("../../reflect/resources/index.js").TypeRegistry} _typeRegistry */ - async parse(response){ + async parse(response, _typeRegistry){ const text = await response.text() return new Text(text) } @@ -57,8 +59,9 @@ class TextExporter extends Exporter { /** * @param {Text} asset + * @param {import("../../reflect/resources/index.js").TypeRegistry} _typeRegistry */ - async serialize(asset){ + async serialize(asset, _typeRegistry){ return JSON.stringify(asset) } } @@ -176,6 +179,7 @@ function createWorld() { const server = new AssetServer() world.setResource(server) + world.setResource(new TypeRegistry()) world.setResourceByTypeId(typeidGeneric(Assets, [Text]), assets) world.setResourceByTypeId(typeidGeneric(Events, [AssetLoadSuccess]), new Events()) world.setResourceByTypeId(typeidGeneric(Events, [AssetSaveSuccess]), new Events()) diff --git a/src/audio/resources/parser.js b/src/audio/resources/parser.js index 0c88b333..fb343adc 100644 --- a/src/audio/resources/parser.js +++ b/src/audio/resources/parser.js @@ -1,3 +1,4 @@ +/** @import { TypeRegistry } from '../../reflect/resources/index.js' */ import { Parser } from '../../asset/index.js' import { Audio } from '../assets/index.js' @@ -25,8 +26,9 @@ export class AudioParser extends Parser { /** * @param {Response} response + * @param {TypeRegistry} _typeRegistry */ - async parse(response) { + async parse(response, _typeRegistry) { const raw = await response.arrayBuffer() const audiobuffer = await this.decoder.decodeAudioData(raw) diff --git a/src/render-core/resources/image.js b/src/render-core/resources/image.js index c9140258..46077e8e 100644 --- a/src/render-core/resources/image.js +++ b/src/render-core/resources/image.js @@ -1,3 +1,4 @@ +/** @import { TypeRegistry } from '../../reflect/resources/index.js' */ import { Parser } from '../../asset/core/parser.js' import { Image } from '../assets/index.js' import { Vector2 } from '../../math/index.js' @@ -19,8 +20,9 @@ export class ImageParser extends Parser { /** * @param {Response} response + * @param {TypeRegistry} _typeRegistry */ - async parse(response) { + async parse(response, _typeRegistry) { const raw = await response.arrayBuffer() const dimensions = await getDimensions(raw) From cd3d20b8e3bd40e1a4cb958488725d6798b3d601 Mon Sep 17 00:00:00 2001 From: waynemwashuma <94756970+waynemwashuma@users.noreply.github.com> Date: Wed, 3 Jun 2026 03:05:20 +0300 Subject: [PATCH 3/3] Lint files --- src/asset/resources/assetserver.js | 2 +- src/asset/systems/server.js | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/asset/resources/assetserver.js b/src/asset/resources/assetserver.js index e894c106..d94a440f 100644 --- a/src/asset/resources/assetserver.js +++ b/src/asset/resources/assetserver.js @@ -4,7 +4,6 @@ import { typeid } from '../../type/index.js' import { assert, warn } from '../../logger/index.js' import { getFileExtension, swapRemove } from '../../utils/index.js' import { Assets, Handle, Parser, Exporter } from '../core/index.js' -import { AssetLoadOperation } from '../events/index.js' /** * @typedef {number} ParserId @@ -278,6 +277,7 @@ export class AssetServer { path || '', 'The given asset handle does not have a registered asset path.' )) + return } diff --git a/src/asset/systems/server.js b/src/asset/systems/server.js index 310a30b6..886ef52a 100644 --- a/src/asset/systems/server.js +++ b/src/asset/systems/server.js @@ -56,10 +56,13 @@ export function registerAssetExporterOnAssetServer(type, exporter) { */ export async function updateAssets(world) { const server = world.getResource(AssetServer) + /** @type {Events} */ const loadSuccessEvents = world.getResourceByTypeId(typeidGeneric(Events, [AssetLoadSuccess])) + /** @type {Events} */ const saveSuccessEvents = world.getResourceByTypeId(typeidGeneric(Events, [AssetSaveSuccess])) + /** @type {Events} */ const loadFailEvents = world.getResourceByTypeId(typeidGeneric(Events, [AssetLoadFail])) const typeRegistry = world.getResource(TypeRegistry) @@ -98,7 +101,9 @@ export async function updateAssets(world) { if (typeof error === 'string') { message = error } else if (error instanceof Error) { - message = error.message + const { message: errorMessage } = error + + message = errorMessage } loadFailEvents.write(new AssetLoadFail(typeId, assetId, path, message)) @@ -141,7 +146,9 @@ export async function updateAssets(world) { if (typeof error === 'string') { message = error } else if (error instanceof Error) { - message = error.message + const { message: errorMessage } = error + + message = errorMessage } loadFailEvents.write(new AssetLoadFail(typeId, assetId, path, message, AssetLoadOperation.Saving))