Skip to content

Commit

Permalink
feat(pmtiles): Create PMTileSource from Blob (#2668)
Browse files Browse the repository at this point in the history
  • Loading branch information
ibgreen authored Oct 1, 2023
1 parent f711293 commit 6fd3f8f
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 10 deletions.
1 change: 1 addition & 0 deletions modules/loader-utils/src/loader-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ export type LoaderWithParser<DataT = any, BatchT = any, LoaderOptionsT = LoaderO
options?: LoaderOptionsT,
context?: LoaderContext
) => Promise<DataT>;
parseFile?: (file: Blob, options?: LoaderOptionsT, context?: LoaderContext) => Promise<DataT>;
/** Parse atomically from an arraybuffer synchronously */
parseSync?: (
arrayBuffer: ArrayBuffer,
Expand Down
38 changes: 33 additions & 5 deletions modules/pmtiles/src/pmtiles-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,43 @@ import {DataSource, resolvePath} from '@loaders.gl/loader-utils';
import {ImageLoader} from '@loaders.gl/images';
import {MVTLoader, MVTLoaderOptions} from '@loaders.gl/mvt';

import {PMTiles} from 'pmtiles';
// import type {pPMTilesMetadata} from './lib/parse-pmtiles';
import {PMTilesMetadata, parsePMTilesHeader} from './lib/parse-pmtiles';
import {PMTiles, Source, RangeResponse} from 'pmtiles';

import type {PMTilesMetadata} from './lib/parse-pmtiles';
import {parsePMTilesHeader} from './lib/parse-pmtiles';
import {TileLoadParameters} from 'modules/loader-utils/src/lib/sources/tile-source';

export type PMTilesSourceProps = DataSourceProps & {
url: string;
url: string | Blob;
attributions?: string[];
};

export class BlobSource implements Source {
blob: Blob;
key: string;

constructor(blob: Blob, key: string) {
this.blob = blob;
this.key = key;
}

// TODO - how is this used?
getKey() {
// @ts-expect-error url is only defined on File subclass
return this.blob.url || '';
}

async getBytes(offset: number, length: number, signal?: AbortSignal): Promise<RangeResponse> {
const slice = this.blob.slice(offset, offset + length);
const data = await slice.arrayBuffer();
return {
data
// etag: response.headers.get('ETag') || undefined,
// cacheControl: response.headers.get('Cache-Control') || undefined,
// expires: response.headers.get('Expires') || undefined
};
}
}
/**
* A PMTiles data source
* @note Can be either a raster or vector tile source depending on the contents of the PMTiles file.
Expand All @@ -26,7 +53,8 @@ export class PMTilesSource extends DataSource implements ImageTileSource, Vector
constructor(props: PMTilesSourceProps) {
super(props);
this.props = props;
const url = resolvePath(props.url);
const url =
typeof props.url === 'string' ? resolvePath(props.url) : new BlobSource(props.url, 'pmtiles');
this.pmtiles = new PMTiles(url);
this.getTileData = this.getTileData.bind(this);
this.metadata = this.getMetadata();
Expand Down
26 changes: 21 additions & 5 deletions modules/pmtiles/test/pmtiles-source.spec.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,37 @@
// loaders.gl, MIT license

import test from 'tape-promise/tape';
import {isBrowser} from '@loaders.gl/loader-utils';
import {isBrowser, fetchFile} from '@loaders.gl/core';

import {PMTILESETS} from './data/tilesets';
import {PMTilesSource} from '@loaders.gl/pmtiles';

test('PMTilesSource', async (t) => {
test('PMTilesSource#urls', async (t) => {
if (!isBrowser) {
t.comment('PMTilesSource currently only supported in browser');
t.end();
return;
}
for (const tilesetUrl of PMTILESETS) {
const source = new PMTilesSource({
url: tilesetUrl
});
const source = new PMTilesSource({url: tilesetUrl});
t.ok(source);
const metadata = await source.getMetadata();
t.ok(metadata);
// console.error(JSON.stringify(metadata.tileJSON, null, 2));
}
t.end();
});

test('PMTilesSource#Blobs', async (t) => {
if (!isBrowser) {
t.comment('PMTilesSource currently only supported in browser');
t.end();
return;
}
for (const tilesetUrl of PMTILESETS) {
const response = await fetchFile(tilesetUrl);
const blob = await response.blob();
const source = new PMTilesSource({url: blob});
t.ok(source);
const metadata = await source.getMetadata();
t.ok(metadata);
Expand Down

0 comments on commit 6fd3f8f

Please sign in to comment.