@loaders.gl/core 4.2.0-alpha.6 → 4.2.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/dist.dev.js +1941 -1894
  2. package/dist/dist.min.js +3 -3
  3. package/dist/index.cjs +110 -68
  4. package/dist/index.cjs.map +4 -4
  5. package/dist/index.d.ts +1 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1 -0
  8. package/dist/lib/api/select-loader.d.ts.map +1 -1
  9. package/dist/lib/api/select-loader.js +3 -2
  10. package/dist/lib/fetch/fetch-error-message.d.ts.map +1 -1
  11. package/dist/lib/fetch/fetch-error-message.js +2 -0
  12. package/dist/lib/fetch/fetch-error.d.ts +14 -0
  13. package/dist/lib/fetch/fetch-error.d.ts.map +1 -0
  14. package/dist/lib/fetch/fetch-error.js +17 -0
  15. package/dist/lib/fetch/fetch-file.d.ts.map +1 -1
  16. package/dist/lib/fetch/fetch-file.js +1 -0
  17. package/dist/lib/init.js +1 -1
  18. package/dist/lib/loader-utils/option-utils.d.ts +1 -1
  19. package/dist/lib/loader-utils/option-utils.d.ts.map +1 -1
  20. package/dist/lib/loader-utils/option-utils.js +3 -0
  21. package/dist/lib/utils/mime-type-utils.d.ts +8 -0
  22. package/dist/lib/utils/mime-type-utils.d.ts.map +1 -1
  23. package/dist/lib/utils/mime-type-utils.js +13 -0
  24. package/dist/lib/utils/response-utils.d.ts.map +1 -1
  25. package/dist/lib/utils/response-utils.js +16 -10
  26. package/dist/lib/utils/url-utils.d.ts +1 -0
  27. package/dist/lib/utils/url-utils.d.ts.map +1 -1
  28. package/dist/lib/utils/url-utils.js +8 -0
  29. package/dist/null-loader.d.ts +40 -3
  30. package/dist/null-loader.d.ts.map +1 -1
  31. package/dist/null-loader.js +5 -1
  32. package/dist/null-worker-node.js +3 -1
  33. package/dist/null-worker.js +3 -1
  34. package/package.json +5 -5
  35. package/src/index.ts +1 -0
  36. package/src/lib/api/select-loader.ts +3 -2
  37. package/src/lib/fetch/fetch-error-message.ts +2 -0
  38. package/src/lib/fetch/fetch-error.ts +18 -0
  39. package/src/lib/fetch/fetch-file.ts +1 -0
  40. package/src/lib/loader-utils/option-utils.ts +3 -1
  41. package/src/lib/utils/mime-type-utils.ts +14 -0
  42. package/src/lib/utils/response-utils.ts +19 -11
  43. package/src/lib/utils/url-utils.ts +9 -0
  44. package/src/null-loader.ts +9 -4
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export type { Loader, LoaderWithParser, LoaderContext, LoaderOptions, Writer, WriterOptions, DataType, SyncDataType, BatchableDataType, ReadableFile, WritableFile, Stat, FileSystem, RandomAccessFileSystem } from '@loaders.gl/loader-utils';
2
2
  export { fetchFile } from "./lib/fetch/fetch-file.js";
3
+ export { FetchError } from "./lib/fetch/fetch-error.js";
3
4
  export { readArrayBuffer } from "./lib/fetch/read-array-buffer.js";
4
5
  export { setLoaderOptions, getLoaderOptions } from "./lib/api/loader-options.js";
