@cereusdb/standard 0.2.0 → 0.4.0

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.
package/README.md CHANGED
@@ -10,11 +10,15 @@ This package includes browser object stores for ranged remote Parquet reads and
10
10
  npm install @cereusdb/standard
11
11
  ```
12
12
 
13
+ ## Parquet support
14
+
15
+ Parquet files compressed with Snappy, Gzip, Brotli, LZ4, or ZSTD can be registered.
16
+
13
17
  ## SQL function availability
14
18
 
15
19
  Current runtime surface:
16
20
 
17
- - `131` runtime `ST_*` names
21
+ - `151` runtime `ST_*` names
18
22
  - `0` runtime `RS_*` names
19
23
 
20
24
  Included function families:
@@ -37,6 +41,44 @@ Not included in this package:
37
41
 
38
42
  Browser object stores are included in `@cereusdb/standard`. Use `registerObjectStores()` to configure `http`, `s3`, `gcs`, or `azure` providers, then `registerParquetTable()` to register an exact Parquet object or provider-backed prefix.
39
43
 
44
+ ## Persistent databases (OPFS)
45
+
46
+ Tables normally live in memory. Persistent databases are stored in the browser's Origin Private File System and survive page reloads:
47
+
48
+ ```ts
49
+ const db = await CereusDB.create({ attach: ['opfs://mydb'] }); // opens or creates mydb
50
+
51
+ await db.sqlJSON(`CREATE TABLE mydb.public.cities AS SELECT 1 AS id, 'Berlin' AS name, ST_Point(13.4, 52.5) AS geom`);
52
+ await db.sqlJSON(`INSERT INTO mydb.public.cities VALUES (2, 'Paris', ST_Point(2.35, 48.86))`);
53
+ await db.sqlJSON(`USE mydb`); // `cities` now resolves to mydb.public.cities
54
+ ```
55
+
56
+ SQL: `CREATE DATABASE 'opfs://mydb'`, `ATTACH 'opfs://mydb' [AS name]`, `DETACH name`, `DROP DATABASE name`, `USE name`, `ALTER TABLE ... RENAME TO | ADD COLUMN | DROP COLUMN | RENAME COLUMN`, and `SELECT * FROM cereusdb_databases()`. Databases appear as catalogs in `information_schema` and `db.catalog()`. A table's data is loaded the first time it is used. See the [persistent databases guide](https://github.com/tobilg/cereusdb/blob/main/packages/documentation/guides/persistent-databases.md).
57
+
58
+ ## GeoParquet export
59
+
60
+ ```ts
61
+ const bytes = await db.exportGeoParquet('mydb.public.cities'); // Uint8Array
62
+ await db.downloadGeoParquet('mydb.public.cities'); // downloads cities.parquet
63
+ await db.sqlJSON(`COPY (SELECT * FROM cities WHERE id > 1) TO 'some.parquet'`);
64
+ ```
65
+
66
+ See the [GeoParquet export guide](https://github.com/tobilg/cereusdb/blob/main/packages/documentation/guides/geoparquet-export.md).
67
+
68
+ ## Loading the WASM module
69
+
70
+ The wasm binary ships as a separate file, `dist/wasm/cereusdb_bg.wasm`. The default entry finds it automatically, and bundlers emit it as an asset.
71
+
72
+ If you host the wasm yourself, or your bundler inlines assets into large `data:application/wasm;base64,...` strings, use the `external` entry. It has no built-in wasm reference and requires `wasmUrl` or `wasmSource`:
73
+
74
+ ```ts
75
+ import { CereusDB } from '@cereusdb/standard/external';
76
+
77
+ const db = await CereusDB.create({ wasmUrl: '/wasm/cereusdb_bg.wasm' });
78
+ ```
79
+
80
+ Copy `node_modules/@cereusdb/standard/dist/wasm/cereusdb_bg.wasm` to your static assets, or import its URL with Vite: `import wasmUrl from '@cereusdb/standard/wasm?url'`. See the [WASM loading guide](https://github.com/tobilg/cereusdb/blob/main/packages/documentation/guides/wasm-loading.md) for details.
81
+
40
82
  ## JS / TS API
41
83
 
42
84
  Exports:
@@ -49,10 +91,49 @@ Exports:
49
91
  - `RegisterParquetTableOptions`
50
92
  - `RasterFormat`
51
93
  - `QueryResult`
94
+ - `MemoryStorageBackend`, `OPFSStorageBackend`, `StorageBackend`, `StorageOptions`
95
+ - `CreateDatabaseOptions`, `AttachDatabaseOptions`, `DatabaseListing`
96
+ - `CatalogDatabase`, `CatalogSchema`, `CatalogTable`, `CatalogColumn`
97
+ - `CreateTableDefinition`, `CreateTableOptions`, `AlterTableOperation`
98
+ - `GeoParquetExportOptions`, `DownloadGeoParquetOptions`, `ExportHandler`
99
+ - `downloadFile`, `PARQUET_MIME_TYPE`
52
100
 
53
101
  Main types:
54
102
 
55
103
  ```ts
