import HTTP from "./HTTP"; import Dom from "./util/Dom"; import CredentialMode from "./CredentialMode"; /** * @classdesc リソースクラス * URLやDB、クラウドサービス等、各種リソースへのアクセスを同一インターフェースで提供することを目的とした抽象クラスです。 * 基本機能: * ・コンストラクタ等によりあらかじめURLやデータの位置を示すプロパティを設定 * ・load()によりリソースを読み込む * ・loadSubResource()によりサブリソースを読み込む * * @memberof mapray */ class Resource { /** * リソースを読み込みます。 */ async load( options={} ) { throw new Error( "Not Implemented" ); } /** * @summary リソースの読み込みをキャンセルできる場合はキャンセルします。 */ cancel() { } /** * @summary サブリソースをサポートするかを返します。 * @return {boolean} */ loadSubResourceSupported() { return false; } /** * @summary サブリソースを読み込みます。 * @param {string} url URL * @param {object} options * @param {mapray.Resource.ResourceType} [options.type] 返却するタイプを指定します。 * @return {object} options.type に応じた型で返却されます。 */ async loadSubResource( url, options={} ) { throw new Error( "Not Supported" ); } /** * @summary 関連リソースをサポートするかを返します。 * @return {boolean} */ resolveResourceSupported() { return false; } /** * @summary 関連リソースを読み込みます。 * @return {boolean} */ async resolveResource( url ) { throw new Error( "Not Supported" ); } /** * @summary リソース型 */ static get ResourceType() { return ResourceType; } } /** * @summary リソースの種類 * @enum {object} * @memberof mapray.ResourceType * @constant */ const ResourceType = { /** * JSON */ JSON: { id: "JSON" }, /** * バイナリ(ArrayBuffer) */ BINARY: { id: "BINARY" }, /** * 画像(Image) */ IMAGE: { id: "IMAGE" } }; /** * @classdesc URLリソースです。 */ class URLResource extends Resource { /** * @param {string} url * @param {object} [options] * @param {mapray.Resource.ResourceType} [options.type] * @param {mapray.Transform} [options.transform] */ constructor( url, options={} ) { super(); this._url = url; const index = url.lastIndexOf( '/' ); if ( index === -1 ) throw new Error( "invalid url" ); this._base_url = this._url.substr( 0, index + 1 ); this._type = options.type || "json"; this._transform = options.transform || defaultTransformCallback; this._abort_ctrl = new AbortController(); } /** * @summary リソースのurl * @type {string} */ get url() { return this._url; } /** * @summary このリソースを読み込みます。 * @param {object} [options] */ async load( options={} ) { return await this._loadURLResource( this._url, options.type || this._type, options ); } /** * @summary リソースの読み込みをキャンセルします。 */ cancel() { this._abort_ctrl.abort(); } /** * @summary このクラスでのデフォルト実装では、trueを返却します。 * @return {boolean} */ loadSubResourceSupported() { return true; } /** * @summary サブリソースを読み込みます。 * @param {string} subUrl URL * @param {object} options * @param {mapray.Resource.ResourceType} [options.type] 返却するタイプを指定します。 * @return {object} options.type に応じた型で返却されます。 */ async loadSubResource( subUrl, options={} ) { return await this._loadURLResource( Dom.resolveUrl( this._base_url, subUrl ), options.type, options ); } /** * @summary 関連リソースをサポートするかを返します。 * @return {boolean} */ resolveResourceSupported() { return true; } /** * @summary 関連リソースを読み込みます。 * @param {string} url * @return {Resource} */ resolveResource( sub_url ) { const url = Dom.resolveUrl( this._base_url, sub_url ); return new URLResource( url, { transform: this._transform }); } /** * @param {string} url * @param {mapray.Resource.ResourceType} [type] * @private */ async _loadURLResource( url, type, options={} ) { const tr = this._transform( url, type ); if ( type === ResourceType.IMAGE ) { return await Dom.loadImage( tr.url, tr ); } const http_option = this._make_fetch_params( tr ) || {}; if ( options.signal ) http_option.signal = options.signal; const response = await HTTP.get( tr.url, null, http_option ); if ( !response.ok ) throw new Error( response.statusText ); return ( type === ResourceType.JSON ? await response.json(): type === ResourceType.BINARY ? await response.arrayBuffer(): response ); } /** * fetch() の init 引数に与えるオブジェクトを生成 * @private */ _make_fetch_params( tr ) { var init = { signal: this._abort_ctrl.signal, credentials: (tr.credentials || CredentialMode.OMIT).credentials }; if ( tr.headers ) { init.headers = tr.headers; } return init; } } function defaultTransformCallback( url, type ) { return { url: url }; } export { URLResource, ResourceType }; export default Resource;