5
6
  export { registerLoaders } from "./lib/api/register-loaders.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,YAAY,EACV,MAAM,EACN,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,MAAM,EACN,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,IAAI,EACJ,UAAU,EACV,sBAAsB,EACvB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAC,SAAS,EAAC,kCAA+B;AAEjD,OAAO,EAAC,eAAe,EAAC,yCAAsC;AAK9D,OAAO,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,oCAAiC;AAC5E,OAAO,EAAC,eAAe,EAAC,sCAAmC;AAC3D,OAAO,EAAC,YAAY,EAAE,gBAAgB,EAAC,mCAAgC;AAGvE,OAAO,EAAC,KAAK,EAAC,2BAAwB;AACtC,OAAO,EAAC,SAAS,EAAC,gCAA6B;AAC/C,OAAO,EAAC,cAAc,EAAC,sCAAmC;AAE1D,OAAO,EAAC,IAAI,EAAC,0BAAuB;AACpC,OAAO,EAAC,aAAa,EAAC,qCAAkC;AAGxD,OAAO,EAAC,WAAW,EAAE,iBAAiB,EAAE,oBAAoB,EAAC,kCAA+B;AAC5F,OAAO,EAAC,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,cAAc,EAAC,4BAAyB;AACrF,OAAO,EAAC,UAAU,EAAE,cAAc,EAAC,4BAAyB;AAG5D,OAAO,EAAC,aAAa,EAAE,aAAa,EAAE,WAAW,EAAC,MAAM,0BAA0B,CAAC;AACnF,OAAO,EAAC,gBAAgB,EAAC,MAAM,0BAA0B,CAAC;AAG1D,OAAO,EAAC,YAAY,EAAC,mDAAgD;AACrE,OAAO,EAAC,UAAU,EAAC,+CAA4C;AAG/D,OAAO,EAAC,gBAAgB,EAAE,UAAU,EAAC,yBAAsB;AAC3D,OAAO,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAC;AAGpD,OAAO,EAAC,aAAa,IAAI,cAAc,EAAC,yCAAsC;AAC9E,OAAO,EAAC,iBAAiB,IAAI,kBAAkB,EAAC,gDAA6C;AAG7F,OAAO,EAAC,kBAAkB,EAAC,sCAAmC;AAM9D,OAAO,EAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAC7F,OAAO,EAAC,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAC,OAAO,EAAE,4BAA4B,EAAC,MAAM,0BAA0B,CAAC;AAE/E,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,wBAAwB,EACzB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,YAAY,EACZ,SAAS,EACT,UAAU,EACV,eAAe,EACf,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EACjB,sCAAmC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,YAAY,EACV,MAAM,EACN,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,MAAM,EACN,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,IAAI,EACJ,UAAU,EACV,sBAAsB,EACvB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAC,SAAS,EAAC,kCAA+B;AACjD,OAAO,EAAC,UAAU,EAAC,mCAAgC;AAEnD,OAAO,EAAC,eAAe,EAAC,yCAAsC;AAK9D,OAAO,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,oCAAiC;AAC5E,OAAO,EAAC,eAAe,EAAC,sCAAmC;AAC3D,OAAO,EAAC,YAAY,EAAE,gBAAgB,EAAC,mCAAgC;AAGvE,OAAO,EAAC,KAAK,EAAC,2BAAwB;AACtC,OAAO,EAAC,SAAS,EAAC,gCAA6B;AAC/C,OAAO,EAAC,cAAc,EAAC,sCAAmC;AAE1D,OAAO,EAAC,IAAI,EAAC,0BAAuB;AACpC,OAAO,EAAC,aAAa,EAAC,qCAAkC;AAGxD,OAAO,EAAC,WAAW,EAAE,iBAAiB,EAAE,oBAAoB,EAAC,kCAA+B;AAC5F,OAAO,EAAC,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,cAAc,EAAC,4BAAyB;AACrF,OAAO,EAAC,UAAU,EAAE,cAAc,EAAC,4BAAyB;AAG5D,OAAO,EAAC,aAAa,EAAE,aAAa,EAAE,WAAW,EAAC,MAAM,0BAA0B,CAAC;AACnF,OAAO,EAAC,gBAAgB,EAAC,MAAM,0BAA0B,CAAC;AAG1D,OAAO,EAAC,YAAY,EAAC,mDAAgD;AACrE,OAAO,EAAC,UAAU,EAAC,+CAA4C;AAG/D,OAAO,EAAC,gBAAgB,EAAE,UAAU,EAAC,yBAAsB;AAC3D,OAAO,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAC;AAGpD,OAAO,EAAC,aAAa,IAAI,cAAc,EAAC,yCAAsC;AAC9E,OAAO,EAAC,iBAAiB,IAAI,kBAAkB,EAAC,gDAA6C;AAG7F,OAAO,EAAC,kBAAkB,EAAC,sCAAmC;AAM9D,OAAO,EAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAC7F,OAAO,EAAC,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAC,OAAO,EAAE,4BAA4B,EAAC,MAAM,0BAA0B,CAAC;AAE/E,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,EAChB,wBAAwB,EACzB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,YAAY,EACZ,SAAS,EACT,UAAU,EACV,eAAe,EACf,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EACjB,sCAAmC"}
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
  // FILE READING AND WRITING
5
5
  export { fetchFile } from "./lib/fetch/fetch-file.js";
6
+ export { FetchError } from "./lib/fetch/fetch-error.js";
6
7
  export { readArrayBuffer } from "./lib/fetch/read-array-buffer.js";
7
8
  // export {readFileSync} from './lib/fetch/read-file';
8
9
  // export {writeFile, writeFileSync} from './lib/fetch/write-file';