104
+ interface StorageOptions {
105
+ opfs?: StorageBackend | false; // default: OPFSStorageBackend when the browser has OPFS
106
+ [scheme: string]: StorageBackend | false | undefined;
107
+ }
108
+
109
+ interface StorageBackend {
110
+ readFile(path: string): Promise<Uint8Array | null>;
111
+ writeFile(path: string, data: Uint8Array): Promise<void>;
112
+ remove(path: string): Promise<void>;
113
+ list(path: string): Promise<string[]>;
114
+ lock?(name: string): Promise<void>;
115
+ unlock?(name: string): Promise<void>;
116
+ }
117
+
118
+ type ExportHandler = (filename: string, data: Uint8Array, mimeType: string) => void | Promise<void>;
119
+
120
+ type CreateTableDefinition = { columns: Record<string, string> } | { as: string };
121
+
122
+ type AlterTableOperation =
123
+ | { renameTo: string }
124
+ | { addColumn: { name: string; type: string; notNull?: boolean; default?: string }; ifNotExists?: boolean }
125
+ | { dropColumn: string | string[]; ifExists?: boolean }
126
+ | { renameColumn: { from: string; to: string } };
127
+
128
+ interface GeoParquetExportOptions {
129
+ compression?: 'zstd' | 'snappy' | 'lz4' | 'gzip' | 'brotli' | 'uncompressed';
130
+ rowGroupSize?: number;
131
+ }
132
+
133
+ interface DownloadGeoParquetOptions extends GeoParquetExportOptions {
134
+ filename?: string;
135
+ }
136
+
56
137
  type RasterFormat = 'geotiff' | 'tiff';
57
138
  type ObjectStoreProvider = 'http' | 's3' | 'gcs' | 'azure';
58
139
 
@@ -66,6 +147,9 @@ interface CereusDBOptions {
66
147
  | WebAssembly.Module
67
148
  | Promise<Response>;
68
149
  objectStores?: ObjectStoreRegistryConfig;
150
+ storage?: StorageOptions;
151
+ attach?: string[];
152
+ onExport?: ExportHandler | false;
69
153
  }
70
154
 
