{"version":3,"file":"Resolver.mjs","sources":["../../src/resolver/Resolver.ts"],"sourcesContent":["import { utils } from '@pixi/core';\nimport { convertToList } from '../utils/convertToList';\nimport { createStringVariations } from '../utils/createStringVariations';\nimport { isSingleItem } from '../utils/isSingleItem';\n\nimport type {\n ArrayOr,\n AssetsBundle,\n AssetsManifest,\n AssetSrc,\n LoadParserName,\n ResolvedAsset,\n ResolvedSrc,\n UnresolvedAsset,\n UnresolvedAssetObject\n} from '../types';\nimport type { PreferOrder, ResolveURLParser } from './types';\n\nexport interface BundleIdentifierOptions\n{\n /** The character that is used to connect the bundleId and the assetId when generating a bundle asset id key */\n connector?: string;\n /**\n * A function that generates a bundle asset id key from a bundleId and an assetId\n * @param bundleId - the bundleId\n * @param assetId - the assetId\n * @returns the bundle asset id key\n */\n createBundleAssetId?: (bundleId: string, assetId: string) => string;\n /**\n * A function that generates an assetId from a bundle asset id key. This is the reverse of generateBundleAssetId\n * @param bundleId - the bundleId\n * @param assetBundleId - the bundle asset id key\n * @returns the assetId\n */\n extractAssetIdFromBundle?: (bundleId: string, assetBundleId: string) => string;\n}\n\n/**\n * A class that is responsible for resolving mapping asset URLs to keys.\n * At its most basic it can be used for Aliases:\n *\n * ```js\n * resolver.add('foo', 'bar');\n * resolver.resolveUrl('foo') // => 'bar'\n * ```\n *\n * It can also be used to resolve the most appropriate asset for a given URL:\n *\n * ```js\n * resolver.prefer({\n * params: {\n * format: 'webp',\n * resolution: 2,\n * }\n * });\n *\n * resolver.add('foo', ['bar@2x.webp', 'bar@2x.png', 'bar.webp', 'bar.png']);\n *\n * resolver.resolveUrl('foo') // => 'bar@2x.webp'\n * ```\n * Other features include:\n * - Ability to process a manifest file to get the correct understanding of how to resolve all assets\n * - Ability to add custom parsers for specific file types\n * - Ability to add custom prefer rules\n *\n * This class only cares about the URL, not the loading of the asset itself.\n *\n * It is not intended that this class is created by developers - its part of the Asset class\n * This is the third major system of PixiJS' main Assets class\n * @memberof PIXI\n */\nexport class Resolver\n{\n private _defaultBundleIdentifierOptions: Required = {\n connector: '-',\n createBundleAssetId: (bundleId, assetId) =>\n `${bundleId}${this._bundleIdConnector}${assetId}`,\n extractAssetIdFromBundle: (bundleId, assetBundleId) =>\n assetBundleId.replace(`${bundleId}${this._bundleIdConnector}`, ''),\n };\n\n /** The character that is used to connect the bundleId and the assetId when generating a bundle asset id key */\n private _bundleIdConnector = this._defaultBundleIdentifierOptions.connector;\n\n /**\n * A function that generates a bundle asset id key from a bundleId and an assetId\n * @param bundleId - the bundleId\n * @param assetId - the assetId\n * @returns the bundle asset id key\n */\n private _createBundleAssetId: (\n bundleId: string,\n assetId: string\n ) => string = this._defaultBundleIdentifierOptions.createBundleAssetId;\n\n /**\n * A function that generates an assetId from a bundle asset id key. This is the reverse of generateBundleAssetId\n * @param bundleId - the bundleId\n * @param assetBundleId - the bundle asset id key\n * @returns the assetId\n */\n private _extractAssetIdFromBundle: (\n bundleId: string,\n assetBundleId: string\n ) => string = this._defaultBundleIdentifierOptions.extractAssetIdFromBundle;\n\n private _assetMap: Record = {};\n private _preferredOrder: PreferOrder[] = [];\n private _parsers: ResolveURLParser[] = [];\n\n private _resolverHash: Record = {};\n private _rootPath: string;\n private _basePath: string;\n private _manifest: AssetsManifest;\n private _bundles: Record = {};\n private _defaultSearchParams: string;\n\n /**\n * Override how the resolver deals with generating bundle ids.\n * must be called before any bundles are added\n * @param bundleIdentifier - the bundle identifier options\n */\n public setBundleIdentifier(bundleIdentifier: BundleIdentifierOptions): void\n {\n this._bundleIdConnector = bundleIdentifier.connector ?? this._bundleIdConnector;\n this._createBundleAssetId = bundleIdentifier.createBundleAssetId ?? this._createBundleAssetId;\n this._extractAssetIdFromBundle = bundleIdentifier.extractAssetIdFromBundle ?? this._extractAssetIdFromBundle;\n\n if (this._extractAssetIdFromBundle('foo', this._createBundleAssetId('foo', 'bar')) !== 'bar')\n {\n throw new Error('[Resolver] GenerateBundleAssetId are not working correctly');\n }\n }\n\n /**\n * Let the resolver know which assets you prefer to use when resolving assets.\n * Multiple prefer user defined rules can be added.\n * @example\n * resolver.prefer({\n * // first look for something with the correct format, and then then correct resolution\n * priority: ['format', 'resolution'],\n * params:{\n * format:'webp', // prefer webp images\n * resolution: 2, // prefer a resolution of 2\n * }\n * })\n * resolver.add('foo', ['bar@2x.webp', 'bar@2x.png', 'bar.webp', 'bar.png']);\n * resolver.resolveUrl('foo') // => 'bar@2x.webp'\n * @param preferOrders - the prefer options\n */\n public prefer(...preferOrders: PreferOrder[]): void\n {\n preferOrders.forEach((prefer) =>\n {\n this._preferredOrder.push(prefer);\n\n if (!prefer.priority)\n {\n // generate the priority based on the order of the object\n prefer.priority = Object.keys(prefer.params);\n }\n });\n\n this._resolverHash = {};\n }\n\n /**\n * Set the base path to prepend to all urls when resolving\n * @example\n * resolver.basePath = 'https://home.com/';\n * resolver.add('foo', 'bar.ong');\n * resolver.resolveUrl('foo', 'bar.png'); // => 'https://home.com/bar.png'\n * @param basePath - the base path to use\n */\n public set basePath(basePath: string)\n {\n this._basePath = basePath;\n }\n\n public get basePath(): string\n {\n return this._basePath;\n }\n\n /**\n * Set the root path for root-relative URLs. By default the `basePath`'s root is used. If no `basePath` is set, then the\n * default value for browsers is `window.location.origin`\n * @example\n * // Application hosted on https://home.com/some-path/index.html\n * resolver.basePath = 'https://home.com/some-path/';\n * resolver.rootPath = 'https://home.com/';\n * resolver.add('foo', '/bar.png');\n * resolver.resolveUrl('foo', '/bar.png'); // => 'https://home.com/bar.png'\n * @param rootPath - the root path to use\n */\n public set rootPath(rootPath: string)\n {\n this._rootPath = rootPath;\n }\n\n public get rootPath(): string\n {\n return this._rootPath;\n }\n\n /**\n * All the active URL parsers that help the parser to extract information and create\n * an asset object-based on parsing the URL itself.\n *\n * Can be added using the extensions API\n * @example\n * resolver.add('foo', [\n * {\n * resolution: 2,\n * format: 'png',\n * src: 'image@2x.png',\n * },\n * {\n * resolution:1,\n * format:'png',\n * src: 'image.png',\n * },\n * ]);\n *\n * // With a url parser the information such as resolution and file format could extracted from the url itself:\n * extensions.add({\n * extension: ExtensionType.ResolveParser,\n * test: loadTextures.test, // test if url ends in an image\n * parse: (value: string) =>\n * ({\n * resolution: parseFloat(settings.RETINA_PREFIX.exec(value)?.[1] ?? '1'),\n * format: value.split('.').pop(),\n * src: value,\n * }),\n * });\n *\n * // Now resolution and format can be extracted from the url\n * resolver.add('foo', [\n * 'image@2x.png',\n * 'image.png',\n * ]);\n */\n public get parsers(): ResolveURLParser[]\n {\n return this._parsers;\n }\n\n /** Used for testing, this resets the resolver to its initial state */\n public reset(): void\n {\n this.setBundleIdentifier(this._defaultBundleIdentifierOptions);\n\n this._assetMap = {};\n this._preferredOrder = [];\n // Do not reset this._parsers\n\n this._resolverHash = {};\n this._rootPath = null;\n this._basePath = null;\n this._manifest = null;\n this._bundles = {};\n this._defaultSearchParams = null;\n }\n\n /**\n * Sets the default URL search parameters for the URL resolver. The urls can be specified as a string or an object.\n * @param searchParams - the default url parameters to append when resolving urls\n */\n public setDefaultSearchParams(searchParams: string | Record): void\n {\n if (typeof searchParams === 'string')\n {\n this._defaultSearchParams = searchParams;\n }\n else\n {\n const queryValues = searchParams as Record;\n\n this._defaultSearchParams = Object.keys(queryValues)\n .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(queryValues[key])}`)\n .join('&');\n }\n }\n\n /**\n * Returns the aliases for a given asset\n * @param asset - the asset to get the aliases for\n */\n public getAlias(asset: UnresolvedAsset): string[]\n {\n const { alias, name, src, srcs } = asset;\n const aliasesToUse = convertToList>(\n alias || name || src || srcs, (value: string | AssetSrc) =>\n {\n if (typeof value === 'string') return value;\n\n if (Array.isArray(value)) return value.map((v) => (v as ResolvedSrc)?.src ?? (v as ResolvedSrc)?.srcs ?? v);\n\n if (value?.src || value?.srcs) return value.src ?? value.srcs;\n\n return value;\n }, true) as string[];\n\n return aliasesToUse;\n }\n\n /**\n * Add a manifest to the asset resolver. This is a nice way to add all the asset information in one go.\n * generally a manifest would be built using a tool.\n * @param manifest - the manifest to add to the resolver\n */\n public addManifest(manifest: AssetsManifest): void\n {\n if (this._manifest)\n {\n if (process.env.DEBUG)\n {\n console.warn('[Resolver] Manifest already exists, this will be overwritten');\n }\n }\n\n this._manifest = manifest;\n\n manifest.bundles.forEach((bundle) =>\n {\n this.addBundle(bundle.name, bundle.assets);\n });\n }\n\n /**\n * This adds a bundle of assets in one go so that you can resolve them as a group.\n * For example you could add a bundle for each screen in you pixi app\n * @example\n * resolver.addBundle('animals', {\n * bunny: 'bunny.png',\n * chicken: 'chicken.png',\n * thumper: 'thumper.png',\n * });\n *\n * const resolvedAssets = await resolver.resolveBundle('animals');\n * @param bundleId - The id of the bundle to add\n * @param assets - A record of the asset or assets that will be chosen from when loading via the specified key\n */\n public addBundle(bundleId: string, assets: AssetsBundle['assets']): void\n {\n const assetNames: string[] = [];\n\n // when storing keys against a bundle we prepend the bundleId to each asset key\n // and pass it through as an additional alias for the asset\n // this keeps clashing ids separate on a per-bundle basis\n // you can also resolve a file using the bundleId-assetId syntax\n if (Array.isArray(assets))\n {\n assets.forEach((asset) =>\n {\n const srcs = asset.src ?? asset.srcs;\n const aliases = asset.alias ?? asset.name;\n let ids: string[];\n\n if (typeof aliases === 'string')\n {\n const bundleAssetId = this._createBundleAssetId(bundleId, aliases);\n\n assetNames.push(bundleAssetId);\n ids = [aliases, bundleAssetId];\n }\n else\n {\n const bundleIds = aliases.map((name) => this._createBundleAssetId(bundleId, name));\n\n assetNames.push(...bundleIds);\n ids = [...aliases, ...bundleIds];\n }\n\n this.add({\n ...asset,\n ...{\n alias: ids,\n src: srcs,\n }\n });\n });\n }\n else\n {\n Object.keys(assets).forEach((key) =>\n {\n const aliases: string[] = [key, this._createBundleAssetId(bundleId, key)];\n\n if (typeof assets[key] === 'string')\n {\n this.add({\n alias: aliases,\n src: assets[key] as string,\n });\n }\n else if (Array.isArray(assets[key]))\n {\n this.add({\n alias: aliases,\n src: assets[key] as string[],\n });\n }\n else\n {\n const asset = assets[key] as UnresolvedAssetObject;\n const assetSrc = asset.src ?? asset.srcs;\n\n this.add({\n ...asset,\n ...{\n alias: aliases,\n src: Array.isArray(assetSrc) ? assetSrc : [assetSrc],\n }\n });\n }\n\n assetNames.push(...aliases);\n });\n }\n\n this._bundles[bundleId] = assetNames;\n }\n\n /** @deprecated */\n public add(a: ArrayOr, s?: AssetSrc, d?: unknown, f?: string, lp?: LoadParserName): void;\n /**\n * Tells the resolver what keys are associated with witch asset.\n * The most important thing the resolver does\n * @example\n * // Single key, single asset:\n * resolver.add({alias: 'foo', src: 'bar.png');\n * resolver.resolveUrl('foo') // => 'bar.png'\n *\n * // Multiple keys, single asset:\n * resolver.add({alias: ['foo', 'boo'], src: 'bar.png'});\n * resolver.resolveUrl('foo') // => 'bar.png'\n * resolver.resolveUrl('boo') // => 'bar.png'\n *\n * // Multiple keys, multiple assets:\n * resolver.add({alias: ['foo', 'boo'], src: ['bar.png', 'bar.webp']});\n * resolver.resolveUrl('foo') // => 'bar.png'\n *\n * // Add custom data attached to the resolver\n * Resolver.add({\n * alias: 'bunnyBooBooSmooth',\n * src: 'bunny{png,webp}',\n * data: { scaleMode:SCALE_MODES.NEAREST }, // Base texture options\n * });\n *\n * resolver.resolve('bunnyBooBooSmooth') // => { src: 'bunny.png', data: { scaleMode: SCALE_MODES.NEAREST } }\n * @param data - the data to add to the resolver\n * @param data.aliases - the key or keys that you will reference when loading this asset\n * @param data.srcs - the asset or assets that will be chosen from when loading via the specified key\n * @param data.data - asset-specific data that will be passed to the loaders\n * - Useful if you want to initiate loaded objects with specific data\n * @param data.format - the format of the asset\n * @param data.loadParser - the name of the load parser to use\n */\n public add(data:(ArrayOr)): void;\n public add(\n aliases: ArrayOr | (ArrayOr),\n srcs?: AssetSrc,\n data?: unknown,\n format?: string,\n loadParser?: LoadParserName\n ): void\n {\n const assets: UnresolvedAsset[] = [];\n\n if (typeof aliases === 'string' || (Array.isArray(aliases) && typeof aliases[0] === 'string'))\n {\n if (process.env.DEBUG)\n {\n // eslint-disable-next-line max-len\n utils.deprecation('7.2.0', `Assets.add now uses an object instead of individual parameters.\\nPlease use Assets.add({ alias, src, data, format, loadParser }) instead.`);\n }\n\n assets.push({ alias: aliases as ArrayOr, src: srcs, data, format, loadParser });\n }\n else if (Array.isArray(aliases))\n {\n assets.push(...(aliases as UnresolvedAsset[]));\n }\n else\n {\n assets.push(aliases as UnresolvedAsset);\n }\n\n let keyCheck: (key: string) => void;\n\n if (process.env.DEBUG)\n {\n keyCheck = (key: string) =>\n {\n if (this.hasKey(key))\n {\n console.warn(`[Resolver] already has key: ${key} overwriting`);\n }\n };\n }\n\n const assetArray = convertToList(assets);\n\n // loop through all the assets and generate a resolve asset for each src\n assetArray.forEach((asset) =>\n {\n const { src, srcs } = asset;\n let { data, format, loadParser } = asset;\n\n // src can contain an unresolved asset itself\n // so we need to merge that data with the current asset\n // we dont need to create string variations for the src if it is a ResolvedAsset\n const srcsToUse: (string | ResolvedSrc)[][] = convertToList(src || srcs).map((src) =>\n {\n if (typeof src === 'string')\n { return createStringVariations(src); }\n\n return Array.isArray(src) ? src : [src];\n });\n\n const aliasesToUse = this.getAlias(asset);\n\n if (process.env.DEBUG)\n {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n Array.isArray(aliasesToUse) ? aliasesToUse.forEach(keyCheck) : keyCheck(aliasesToUse);\n }\n\n // loop through all the srcs and generate a resolve asset for each src\n const resolvedAssets: ResolvedAsset[] = [];\n\n srcsToUse.forEach((srcs) =>\n {\n srcs.forEach((src) =>\n {\n let formattedAsset = {} as ResolvedAsset;\n\n if (typeof src !== 'object')\n {\n formattedAsset.src = src;\n // first see if it contains any {} tags...\n for (let i = 0; i < this._parsers.length; i++)\n {\n const parser = this._parsers[i];\n\n if (parser.test(src))\n {\n formattedAsset = parser.parse(src);\n break;\n }\n }\n }\n else\n {\n data = src.data ?? data;\n format = src.format ?? format;\n loadParser = src.loadParser ?? loadParser;\n formattedAsset = {\n ...formattedAsset,\n ...src,\n };\n }\n\n // check if aliases is undefined\n if (!aliasesToUse)\n {\n throw new Error(`[Resolver] alias is undefined for this asset: ${formattedAsset.src}`);\n }\n\n formattedAsset = this.buildResolvedAsset(formattedAsset, {\n aliases: aliasesToUse,\n data,\n format,\n loadParser,\n });\n\n resolvedAssets.push(formattedAsset);\n });\n });\n\n aliasesToUse.forEach((alias) =>\n {\n this._assetMap[alias] = resolvedAssets;\n });\n });\n }\n\n // TODO: this needs an overload like load did in Assets\n /**\n * If the resolver has had a manifest set via setManifest, this will return the assets urls for\n * a given bundleId or bundleIds.\n * @example\n * // Manifest Example\n * const manifest = {\n * bundles: [\n * {\n * name: 'load-screen',\n * assets: [\n * {\n * alias: 'background',\n * src: 'sunset.png',\n * },\n * {\n * alias: 'bar',\n * src: 'load-bar.{png,webp}',\n * },\n * ],\n * },\n * {\n * name: 'game-screen',\n * assets: [\n * {\n * alias: 'character',\n * src: 'robot.png',\n * },\n * {\n * alias: 'enemy',\n * src: 'bad-guy.png',\n * },\n * ],\n * },\n * ]\n * };\n *\n * resolver.setManifest(manifest);\n * const resolved = resolver.resolveBundle('load-screen');\n * @param bundleIds - The bundle ids to resolve\n * @returns All the bundles assets or a hash of assets for each bundle specified\n */\n public resolveBundle(bundleIds: ArrayOr):\n Record | Record>\n {\n const singleAsset = isSingleItem(bundleIds);\n\n bundleIds = convertToList(bundleIds);\n\n const out: Record> = {};\n\n bundleIds.forEach((bundleId) =>\n {\n const assetNames = this._bundles[bundleId];\n\n if (assetNames)\n {\n const results = this.resolve(assetNames) as Record;\n\n const assets: Record = {};\n\n for (const key in results)\n {\n const asset = results[key];\n\n assets[this._extractAssetIdFromBundle(bundleId, key)] = asset;\n }\n\n out[bundleId] = assets;\n }\n });\n\n return singleAsset ? out[bundleIds[0]] : out;\n }\n\n /**\n * Does exactly what resolve does, but returns just the URL rather than the whole asset object\n * @param key - The key or keys to resolve\n * @returns - The URLs associated with the key(s)\n */\n public resolveUrl(key: ArrayOr): string | Record\n {\n const result = this.resolve(key as string) as ResolvedAsset | Record;\n\n if (typeof key !== 'string')\n {\n const out: Record = {};\n\n for (const i in result)\n {\n out[i] = (result as Record)[i].src;\n }\n\n return out;\n }\n\n return (result as ResolvedAsset).src;\n }\n\n /**\n * Resolves each key in the list to an asset object.\n * Another key function of the resolver! After adding all the various key/asset pairs. this will run the logic\n * of finding which asset to return based on any preferences set using the `prefer` function\n * by default the same key passed in will be returned if nothing is matched by the resolver.\n * @example\n * resolver.add('boo', 'bunny.png');\n *\n * resolver.resolve('boo') // => { src: 'bunny.png' }\n *\n * // Will return the same string as no key was added for this value..\n * resolver.resolve('another-thing.png') // => { src: 'another-thing.png' }\n * @param keys - key or keys to resolve\n * @returns - the resolve asset or a hash of resolve assets for each key specified\n */\n public resolve(keys: string): ResolvedAsset;\n public resolve(keys: string[]): Record;\n public resolve(keys: ArrayOr): ResolvedAsset | Record\n {\n const singleAsset = isSingleItem(keys);\n\n keys = convertToList(keys);\n\n const result: Record = {};\n\n keys.forEach((key) =>\n {\n if (!this._resolverHash[key])\n {\n if (this._assetMap[key])\n {\n let assets = this._assetMap[key];\n const bestAsset = assets[0];\n const preferredOrder = this._getPreferredOrder(assets);\n\n preferredOrder?.priority.forEach((priorityKey) =>\n {\n preferredOrder.params[priorityKey].forEach((value: unknown) =>\n {\n const filteredAssets = assets.filter((asset) =>\n {\n if (asset[priorityKey as keyof ResolvedAsset])\n {\n return asset[priorityKey as keyof ResolvedAsset] === value;\n }\n\n return false;\n });\n\n if (filteredAssets.length)\n {\n assets = filteredAssets;\n }\n });\n });\n\n this._resolverHash[key] = (assets[0] ?? bestAsset);\n }\n else\n {\n this._resolverHash[key] = this.buildResolvedAsset({\n alias: [key],\n src: key,\n }, {});\n }\n }\n\n result[key] = this._resolverHash[key];\n });\n\n return singleAsset ? result[keys[0]] : result;\n }\n\n /**\n * Checks if an asset with a given key exists in the resolver\n * @param key - The key of the asset\n */\n public hasKey(key: string): boolean\n {\n return !!this._assetMap[key];\n }\n\n /**\n * Checks if a bundle with the given key exists in the resolver\n * @param key - The key of the bundle\n */\n public hasBundle(key: string): boolean\n {\n return !!this._bundles[key];\n }\n\n /**\n * Internal function for figuring out what prefer criteria an asset should use.\n * @param assets\n */\n private _getPreferredOrder(assets: ResolvedAsset[]): PreferOrder\n {\n for (let i = 0; i < assets.length; i++)\n {\n const asset = assets[0];\n\n const preferred = this._preferredOrder.find((preference: PreferOrder) =>\n preference.params.format.includes(asset.format));\n\n if (preferred)\n {\n return preferred;\n }\n }\n\n return this._preferredOrder[0];\n }\n\n /**\n * Appends the default url parameters to the url\n * @param url - The url to append the default parameters to\n * @returns - The url with the default parameters appended\n */\n private _appendDefaultSearchParams(url: string): string\n {\n if (!this._defaultSearchParams) return url;\n\n const paramConnector = (/\\?/).test(url) ? '&' : '?';\n\n return `${url}${paramConnector}${this._defaultSearchParams}`;\n }\n\n private buildResolvedAsset(formattedAsset: ResolvedAsset, data?: {\n aliases?: string[],\n data?: Record\n loadParser?: string,\n format?: string,\n }): ResolvedAsset\n {\n const { aliases, data: assetData, loadParser, format } = data;\n\n if (this._basePath || this._rootPath)\n {\n formattedAsset.src = utils.path.toAbsolute(formattedAsset.src, this._basePath, this._rootPath);\n }\n\n formattedAsset.alias = aliases ?? formattedAsset.alias ?? [formattedAsset.src];\n formattedAsset.src = this._appendDefaultSearchParams(formattedAsset.src);\n formattedAsset.data = { ...assetData || {}, ...formattedAsset.data };\n formattedAsset.loadParser = loadParser ?? formattedAsset.loadParser;\n formattedAsset.format = format ?? formattedAsset.format ?? utils.path.extname(formattedAsset.src).slice(1);\n formattedAsset.srcs = formattedAsset.src;\n formattedAsset.name = formattedAsset.alias;\n\n return formattedAsset;\n }\n}\n"],"names":["srcs","data","format","loadParser","src"],"mappings":"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"}