@@ -1 +1 @@
1
- {"version":3,"file":"select-loader.d.ts","sourceRoot":"","sources":["../../../src/lib/api/select-loader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,aAAa,EAAE,aAAa,EAAE,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAgBnF;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,WAAW,GAAG,MAAM,EAC5C,OAAO,GAAE,MAAM,EAAE,GAAG,MAAW,EAC/B,OAAO,CAAC,EAAE,aAAa,EACvB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwBxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,WAAW,GAAG,MAAM,EAC5C,OAAO,GAAE,MAAM,EAAE,GAAG,MAAW,EAC/B,OAAO,CAAC,EAAE,aAAa,EACvB,OAAO,CAAC,EAAE,aAAa,GACtB,MAAM,GAAG,IAAI,CAmCf"}
1
+ {"version":3,"file":"select-loader.d.ts","sourceRoot":"","sources":["../../../src/lib/api/select-loader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,aAAa,EAAE,aAAa,EAAE,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAiBnF;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,WAAW,GAAG,MAAM,EAC5C,OAAO,GAAE,MAAM,EAAE,GAAG,MAAW,EAC/B,OAAO,CAAC,EAAE,aAAa,EACvB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwBxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,QAAQ,GAAG,IAAI,GAAG,WAAW,GAAG,MAAM,EAC5C,OAAO,GAAE,MAAM,EAAE,GAAG,MAAW,EAC/B,OAAO,CAAC,EAAE,aAAa,EACvB,OAAO,CAAC,EAAE,aAAa,GACtB,MAAM,GAAG,IAAI,CAmCf"}
@@ -5,6 +5,7 @@ import { compareArrayBuffers, path } from '@loaders.gl/loader-utils';
5
5
  import { normalizeLoader } from "../loader-utils/normalize-loader.js";
6
6
  import { log } from "../utils/log.js";
7
7
  import { getResourceUrl, getResourceMIMEType } from "../utils/resource-utils.js";
8
+ import { compareMIMETypes } from "../utils/mime-type-utils.js";
8
9
  import { getRegisteredLoaders } from "./register-loaders.js";
9
10
  import { isBlob } from "../../javascript-utils/is-type.js";
10
11
  import { stripQueryString } from "../utils/url-utils.js";
@@ -166,12 +167,12 @@ function findLoaderByExtension(loaders, extension) {
166
167
  }
167
168
  function findLoaderByMIMEType(loaders, mimeType) {
168
169
  for (const loader of loaders) {
169
- if (loader.mimeTypes && loader.mimeTypes.includes(mimeType)) {
170
+ if (loader.mimeTypes?.some((mimeType1) => compareMIMETypes(mimeType, mimeType1))) {
170
171
  return loader;
171
172
  }
172
173
  // Support referring to loaders using the "unregistered tree"
173
174
  // https://en.wikipedia.org/wiki/Media_type#Unregistered_tree
174
- if (mimeType === `application/x.${loader.id}`) {
175
+ if (compareMIMETypes(mimeType, `application/x.${loader.id}`)) {
175
176
  return loader;
176
177
  }
177
178
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-error-message.d.ts","sourceRoot":"","sources":["../../../src/lib/fetch/fetch-error-message.ts"],"names":[],"mappings":"AAIA,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAE1E;AAED,wBAAsB,2BAA2B,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAcrF"}
1
+ {"version":3,"file":"fetch-error-message.d.ts","sourceRoot":"","sources":["../../../src/lib/fetch/fetch-error-message.ts"],"names":[],"mappings":"AAKA,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAE1E;AAGD,wBAAsB,2BAA2B,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAcrF"}
@@ -1,9 +1,11 @@
1
1
  // loaders.gl
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
+ // TODO - duplicates response-utils code
4
5
  export function getErrorMessageFromResponseSync(response) {
5
6
  return `Failed to fetch resource ${response.url}(${response.status}): ${response.statusText} `;
6
7
  }
8
+ // TODO - duplicates response-utils code
7
9
  export async function getErrorMessageFromResponse(response) {
8
10
  let message = `Failed to fetch resource ${response.url} (${response.status}): `;
9
11
  try {
@@ -0,0 +1,14 @@
1
+ export declare class FetchError extends Error {
2
+ constructor(message: string, info: {
3
+ url: string;
4
+ reason: string;
5
+ response?: Response;
6
+ });
7
+ /** A best effort reason for why the fetch failed */
8
+ reason: string;
9
+ /** The URL that failed to load. Empty string if not available. */
10
+ url: string;
11
+ /** The Response object, if any. */
12
+ response?: Response;
13
+ }
14
+ //# sourceMappingURL=fetch-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-error.d.ts","sourceRoot":"","sources":["../../../src/lib/fetch/fetch-error.ts"],"names":[],"mappings":"AAIA,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;KAAC;IAMrF,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,GAAG,EAAE,MAAM,CAAC;IACZ,mCAAmC;IACnC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB"}
@@ -0,0 +1,17 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+ export class FetchError extends Error {
5
+ constructor(message, info) {
6
+ super(message);
7
+ this.reason = info.reason;
8
+ this.url = info.url;
9
+ this.response = info.response;
10
+ }
11
+ /** A best effort reason for why the fetch failed */
12
+ reason;
13
+ /** The URL that failed to load. Empty string if not available. */
14
+ url;
15
+ /** The Response object, if any. */
16
+ response;
17
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-file.d.ts","sourceRoot":"","sources":["../../../src/lib/fetch/fetch-file.ts"],"names":[],"mappings":"AAOA,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE/C;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,YAAY,CAAC,EAAE,WAAW,GACzB,OAAO,CAAC,QAAQ,CAAC,CAoBnB"}
1
+ {"version":3,"file":"fetch-file.d.ts","sourceRoot":"","sources":["../../../src/lib/fetch/fetch-file.ts"],"names":[],"mappings":"AAQA,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE/C;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,YAAY,CAAC,EAAE,WAAW,GACzB,OAAO,CAAC,QAAQ,CAAC,CAoBnB"}
@@ -3,6 +3,7 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
  import { resolvePath } from '@loaders.gl/loader-utils';
5
5
  import { makeResponse } from "../utils/response-utils.js";
6
+ // import {FetchError} from './fetch-error';
6
7
  export function isNodePath(url) {
7
8
  return !isRequestURL(url) && !isDataURL(url);
8
9
  }
package/dist/lib/init.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
  import { log } from "./utils/log.js";
5
5
  // @ts-ignore TS2304: Cannot find name '__VERSION__'.
6
- const version = typeof "4.2.0-alpha.5" !== 'undefined' ? "4.2.0-alpha.5" : '';
6
+ const version = typeof "4.2.0-alpha.6" !== 'undefined' ? "4.2.0-alpha.6" : '';
7
7
  // @ts-ignore
8
8
  if (!globalThis.loaders) {
9
9
  log.log(1, `loaders.gl ${version}`)();
@@ -1,4 +1,4 @@
1
- import type { Loader, LoaderOptions } from '@loaders.gl/loader-utils';
1
+ import { Loader, LoaderOptions } from '@loaders.gl/loader-utils';
2
2
  /**
3
3
  * Global state for loaders.gl. Stored on `globalThis.loaders._state`
4
4
  */
@@ -1 +1 @@
1
- {"version":3,"file":"option-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/loader-utils/option-utils.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,MAAM,EAAE,aAAa,EAAC,MAAM,0BAA0B,CAAC;AAKpE;;GAEG;AACH,KAAK,iBAAiB,GAAG;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,EAAE,aAAa,CAAC;CAC9B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,iBAAiB,CAWxD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,aAAa,CAKtD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAK7D;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAAE,EAClB,GAAG,CAAC,EAAE,MAAM,GACX,aAAa,CAMf"}
1
+ {"version":3,"file":"option-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/loader-utils/option-utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,MAAM,EAAE,aAAa,EAAoB,MAAM,0BAA0B,CAAC;AAKlF;;GAEG;AACH,KAAK,iBAAiB,GAAG;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,EAAE,aAAa,CAAC;CAC9B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,iBAAiB,CAWxD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,aAAa,CAKtD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAO7D;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAAE,EAClB,GAAG,CAAC,EAAE,MAAM,GACX,aAAa,CAMf"}
@@ -1,6 +1,7 @@
1
1
  // loaders.gl
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
+ import { registerJSModules } from '@loaders.gl/loader-utils';
4
5
  import { isPureObject, isObject } from "../../javascript-utils/is-type.js";
5
6
  import { probeLog, NullLog } from "./loggers.js";
6
7
  import { DEFAULT_LOADER_OPTIONS, REMOVED_LOADER_OPTIONS } from "./option-defaults.js";
@@ -39,6 +40,8 @@ export function setGlobalOptions(options) {
39
40
  const globalOptions = getGlobalLoaderOptions();
40
41
  // @ts-expect-error First param looks incorrect
41
42
  state.globalOptions = normalizeOptionsInternal(globalOptions, options);
43
+ // Make sure any new modules are registered
44
+ registerJSModules(options.modules);
42
45
  }
43
46
  /**
44
47
  * Merges options with global opts and loader defaults, also injects baseUri
@@ -1,3 +1,11 @@
1
+ /**
2
+ * Compare two MIME types, case insensitively etc.
3
+ * @param mimeType1
4
+ * @param mimeType2
5
+ * @returns true if the MIME types are equivalent
6
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#structure_of_a_mime_type
7
+ */
8
+ export declare function compareMIMETypes(mimeType1: string, mimeType2: string): boolean;
1
9
  /**
2
10
  * Remove extra data like `charset` from MIME types
3
11
  * @param mimeString
@@ -1 +1 @@
1
- {"version":3,"file":"mime-type-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/mime-type-utils.ts"],"names":[],"mappings":"AAUA;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAOxD;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOxD"}
1
+ {"version":3,"file":"mime-type-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/mime-type-utils.ts"],"names":[],"mappings":"AAUA;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAK9E;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAOxD;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOxD"}
@@ -5,6 +5,19 @@
5
5
  // https://mimesniff.spec.whatwg.org/
6
6
  const DATA_URL_PATTERN = /^data:([-\w.]+\/[-\w.+]+)(;|,)/;
7
7
  const MIME_TYPE_PATTERN = /^([-\w.]+\/[-\w.+]+)/;
8
+ /**
9
+ * Compare two MIME types, case insensitively etc.
10
+ * @param mimeType1
11
+ * @param mimeType2
12
+ * @returns true if the MIME types are equivalent
13
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#structure_of_a_mime_type
14
+ */
15
+ export function compareMIMETypes(mimeType1, mimeType2) {
16
+ if (mimeType1.toLowerCase() === mimeType2.toLowerCase()) {
17
+ return true;
18
+ }
19
+ return false;
20
+ }
8
21
  /**
9
22
  * Remove extra data like `charset` from MIME types
10
23
  * @param mimeString
@@ -1 +1 @@
1
- {"version":3,"file":"response-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/response-utils.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAuCvE;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAKrE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAM1D"}
1
+ {"version":3,"file":"response-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/response-utils.ts"],"names":[],"mappings":"AASA;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAuCvE;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAKrE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAM1D"}
@@ -2,7 +2,9 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
  import { isResponse } from "../../javascript-utils/is-type.js";
5
+ import { FetchError } from "../fetch/fetch-error.js";
5
6
  import { getResourceContentLength, getResourceUrl, getResourceMIMEType } from "./resource-utils.js";
7
+ import { shortenUrlForDisplay } from "./url-utils.js";
6
8
  /**
7
9
  * Returns a Response object
8
10
  * Adds content-length header when possible
@@ -49,8 +51,8 @@ export async function makeResponse(resource) {
49
51
  */
50
52
  export async function checkResponse(response) {
51
53
  if (!response.ok) {
52
- const message = await getResponseError(response);
53
- throw new Error(message);
54
+ const error = await getResponseError(response);
55
+ throw error;
54
56
  }
55
57
  }
56
58
  /**
@@ -66,20 +68,24 @@ export function checkResponseSync(response) {
66
68
  }
67
69
  // HELPERS
68
70
  async function getResponseError(response) {
69
- let message = `Failed to fetch resource ${response.url} (${response.status}): `;
71
+ const shortUrl = shortenUrlForDisplay(response.url);
72
+ let message = `Failed to fetch resource (${response.status}) ${response.statusText}: ${shortUrl}`;
73
+ message = message.length > 100 ? `${message.slice(0, 100)}...` : message;
74
+ const info = {
75
+ reason: response.statusText,
76
+ url: response.url,
77
+ response
78
+ };
70
79
  try {
71
80
  const contentType = response.headers.get('Content-Type');
72
- let text = response.statusText;
73
- if (contentType?.includes('application/json')) {
74
- text += ` ${await response.text()}`;
75
- }
76
- message += text;
77
- message = message.length > 60 ? `${message.slice(0, 60)}...` : message;
81
+ info.reason = contentType?.includes('application/json')
82
+ ? await response.json()
83
+ : response.text();
78
84
  }
79
85
  catch (error) {
80
86
  // eslint forbids return in a finally statement, so we just catch here
81
87
  }
82
- return message;
88
+ return new FetchError(message, info);
83
89
  }
84
90
  async function getInitialDataUrl(resource) {
85
91
  const INITIAL_DATA_LENGTH = 5;
@@ -1,3 +1,4 @@
1
1
  export declare function extractQueryString(url: any): string;
2
2
  export declare function stripQueryString(url: any): string;
3
+ export declare function shortenUrlForDisplay(url: string): string;
3
4
  //# sourceMappingURL=url-utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"url-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/url-utils.ts"],"names":[],"mappings":"AAMA,wBAAgB,kBAAkB,CAAC,GAAG,KAAA,GAAG,MAAM,CAG9C;AAED,wBAAgB,gBAAgB,CAAC,GAAG,KAAA,GAAG,MAAM,CAE5C"}
1
+ {"version":3,"file":"url-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/url-utils.ts"],"names":[],"mappings":"AAMA,wBAAgB,kBAAkB,CAAC,GAAG,KAAA,GAAG,MAAM,CAG9C;AAED,wBAAgB,gBAAgB,CAAC,GAAG,KAAA,GAAG,MAAM,CAE5C;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOxD"}
@@ -9,3 +9,11 @@ export function extractQueryString(url) {
9
9
  export function stripQueryString(url) {
10
10
  return url.replace(QUERY_STRING_PATTERN, '');
11
11
  }
12
+ export function shortenUrlForDisplay(url) {
13
+ if (url.length < 50) {
14
+ return url;
15
+ }
16
+ const urlEnd = url.slice(url.length - 15);
17
+ const urlStart = url.substr(0, 32);
18
+ return `${urlStart}...${urlEnd}`;
19
+ }
@@ -1,13 +1,50 @@
1
- import type { Loader, LoaderWithParser, LoaderOptions } from '@loaders.gl/loader-utils';
1
+ import type { LoaderOptions } from '@loaders.gl/loader-utils';
2
+ import { LoaderContext } from '@loaders.gl/loader-utils';
2
3
  export type NullLoaderOptions = LoaderOptions & {
3
4
  null?: {};
4
5
  };
5
6
  /**
6
7
  * Loads any data and returns null (or optionally passes through data unparsed)
7
8
  */
8
- export declare const NullWorkerLoader: Loader<null, never, NullLoaderOptions>;
9
+ export declare const NullWorkerLoader: {
10
+ readonly dataType: null;
11
+ readonly batchType: never;
12
+ readonly name: "Null loader";
13
+ readonly id: "null";
14
+ readonly module: "core";
15
+ readonly version: any;
16
+ readonly worker: true;
17
+ readonly mimeTypes: ["application/x.empty"];
18
+ readonly extensions: ["null"];
19
+ readonly tests: [() => false];
20
+ readonly options: {
21
+ readonly null: {};
22
+ };
23
+ };
9
24
  /**
10
25
  * Loads any data and returns null (or optionally passes through data unparsed)
11
26
  */
12
- export declare const NullLoader: LoaderWithParser<null, null, NullLoaderOptions>;
27
+ export declare const NullLoader: {
28
+ readonly dataType: null;
29
+ readonly batchType: null;
30
+ readonly name: "Null loader";
31
+ readonly id: "null";
32
+ readonly module: "core";
33
+ readonly version: any;
34
+ readonly mimeTypes: ["application/x.empty"];
35
+ readonly extensions: ["null"];
36
+ readonly parse: (arrayBuffer: ArrayBuffer, options?: NullLoaderOptions, context?: LoaderContext) => Promise<null>;
37
+ readonly parseSync: typeof parseSync;
38
+ readonly parseInBatches: (asyncIterator: Iterable<ArrayBuffer> | AsyncIterable<ArrayBuffer>, options: NullLoaderOptions | undefined, context: LoaderContext | undefined) => AsyncGenerator<null, void, undefined>;
39
+ readonly tests: [() => false];
40
+ readonly options: {
41
+ readonly null: {};
42
+ };
43
+ };
44
+ /**
45
+ * Returns arguments passed to the parse API in a format that can be transferred to a
46
+ * web worker. The `context` parameter is stripped using JSON.stringify & parse.
47
+ */
48
+ declare function parseSync(arrayBuffer: ArrayBuffer, options?: NullLoaderOptions, context?: LoaderContext): null;
49
+ export {};
13
50
  //# sourceMappingURL=null-loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"null-loader.d.ts","sourceRoot":"","sources":["../src/null-loader.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAC,MAAM,EAAE,gBAAgB,EAAE,aAAa,EAAC,MAAM,0BAA0B,CAAC;AAGtF,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG;IAC9C,IAAI,CAAC,EAAE,EAAE,CAAC;CACX,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,iBAAiB,CAYnE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,iBAAiB,CAmBtE,CAAC"}
1
+ {"version":3,"file":"null-loader.d.ts","sourceRoot":"","sources":["../src/null-loader.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAA2B,aAAa,EAAC,MAAM,0BAA0B,CAAC;AACtF,OAAO,EAAC,aAAa,EAAC,MAAM,0BAA0B,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GAAG,aAAa,GAAG;IAC9C,IAAI,CAAC,EAAE,EAAE,CAAC;CACX,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;CAc8B,CAAC;AAE5D;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;;;;kCAUM,WAAW,YAAY,iBAAiB,YAAY,aAAa;;;;;;;CAY1B,CAAC;AAErE;;;GAGG;AACH,iBAAS,SAAS,CAChB,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,iBAAiB,EAC3B,OAAO,CAAC,EAAE,aAAa,GACtB,IAAI,CAEN"}
@@ -3,11 +3,13 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
  // __VERSION__ is injected by babel-plugin-version-inline
5
5
  // @ts-ignore TS2304: Cannot find name '__VERSION__'.
6
- const VERSION = typeof "4.2.0-alpha.5" !== 'undefined' ? "4.2.0-alpha.5" : 'latest';
6
+ const VERSION = typeof "4.2.0-alpha.6" !== 'undefined' ? "4.2.0-alpha.6" : 'latest';
7
7
  /**
8
8
  * Loads any data and returns null (or optionally passes through data unparsed)
9
9
  */
10
10
  export const NullWorkerLoader = {
11
+ dataType: null,
12
+ batchType: null,
11
13
  name: 'Null loader',
12
14
  id: 'null',
13
15
  module: 'core',
@@ -24,6 +26,8 @@ export const NullWorkerLoader = {
24
26
  * Loads any data and returns null (or optionally passes through data unparsed)
25
27
  */
26
28
  export const NullLoader = {
29
+ dataType: null,
30
+ batchType: null,
27
31
  name: 'Null loader',
28
32
  id: 'null',
29
33
  module: 'core',
@@ -235,8 +235,10 @@ async function parseData({
235
235
  }
236
236
 
237
237
  // src/null-loader.ts
238
- var VERSION = true ? "4.2.0-alpha.5" : "latest";
238
+ var VERSION = true ? "4.2.0-alpha.6" : "latest";
239
239
  var NullLoader = {
240
+ dataType: null,
241
+ batchType: null,
240
242
  name: "Null loader",
241
243
  id: "null",
242
244
  module: "core",
@@ -200,8 +200,10 @@
200
200
  }
201
201
 
202
202
  // src/null-loader.ts
203
- var VERSION = true ? "4.2.0-alpha.5" : "latest";
203
+ var VERSION = true ? "4.2.0-alpha.6" : "latest";
204
204
  var NullLoader = {
205
+ dataType: null,
206
+ batchType: null,
205
207
  name: "Null loader",
206
208
  id: "null",
207
209
  module: "core",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loaders.gl/core",
3
- "version": "4.2.0-alpha.6",
3
+ "version": "4.2.0-beta.1",
4
4
  "description": "The core API for working with loaders.gl loaders and writers",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -55,10 +55,10 @@
55
55
  "build-worker-node": "esbuild src/workers/null-worker.ts --outfile=dist/null-worker-node.js --bundle --platform=node --target=node16 --define:__VERSION__=\\\"$npm_package_version\\\""
56
56
  },
57
57
  "dependencies": {
58
- "@loaders.gl/loader-utils": "4.2.0-alpha.6",
59
- "@loaders.gl/schema": "4.2.0-alpha.6",
60
- "@loaders.gl/worker-utils": "4.2.0-alpha.6",
58
+ "@loaders.gl/loader-utils": "4.2.0-beta.1",
59
+ "@loaders.gl/schema": "4.2.0-beta.1",
60
+ "@loaders.gl/worker-utils": "4.2.0-beta.1",
61
61
  "@probe.gl/log": "^4.0.2"
62
62
  },
63
- "gitHead": "37bd8ca71763529f18727ee4bf29dd176aa914ca"
63
+ "gitHead": "c386a9196516fe3ff24847b40e6c77be039cf905"
64
64
  }
package/src/index.ts CHANGED
@@ -22,6 +22,7 @@ export type {
22
22
 
23
23
  // FILE READING AND WRITING
24
24
  export {fetchFile} from './lib/fetch/fetch-file';
25
+ export {FetchError} from './lib/fetch/fetch-error';
25
26
 
26
27
  export {readArrayBuffer} from './lib/fetch/read-array-buffer';
27
28
  // export {readFileSync} from './lib/fetch/read-file';
@@ -7,6 +7,7 @@ import {compareArrayBuffers, path} from '@loaders.gl/loader-utils';
7
7
  import {normalizeLoader} from '../loader-utils/normalize-loader';
8
8
  import {log} from '../utils/log';
9
9
  import {getResourceUrl, getResourceMIMEType} from '../utils/resource-utils';
10
+ import {compareMIMETypes} from '../utils/mime-type-utils';
10
11
  import {getRegisteredLoaders} from './register-loaders';
11
12
  import {isBlob} from '../../javascript-utils/is-type';
12
13
  import {stripQueryString} from '../utils/url-utils';
@@ -216,13 +217,13 @@ function findLoaderByExtension(loaders: Loader[], extension: string): Loader | n
216
217
 
217
218
  function findLoaderByMIMEType(loaders: Loader[], mimeType: string): Loader | null {
218
219
  for (const loader of loaders) {
219
- if (loader.mimeTypes && loader.mimeTypes.includes(mimeType)) {
220
+ if (loader.mimeTypes?.some((mimeType1) => compareMIMETypes(mimeType, mimeType1))) {
220
221
  return loader;
221
222
  }
222
223
 
223
224
  // Support referring to loaders using the "unregistered tree"
224
225
  // https://en.wikipedia.org/wiki/Media_type#Unregistered_tree
225
- if (mimeType === `application/x.${loader.id}`) {
226
+ if (compareMIMETypes(mimeType, `application/x.${loader.id}`)) {
226
227
  return loader;
227
228
  }
228
229
  }
@@ -2,10 +2,12 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
+ // TODO - duplicates response-utils code
5
6
  export function getErrorMessageFromResponseSync(response: Response): string {
6
7
  return `Failed to fetch resource ${response.url}(${response.status}): ${response.statusText} `;
7
8
  }
8
9
 
10
+ // TODO - duplicates response-utils code
9
11
  export async function getErrorMessageFromResponse(response: Response): Promise<string> {
10
12
  let message = `Failed to fetch resource ${response.url} (${response.status}): `;
11
13
  try {
@@ -0,0 +1,18 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ export class FetchError extends Error {
6
+ constructor(message: string, info: {url: string; reason: string; response?: Response}) {
7
+ super(message);
8
+ this.reason = info.reason;
9
+ this.url = info.url;
10
+ this.response = info.response;
11
+ }
12
+ /** A best effort reason for why the fetch failed */
13
+ reason: string;
14
+ /** The URL that failed to load. Empty string if not available. */
15
+ url: string;
16
+ /** The Response object, if any. */
17
+ response?: Response;
18
+ }
@@ -4,6 +4,7 @@
4
4
 
5
5
  import {resolvePath} from '@loaders.gl/loader-utils';
6
6
  import {makeResponse} from '../utils/response-utils';
7
+ // import {FetchError} from './fetch-error';
7
8
 
8
9
  export function isNodePath(url: string): boolean {
9
10
  return !isRequestURL(url) && !isDataURL(url);
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import type {Loader, LoaderOptions} from '@loaders.gl/loader-utils';
5
+ import {Loader, LoaderOptions, registerJSModules} from '@loaders.gl/loader-utils';
6
6
  import {isPureObject, isObject} from '../../javascript-utils/is-type';
7
7
  import {probeLog, NullLog} from './loggers';
8
8
  import {DEFAULT_LOADER_OPTIONS, REMOVED_LOADER_OPTIONS} from './option-defaults';
@@ -53,6 +53,8 @@ export function setGlobalOptions(options: LoaderOptions): void {
53
53
  const globalOptions = getGlobalLoaderOptions();
54
54
  // @ts-expect-error First param looks incorrect
55
55
  state.globalOptions = normalizeOptionsInternal(globalOptions, options);
56
+ // Make sure any new modules are registered
57
+ registerJSModules(options.modules);
56
58
  }
57
59
 
58
60
  /**
@@ -8,6 +8,20 @@
8
8
  const DATA_URL_PATTERN = /^data:([-\w.]+\/[-\w.+]+)(;|,)/;
9
9
  const MIME_TYPE_PATTERN = /^([-\w.]+\/[-\w.+]+)/;
10
10
 
11
+ /**
12
+ * Compare two MIME types, case insensitively etc.
13
+ * @param mimeType1
14
+ * @param mimeType2
15
+ * @returns true if the MIME types are equivalent
16
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#structure_of_a_mime_type
17
+ */
18
+ export function compareMIMETypes(mimeType1: string, mimeType2: string): boolean {
19
+ if (mimeType1.toLowerCase() === mimeType2.toLowerCase()) {
20
+ return true;
21
+ }
22
+ return false;
23
+ }
24
+
11
25
  /**
12
26
  * Remove extra data like `charset` from MIME types
13
27
  * @param mimeString
@@ -3,7 +3,9 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
5
  import {isResponse} from '../../javascript-utils/is-type';
6
+ import {FetchError} from '../fetch/fetch-error';
6
7
  import {getResourceContentLength, getResourceUrl, getResourceMIMEType} from './resource-utils';
8
+ import {shortenUrlForDisplay} from './url-utils';
7
9
 
8
10
  /**
9
11
  * Returns a Response object
@@ -58,8 +60,8 @@ export async function makeResponse(resource: unknown): Promise<Response> {
58
60
  */
59
61
  export async function checkResponse(response: Response): Promise<void> {
60
62
  if (!response.ok) {
61
- const message = await getResponseError(response);
62
- throw new Error(message);
63
+ const error = await getResponseError(response);
64
+ throw error;
63
65
  }
64
66
  }
65
67
 
@@ -77,20 +79,26 @@ export function checkResponseSync(response: Response): void {
77
79
 
78
80
  // HELPERS
79
81
 
80
- async function getResponseError(response: Response): Promise<string> {
81
- let message = `Failed to fetch resource ${response.url} (${response.status}): `;
82
+ async function getResponseError(response: Response): Promise<Error> {
83
+ const shortUrl = shortenUrlForDisplay(response.url);
84
+ let message = `Failed to fetch resource (${response.status}) ${response.statusText}: ${shortUrl}`;
85
+ message = message.length > 100 ? `${message.slice(0, 100)}...` : message;
86
+
87
+ const info = {
88
+ reason: response.statusText,
89
+ url: response.url,
90
+ response
91
+ };
92
+
82
93
  try {
83
94
  const contentType = response.headers.get('Content-Type');
84
- let text = response.statusText;
85
- if (contentType?.includes('application/json')) {
86
- text += ` ${await response.text()}`;
87
- }
88
- message += text;
89
- message = message.length > 60 ? `${message.slice(0, 60)}...` : message;
95
+ info.reason = contentType?.includes('application/json')
96
+ ? await response.json()
97
+ : response.text();
90
98
  } catch (error) {
91
99
  // eslint forbids return in a finally statement, so we just catch here
92
100
  }
93
- return message;
101
+ return new FetchError(message, info);
94
102
  }
95
103
 
96
104
  async function getInitialDataUrl(
@@ -12,3 +12,12 @@ export function extractQueryString(url): string {
12
12
  export function stripQueryString(url): string {
13
13
  return url.replace(QUERY_STRING_PATTERN, '');
14
14
  }
15
+
16
+ export function shortenUrlForDisplay(url: string): string {
17
+ if (url.length < 50) {
18
+ return url;
19
+ }
20
+ const urlEnd = url.slice(url.length - 15);
21
+ const urlStart = url.substr(0, 32);
22
+ return `${urlStart}...${urlEnd}`;
23
+ }