71
155
  interface ObjectStoreRegistryConfig {
@@ -104,8 +188,22 @@ class CereusDB {
104
188
  registerGeoJSON(name: string, geojson: string | object): void;
105
189
  registerRaster(name: string, data: BufferSource, format: RasterFormat): void;
106
190
  registerGeoTIFF(name: string, data: BufferSource): void;
107
- dropTable(name: string): void;
108
- tables(): string[];
191
+ dropTable(name: string): Promise<void>;
192
+ catalog(): Promise<CatalogDatabase[]>;
193
+ createDatabase(location: string, options?: CreateDatabaseOptions): Promise<string>;
194
+ attachDatabase(location: string, options?: AttachDatabaseOptions): Promise<string>;
195
+ detachDatabase(name: string, options?: { ifExists?: boolean }): Promise<void>;
196
+ dropDatabase(nameOrLocation: string, options?: { ifExists?: boolean }): Promise<void>;
197
+ useDatabase(database: string, schema?: string): Promise<void>;
198
+ listDatabases(): Promise<DatabaseListing[]>;
199
+ createTable(name: string, definition: CreateTableDefinition, options?: CreateTableOptions): Promise<void>;
200
+ alterTable(name: string, operation: AlterTableOperation): Promise<void>;
201
+ insertArrow(table: string, data: BufferSource): Promise<number>;
202
+ compactDatabase(name: string): Promise<void>;
203
+ flush(): Promise<void>;
204
+ exportGeoParquet(queryOrTable: string, options?: GeoParquetExportOptions): Promise<Uint8Array>;
205
+ downloadGeoParquet(queryOrTable: string, options?: DownloadGeoParquetOptions): Promise<string>;
206
+ tables(options?: { qualified?: boolean }): string[];
109
207
  version(): string;
110
208
  }
111
209
  ```
@@ -119,6 +217,8 @@ API notes:
119
217
  - S3 temporary credentials use `access_key_id`, `secret_access_key`, and `token`, where `token` is the STS `SessionToken`.
120
218
  - S3-compatible endpoints can be configured with `endpoint`; use `allow_http: true` for local HTTP endpoints such as MinIO or LocalStack.
121
219
  - `registerRaster()` and `registerGeoTIFF()` are part of the shared wrapper, but raster registration requires `@cereusdb/full`.
220
+ - Persistent databases (`createDatabase()` and related methods), `ALTER TABLE`, `insertArrow()`, `catalog()` and GeoParquet export are available in every package.
221
+ - `downloadGeoParquet()` and `COPY ... TO` pass the file to the `onExport` handler: a browser download by default on the main thread; pass your own handler in Web Workers or Node.js.
122
222
 
123
223
  ## Example
124
224
 
@@ -0,0 +1,293 @@
1
+ import { type StorageBackend } from './storage.js';
2
+ export { MemoryStorageBackend, OPFSStorageBackend, type OPFSStorageBackendOptions, type StorageBackend, } from './storage.js';
3
+ export interface QueryResult {
4
+ /** Raw JSON data parsed from query */
5
+ data: Record<string, unknown>[];
6
+ /** Number of rows */
7
+ numRows: number;
8
+ /** Raw Arrow IPC bytes */
9
+ toIPC(): Uint8Array;
10
+ /** Convert to array of plain JS objects */
11
+ toJSON(): Record<string, unknown>[];
12
+ }
13
+ export interface CereusDBOptions {
14
+ /** Custom WASM module URL (for CDN hosting) */
15
+ wasmUrl?: string;
16
+ /** Preloaded WASM bytes/module for Node or custom loaders. */
17
+ wasmSource?: RequestInfo | URL | Response | BufferSource | WebAssembly.Module | Promise<Response>;
18
+ /** Browser-backed object stores to register at startup. */
19
+ objectStores?: ObjectStoreRegistryConfig;
20
+ /**
21
+ * Storage backends for persistent databases, by URL scheme. `opfs` defaults
22
+ * to an {@link OPFSStorageBackend} when the browser supports OPFS; pass
23
+ * `false` to disable it.
24
+ */
25
+ storage?: StorageOptions;
26
+ /**
27
+ * Persistent databases to open at startup, for example `['opfs://mydb']`.
28
+ * Each is created if it does not exist yet.
29
+ */
30
+ attach?: string[];
31
+ /**
32
+ * Receives files written by `COPY ... TO '<file>'` and
33
+ * {@link CereusDB.downloadGeoParquet}. Defaults to {@link downloadFile}
34
+ * (a browser download) when a DOM `document` is available; pass `false` to
35
+ * disable exports or a function to handle them yourself (for example in a
36
+ * Web Worker or in Node.js).
37
+ */
38
+ onExport?: ExportHandler | false;
39
+ }
40
+ /** Receives an exported file. */
41
+ export type ExportHandler = (filename: string, data: Uint8Array, mimeType: string) => void | Promise<void>;
42
+ /** MIME type of GeoParquet exports. */
43
+ export declare const PARQUET_MIME_TYPE = "application/vnd.apache.parquet";
44
+ /**
45
+ * Save a file with the browser's download mechanism. Needs a DOM `document`
46
+ * (the main thread); it does not work in Web Workers or Node.js.
47
+ */
48
+ export declare function downloadFile(filename: string, data: Uint8Array, mimeType?: string): void;
49
+ export interface StorageOptions {
50
+ opfs?: StorageBackend | false;
51
+ [scheme: string]: StorageBackend | false | undefined;
52
+ }
53
+ export interface CreateDatabaseOptions {
54
+ /** Database (catalog) name. Defaults to the lowercased name in the location URL. */
55
+ name?: string;
56
+ /** Open the database if it already exists instead of failing. */
57
+ ifNotExists?: boolean;
58
+ }
59
+ export interface AttachDatabaseOptions {
60
+ /** Database (catalog) name. Defaults to the lowercased name in the location URL. */
61
+ name?: string;
62
+ /** Succeed if the database is already attached under this name. */
63
+ ifNotExists?: boolean;
64
+ }
65
+ export interface DatabaseListing {
66
+ /** Catalog name, or `null` for stored databases that are not attached. */
67
+ name: string | null;
68
+ /** `memory` or the storage scheme, for example `opfs`. */
69
+ storage: string;
70
+ /** Location URL for persistent databases. */
71
+ location: string | null;
72
+ attached: boolean;
73
+ }
74
+ export interface CatalogColumn {
75
+ name: string;
76
+ /** Arrow data type. */
77
+ type: string;
78
+ nullable: boolean;
79
+ /** Arrow extension type, for example `geoarrow.wkb` for geometry columns. */
80
+ extension?: string;
81
+ }
82
+ export interface CatalogTable {
83
+ name: string;
84
+ type: 'BASE TABLE' | 'VIEW' | 'LOCAL TEMPORARY';
85
+ columns: CatalogColumn[];
86
+ }
87
+ export interface CatalogSchema {
88
+ name: string;
89
+ tables: CatalogTable[];
90
+ }
91
+ export interface CatalogDatabase {
92
+ name: string;
93
+ storage: string;
94
+ location: string | null;
95
+ schemas: CatalogSchema[];
96
+ }
97
+ /** Columns as `{ name: 'SQL type' }`, or a query for CREATE TABLE ... AS. */
98
+ export type CreateTableDefinition = {
99
+ columns: Record<string, string>;
100
+ } | {
101
+ as: string;
102
+ };
103
+ export interface GeoParquetExportOptions {
104
+ /** Parquet compression codec. Defaults to `zstd`. */
105
+ compression?: 'zstd' | 'snappy' | 'lz4' | 'gzip' | 'brotli' | 'uncompressed';
106
+ /** Maximum number of rows per row group. */
107
+ rowGroupSize?: number;
108
+ }
109
+ export interface DownloadGeoParquetOptions extends GeoParquetExportOptions {
110
+ /**
111
+ * File name. Defaults to `<table>.parquet` for a table and
112
+ * `export.parquet` for a query.
113
+ */
114
+ filename?: string;
115
+ }
116
+ export interface CreateTableOptions {
117
+ ifNotExists?: boolean;
118
+ orReplace?: boolean;
119
+ }
120
+ export type AlterTableOperation = {
121
+ renameTo: string;
122
+ } | {
123
+ addColumn: {
124
+ name: string;
125
+ /** SQL type, for example `VARCHAR` or `DOUBLE`. */
126
+ type: string;
127
+ notNull?: boolean;
128
+ /** SQL expression used for existing rows and as column default. */
129
+ default?: string;
130
+ };
131
+ ifNotExists?: boolean;
132
+ } | {
133
+ dropColumn: string | string[];
134
+ ifExists?: boolean;
135
+ } | {
136
+ renameColumn: {
137
+ from: string;
138
+ to: string;
139
+ };
140
+ };
141
+ export type RasterFormat = 'geotiff' | 'tiff';
142
+ export type ObjectStoreProvider = 'http' | 's3' | 'gcs' | 'azure';
143
+ export interface ObjectStoreRegistryConfig {
144
+ /** Maximum concurrent browser fetches used by object_store. */
145
+ maxConcurrency?: number;
146
+ /** Stores registered by URL prefix. */
147
+ stores: ObjectStoreConfig[];
148
+ }
149
+ export interface ObjectStoreConfig {
150
+ /** Optional diagnostic name. */
151
+ name?: string;
152
+ /** Backing provider. */
153
+ provider: ObjectStoreProvider;
154
+ /** URL prefix, for example https://host, s3://bucket, gs://bucket. */
155
+ url: string;
156
+ /** Upstream object_store option keys and primitive values. */
157
+ options?: Record<string, string | number | boolean>;
158
+ }
159
+ export interface RegisterParquetTableOptions {
160
+ /** File extension used during listing discovery. Defaults to .parquet. */
161
+ fileExtension?: string;
162
+ /** Optional DataFusion target partition count. */
163
+ targetPartitions?: number;
164
+ }
165
+ export declare class CereusDB {
166
+ private inner;
167
+ private storageBackends;
168
+ private exportHandler?;
169
+ private constructor();
170
+ /**
171
+ * Create and initialize a new CereusDB instance.
172
+ * This loads the WASM module and initializes the query engine.
173
+ */
174
+ static create(options?: CereusDBOptions): Promise<CereusDB>;
175
+ /**
176
+ * Execute a SQL query and return results as Arrow IPC bytes.
177
+ */
178
+ sql(query: string): Promise<Uint8Array>;
179
+ /**
180
+ * Execute a SQL query and return results as JSON.
181
+ */
182
+ sqlJSON(query: string): Promise<Record<string, unknown>[]>;
183
+ /**
184
+ * Register a remote Parquet file as a table.
185
+ * The server must support CORS.
186
+ */
187
+ registerRemoteParquet(name: string, url: string): Promise<void>;
188
+ /**
189
+ * Register browser-backed object stores for ranged and listing reads.
190
+ */
191
+ registerObjectStores(config: ObjectStoreRegistryConfig): void;
192
+ /**
193
+ * Register a remote Parquet object or prefix through DataFusion's listing table path.
194
+ */
195
+ registerParquetTable(name: string, url: string, options?: RegisterParquetTableOptions): Promise<void>;
196
+ /**
197
+ * Register a local file (from File API / drag-and-drop) as a table.
198
+ * Currently supports Parquet, GeoJSON, and GeoTIFF rasters.
199
+ */
200
+ registerFile(name: string, file: File): Promise<void>;
201
+ /**
202
+ * Register a GeoJSON object or string as a table.
203
+ */
204
+ registerGeoJSON(name: string, geojson: string | object): void;
205
+ /**
206
+ * Register a raster buffer as a single-column raster table.
207
+ * Requires the full GDAL-enabled package build.
208
+ */
209
+ registerRaster(name: string, data: BufferSource, format: RasterFormat): void;
210
+ /**
211
+ * Register a GeoTIFF buffer as a single-column raster table.
212
+ * Requires the full GDAL-enabled package build.
213
+ */
214
+ registerGeoTIFF(name: string, data: BufferSource): void;
215
+ /**
216
+ * Drop a table. The table is removed immediately; for tables of persistent
217
+ * databases the returned promise resolves once the change is written.
218
+ */
219
+ dropTable(name: string): Promise<void>;
220
+ /**
221
+ * Create a persistent database, for example `opfs://mydb`, and attach it
222
+ * as a catalog. Equivalent to `CREATE DATABASE 'opfs://mydb'`.
223
+ * Resolves to the database name.
224
+ */
225
+ createDatabase(location: string, options?: CreateDatabaseOptions): Promise<string>;
226
+ /**
227
+ * Open an existing persistent database. Equivalent to
228
+ * `ATTACH 'opfs://mydb' [AS name]`. Resolves to the database name.
229
+ */
230
+ attachDatabase(location: string, options?: AttachDatabaseOptions): Promise<string>;
231
+ /** Write pending changes and close a persistent database. Equivalent to `DETACH name`. */
232
+ detachDatabase(name: string, options?: {
233
+ ifExists?: boolean;
234
+ }): Promise<void>;
235
+ /**
236
+ * Drop a database by name or location. Persistent databases are deleted
237
+ * from storage. Equivalent to `DROP DATABASE`.
238
+ */
239
+ dropDatabase(nameOrLocation: string, options?: {
240
+ ifExists?: boolean;
241
+ }): Promise<void>;
242
+ /** Set the default database (and schema). Equivalent to `USE database[.schema]`. */
243
+ useDatabase(database: string, schema?: string): Promise<void>;
244
+ /** Attached databases plus stored databases that are not attached. */
245
+ listDatabases(): Promise<DatabaseListing[]>;
246
+ /** Describe all databases, schemas, tables and views. */
247
+ catalog(): Promise<CatalogDatabase[]>;
248
+ /**
249
+ * Create a table from column definitions or a query. `name` may be
250
+ * qualified (`mydb.public.cities`).
251
+ */
252
+ createTable(name: string, definition: CreateTableDefinition, options?: CreateTableOptions): Promise<void>;
253
+ /** Rename a table or add, drop, or rename a column. */
254
+ alterTable(name: string, operation: AlterTableOperation): Promise<void>;
255
+ /**
256
+ * Insert Arrow IPC data (stream or file format, for example from
257
+ * `tableToIPC()` of apache-arrow) into a table. Columns are matched by
258
+ * name; missing columns are filled with NULL. Resolves to the number of
259
+ * inserted rows.
260
+ */
261
+ insertArrow(table: string, data: BufferSource): Promise<number>;
262
+ /**
263
+ * Export a table or query result as a GeoParquet (1.1) file. Geometry and
264
+ * geography columns are described in the file's `geo` metadata.
265
+ *
266
+ * @param queryOrTable A query (`SELECT ...`, `WITH ...`) or a table name.
267
+ */
268
+ exportGeoParquet(queryOrTable: string, options?: GeoParquetExportOptions): Promise<Uint8Array>;
269
+ /**
270
+ * Export a table or query result as GeoParquet and pass it to the export
271
+ * handler: a browser download by default (see `onExport` in
272
+ * {@link CereusDBOptions}). Resolves to the file name.
273
+ *
274
+ * @param queryOrTable A query (`SELECT ...`, `WITH ...`) or a table name.
275
+ */
276
+ downloadGeoParquet(queryOrTable: string, options?: DownloadGeoParquetOptions): Promise<string>;
277
+ /** Rewrite all tables of a persistent database into one segment each. */
278
+ compactDatabase(name: string): Promise<void>;
279
+ /** Write pending changes of persistent databases (for example after registerGeoJSON()). */
280
+ flush(): Promise<void>;
281
+ /**
282
+ * List the tables and views of all databases. By default only the table
283
+ * names are returned, which is ambiguous when databases contain tables with
284
+ * the same name; pass `{ qualified: true }` for `database.schema.table`
285
+ * names, or use {@link CereusDB.catalog} for full details.
286
+ */
287
+ tables(options?: {
288
+ qualified?: boolean;
289
+ }): string[];
290
+ /** Version string. */
291
+ version(): string;
292
+ private objectStoreApi;
293
+ }