quiverdb 0.9.5 → 0.9.7

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.
Binary file
Binary file
Binary file
Binary file
Binary file
package/mod.ts CHANGED
@@ -22,4 +22,4 @@ export type {
22
22
  TimeSeriesData,
23
23
  Value,
24
24
  } from "./src/index.ts";
25
- export { Database, LuaRunner, QuiverError } from "./src/index.ts";
25
+ export { Database, LUA_DB_API_REFERENCE, LuaRunner, QuiverError } from "./src/index.ts";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quiverdb",
3
- "version": "0.9.5",
3
+ "version": "0.9.7",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
package/src/composites.ts CHANGED
@@ -1,4 +1,11 @@
1
1
  import { Database } from "./database.ts";
2
+ import { QuiverError } from "./errors.ts";
3
+ import {
4
+ DATA_TYPE_DATE_TIME,
5
+ DATA_TYPE_FLOAT,
6
+ DATA_TYPE_INTEGER,
7
+ DATA_TYPE_STRING,
8
+ } from "./types.ts";
2
9
 
3
10
  Database.prototype.readScalarsById = function (
4
11
  this: Database,
@@ -10,18 +17,18 @@ Database.prototype.readScalarsById = function (
10
17
 
11
18
  for (const attr of attributes) {
12
19
  switch (attr.dataType) {
13
- case 0: // INTEGER
20
+ case DATA_TYPE_INTEGER:
14
21
  result[attr.name] = this.readScalarIntegerById(collection, attr.name, id);
15
22
  break;
16
- case 1: // FLOAT
23
+ case DATA_TYPE_FLOAT:
17
24
  result[attr.name] = this.readScalarFloatById(collection, attr.name, id);
18
25
  break;
19
- case 2: // STRING
20
- case 3: // DATE_TIME
26
+ case DATA_TYPE_STRING:
27
+ case DATA_TYPE_DATE_TIME:
21
28
  result[attr.name] = this.readScalarStringById(collection, attr.name, id);
22
29
  break;
23
30
  default:
24
- throw new Error(`Unknown data type ${attr.dataType} for attribute '${attr.name}'`);
31
+ throw new QuiverError(`Unknown data type ${attr.dataType} for attribute '${attr.name}'`);
25
32
  }
26
33
  }
27
34
 
@@ -39,18 +46,18 @@ Database.prototype.readVectorsById = function (
39
46
  for (const group of groups) {
40
47
  for (const col of group.valueColumns) {
41
48
  switch (col.dataType) {
42
- case 0: // INTEGER
49
+ case DATA_TYPE_INTEGER:
43
50
  result[col.name] = this.readVectorIntegersById(collection, col.name, id);
44
51
  break;
45
- case 1: // FLOAT
52
+ case DATA_TYPE_FLOAT:
46
53
  result[col.name] = this.readVectorFloatsById(collection, col.name, id);
47
54
  break;
48
- case 2: // STRING
49
- case 3: // DATE_TIME
55
+ case DATA_TYPE_STRING:
56
+ case DATA_TYPE_DATE_TIME:
50
57
  result[col.name] = this.readVectorStringsById(collection, col.name, id);
51
58
  break;
52
59
  default:
53
- throw new Error(`Unknown data type ${col.dataType} for column '${col.name}'`);
60
+ throw new QuiverError(`Unknown data type ${col.dataType} for column '${col.name}'`);
54
61
  }
55
62
  }
56
63
  }
@@ -69,18 +76,18 @@ Database.prototype.readSetsById = function (
69
76
  for (const group of groups) {
70
77
  for (const col of group.valueColumns) {
71
78
  switch (col.dataType) {
72
- case 0: // INTEGER
79
+ case DATA_TYPE_INTEGER:
73
80
  result[col.name] = this.readSetIntegersById(collection, col.name, id);
74
81
  break;
75
- case 1: // FLOAT
82
+ case DATA_TYPE_FLOAT:
76
83
  result[col.name] = this.readSetFloatsById(collection, col.name, id);
77
84
  break;
78
- case 2: // STRING
79
- case 3: // DATE_TIME
85
+ case DATA_TYPE_STRING:
86
+ case DATA_TYPE_DATE_TIME:
80
87
  result[col.name] = this.readSetStringsById(collection, col.name, id);
81
88
  break;
82
89
  default:
83
- throw new Error(`Unknown data type ${col.dataType} for column '${col.name}'`);
90
+ throw new QuiverError(`Unknown data type ${col.dataType} for column '${col.name}'`);
84
91
  }
85
92
  }
86
93
  }
package/src/create.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { ptr } from "bun:ffi";
2
1
  import { Database } from "./database.ts";
3
2
  import { check, QuiverError } from "./errors.ts";
4
3
  import {
@@ -30,8 +29,8 @@ function setElementArray(
30
29
  const first = values[0];
31
30
 
32
31
  if (typeof first === "bigint") {
33
- const arr = allocNativeInt64((values as bigint[]).map(Number));
34
- check(lib.quiver_element_set_array_integer(elemPtr, nameBuf.buf, arr.ptr, values.length));
32
+ const arr = allocNativeInt64(values as bigint[]);
33
+ check(lib.quiver_element_set_array_integer(elemPtr, nameBuf.buf, arr.buf, values.length));
35
34
  return;
36
35
  }
37
36
 
@@ -39,17 +38,17 @@ function setElementArray(
39
38
  const allIntegers = (values as number[]).every((v) => Number.isInteger(v));
40
39
  if (allIntegers) {
41
40
  const arr = allocNativeInt64(values as number[]);
42
- check(lib.quiver_element_set_array_integer(elemPtr, nameBuf.buf, arr.ptr, values.length));
41
+ check(lib.quiver_element_set_array_integer(elemPtr, nameBuf.buf, arr.buf, values.length));
43
42
  } else {
44
43
  const arr = allocNativeFloat64(values as number[]);
45
- check(lib.quiver_element_set_array_float(elemPtr, nameBuf.buf, arr.ptr, values.length));
44
+ check(lib.quiver_element_set_array_float(elemPtr, nameBuf.buf, arr.buf, values.length));
46
45
  }
47
46
  return;
48
47
  }
49
48
 
50
49
  if (typeof first === "string") {
51
50
  const { table, keepalive: _keepalive } = allocNativeStringArray(values as string[]);
52
- check(lib.quiver_element_set_array_string(elemPtr, nameBuf.buf, table.ptr, values.length));
51
+ check(lib.quiver_element_set_array_string(elemPtr, nameBuf.buf, table.buf, values.length));
53
52
  return;
54
53
  }
55
54
 
@@ -101,7 +100,7 @@ Database.prototype.createElement = function (
101
100
  const handle = this._handle;
102
101
 
103
102
  const outElem = allocPtrOut();
104
- check(lib.quiver_element_create(outElem.ptr));
103
+ check(lib.quiver_element_create(outElem.buf));
105
104
  const elemPtr = readPtrOut(outElem);
106
105
 
107
106
  try {
@@ -111,9 +110,8 @@ Database.prototype.createElement = function (
111
110
  }
112
111
 
113
112
  const outIdBuf = new Uint8Array(8);
114
- const outIdPtr = ptr(outIdBuf);
115
113
  const collBuf = toCString(collection);
116
- check(lib.quiver_database_create_element(handle, collBuf.buf, elemPtr, outIdPtr));
114
+ check(lib.quiver_database_create_element(handle, collBuf.buf, elemPtr, outIdBuf));
117
115
  return Number(new DataView(outIdBuf.buffer).getBigInt64(0, true));
118
116
  } finally {
119
117
  lib.quiver_element_destroy(elemPtr);
@@ -130,7 +128,7 @@ Database.prototype.updateElement = function (
130
128
  const handle = this._handle;
131
129
 
132
130
  const outElem = allocPtrOut();
133
- check(lib.quiver_element_create(outElem.ptr));
131
+ check(lib.quiver_element_create(outElem.buf));
134
132
  const elemPtr = readPtrOut(outElem);
135
133
 
136
134
  try {
package/src/csv.ts CHANGED
@@ -96,7 +96,7 @@ Database.prototype.exportCsv = function (
96
96
  const pathBuf = toCString(filePath);
97
97
  const [optsBuf, _keepalive] = buildCsvOptionsBuffer(options);
98
98
  check(
99
- lib.quiver_database_export_csv(this._handle, collBuf.buf, grpBuf.buf, pathBuf.buf, optsBuf.ptr),
99
+ lib.quiver_database_export_csv(this._handle, collBuf.buf, grpBuf.buf, pathBuf.buf, optsBuf.buf),
100
100
  );
101
101
  };
102
102
 
@@ -113,6 +113,6 @@ Database.prototype.importCsv = function (
113
113
  const pathBuf = toCString(filePath);
114
114
  const [optsBuf, _keepalive] = buildCsvOptionsBuffer(options);
115
115
  check(
116
- lib.quiver_database_import_csv(this._handle, collBuf.buf, grpBuf.buf, pathBuf.buf, optsBuf.ptr),
116
+ lib.quiver_database_import_csv(this._handle, collBuf.buf, grpBuf.buf, pathBuf.buf, optsBuf.buf),
117
117
  );
118
118
  };
package/src/database.ts CHANGED
@@ -5,7 +5,7 @@ import type { NativePointer } from "./loader.ts";
5
5
  import { getSymbols } from "./loader.ts";
6
6
  import type { GroupMetadata, ScalarMetadata } from "./metadata.ts";
7
7
  import type { TimeSeriesData } from "./time-series.ts";
8
- import type { ElementData, QueryParam } from "./types.ts";
8
+ import type { DatabaseOptions, ElementData, QueryParam } from "./types.ts";
9
9
 
10
10
  export class Database {
11
11
  private _ptr: NativePointer;
@@ -15,41 +15,50 @@ export class Database {
15
15
  this._ptr = nativePtr;
16
16
  }
17
17
 
18
- static fromSchema(dbPath: string, schemaPath: string): Database {
18
+ static fromSchema(dbPath: string, schemaPath: string, options?: DatabaseOptions): Database {
19
19
  const lib = getSymbols();
20
- const options = makeDefaultOptions();
20
+ const optionsBuf = makeDefaultOptions(options);
21
21
  const outDb = allocPtrOut();
22
22
  const dbPathBuf = toCString(dbPath);
23
23
  const schemaPathBuf = toCString(schemaPath);
24
24
 
25
25
  check(
26
- lib.quiver_database_from_schema(dbPathBuf.buf, schemaPathBuf.buf, options.buf, outDb.ptr),
26
+ lib.quiver_database_from_schema(dbPathBuf.buf, schemaPathBuf.buf, optionsBuf.buf, outDb.buf),
27
27
  );
28
28
 
29
29
  return new Database(readPtrOut(outDb));
30
30
  }
31
31
 
32
- static fromMigrations(dbPath: string, migrationsPath: string): Database {
32
+ static fromMigrations(
33
+ dbPath: string,
34
+ migrationsPath: string,
35
+ options?: DatabaseOptions,
36
+ ): Database {
33
37
  const lib = getSymbols();
34
- const options = makeDefaultOptions();
38
+ const optionsBuf = makeDefaultOptions(options);
35
39
  const outDb = allocPtrOut();
36
40
  const dbPathBuf = toCString(dbPath);
37
41
  const migrPathBuf = toCString(migrationsPath);
38
42
 
39
43
  check(
40
- lib.quiver_database_from_migrations(dbPathBuf.buf, migrPathBuf.buf, options.buf, outDb.ptr),
44
+ lib.quiver_database_from_migrations(
45
+ dbPathBuf.buf,
46
+ migrPathBuf.buf,
47
+ optionsBuf.buf,
48
+ outDb.buf,
49
+ ),
41
50
  );
42
51
 
43
52
  return new Database(readPtrOut(outDb));
44
53
  }
45
54
 
46
- static open(dbPath: string): Database {
55
+ static open(dbPath: string, options?: DatabaseOptions): Database {
47
56
  const lib = getSymbols();
48
- const options = makeDefaultOptions();
57
+ const optionsBuf = makeDefaultOptions(options);
49
58
  const outDb = allocPtrOut();
50
59
  const dbPathBuf = toCString(dbPath);
51
60
 
52
- check(lib.quiver_database_open(dbPathBuf.buf, options.buf, outDb.ptr));
61
+ check(lib.quiver_database_open(dbPathBuf.buf, optionsBuf.buf, outDb.buf));
53
62
 
54
63
  return new Database(readPtrOut(outDb));
55
64
  }
@@ -130,12 +139,24 @@ export class Database {
130
139
 
131
140
  // --- Time series (implemented in time-series.ts) ---
132
141
  declare readTimeSeriesGroup: (collection: string, group: string, id: number) => TimeSeriesData;
142
+ declare readTimeSeriesRow: (
143
+ collection: string,
144
+ group: string,
145
+ attribute: string,
146
+ dateTime: string,
147
+ ) => (number | string | null)[];
133
148
  declare updateTimeSeriesGroup: (
134
149
  collection: string,
135
150
  group: string,
136
151
  id: number,
137
152
  data: TimeSeriesData,
138
153
  ) => void;
154
+ declare addTimeSeriesRow: (
155
+ collection: string,
156
+ group: string,
157
+ id: number,
158
+ row: Record<string, number | bigint | string>,
159
+ ) => void;
139
160
  declare hasTimeSeriesFiles: (collection: string) => boolean;
140
161
  declare listTimeSeriesFilesColumns: (collection: string) => string[];
141
162
  declare readTimeSeriesFiles: (collection: string) => Record<string, string | null>;
@@ -159,7 +180,9 @@ export class Database {
159
180
  declare isHealthy: () => boolean;
160
181
  declare currentVersion: () => number;
161
182
  declare path: () => string;
162
- declare describe: () => void;
183
+ declare describe: () => string;
184
+ declare describeCollection: (collection: string) => string;
185
+ declare summarizeCollection: (collection: string) => string;
163
186
 
164
187
  // --- Composite helpers (implemented in composites.ts) ---
165
188
  declare readScalarsById: (
@@ -1,5 +1,5 @@
1
1
  import { CString, type Pointer, ptr, read, toArrayBuffer } from "bun:ffi";
2
- import type { Allocation } from "./types.ts";
2
+ import { type Allocation, type DatabaseOptions, LOG_LEVEL_INFO } from "./types.ts";
3
3
 
4
4
  const encoder = new TextEncoder();
5
5
 
@@ -7,11 +7,11 @@ const encoder = new TextEncoder();
7
7
  * Construct the 8-byte quiver_database_options_t struct as an Allocation.
8
8
  * Layout: offset 0 = int32 read_only (default 0), offset 4 = int32 console_level (default 1 = QUIVER_LOG_INFO).
9
9
  */
10
- export function makeDefaultOptions(): Allocation {
10
+ export function makeDefaultOptions(options?: DatabaseOptions): Allocation {
11
11
  const buf = new Uint8Array(8);
12
12
  const dv = new DataView(buf.buffer);
13
- dv.setInt32(0, 0, true); // read_only = false
14
- dv.setInt32(4, 1, true); // console_level = QUIVER_LOG_INFO
13
+ dv.setInt32(0, options?.readOnly ? 1 : 0, true);
14
+ dv.setInt32(4, options?.consoleLevel ?? LOG_LEVEL_INFO, true);
15
15
  return { ptr: ptr(buf), buf };
16
16
  }
17
17
 
@@ -102,7 +102,7 @@ export function toCString(str: string): Allocation {
102
102
  }
103
103
 
104
104
  /** Allocate native memory for an array of int64 values. */
105
- export function allocNativeInt64(values: number[]): Allocation {
105
+ export function allocNativeInt64(values: (number | bigint)[]): Allocation {
106
106
  const buf = new Uint8Array(values.length * 8);
107
107
  const dv = new DataView(buf.buffer);
108
108
  for (let i = 0; i < values.length; i++) {
package/src/index.ts CHANGED
@@ -11,7 +11,22 @@ import "./composites.ts";
11
11
  export type { CsvOptions } from "./csv.ts";
12
12
  export { Database } from "./database.ts";
13
13
  export { QuiverError } from "./errors.ts";
14
+ export { LUA_DB_API_REFERENCE } from "./lua-api.ts";
14
15
  export { LuaRunner } from "./lua-runner.ts";
15
16
  export type { GroupMetadata, ScalarMetadata } from "./metadata.ts";
16
17
  export type { TimeSeriesData } from "./time-series.ts";
17
- export type { ArrayValue, ElementData, QueryParam, ScalarValue, Value } from "./types.ts";
18
+ export type {
19
+ ArrayValue,
20
+ DatabaseOptions,
21
+ ElementData,
22
+ QueryParam,
23
+ ScalarValue,
24
+ Value,
25
+ } from "./types.ts";
26
+ export {
27
+ LOG_LEVEL_DEBUG,
28
+ LOG_LEVEL_ERROR,
29
+ LOG_LEVEL_INFO,
30
+ LOG_LEVEL_OFF,
31
+ LOG_LEVEL_WARN,
32
+ } from "./types.ts";
@@ -1,33 +1,54 @@
1
- import { ptr } from "bun:ffi";
2
1
  import { Database } from "./database.ts";
3
2
  import { check } from "./errors.ts";
4
- import { allocPtrOut, decodeStringFromBuf, toCString } from "./ffi-helpers.ts";
3
+ import { allocPtrOut, decodeStringFromBuf, readPtrOut, toCString } from "./ffi-helpers.ts";
5
4
  import { getSymbols } from "./loader.ts";
6
5
 
7
6
  Database.prototype.isHealthy = function (this: Database): boolean {
8
7
  const lib = getSymbols();
9
8
  const outBuf = new Uint8Array(4);
10
- const outPtr = ptr(outBuf);
11
- check(lib.quiver_database_is_healthy(this._handle, outPtr));
9
+ check(lib.quiver_database_is_healthy(this._handle, outBuf));
12
10
  return new DataView(outBuf.buffer).getInt32(0, true) !== 0;
13
11
  };
14
12
 
15
13
  Database.prototype.currentVersion = function (this: Database): number {
16
14
  const lib = getSymbols();
17
15
  const outBuf = new Uint8Array(8);
18
- const outPtr = ptr(outBuf);
19
- check(lib.quiver_database_current_version(this._handle, outPtr));
16
+ check(lib.quiver_database_current_version(this._handle, outBuf));
20
17
  return Number(new DataView(outBuf.buffer).getBigInt64(0, true));
21
18
  };
22
19
 
23
20
  Database.prototype.path = function (this: Database): string {
24
21
  const lib = getSymbols();
25
22
  const outPath = allocPtrOut();
26
- check(lib.quiver_database_path(this._handle, outPath.ptr));
23
+ check(lib.quiver_database_path(this._handle, outPath.buf));
27
24
  return decodeStringFromBuf(outPath);
28
25
  };
29
26
 
30
- Database.prototype.describe = function (this: Database): void {
27
+ Database.prototype.describe = function (this: Database): string {
31
28
  const lib = getSymbols();
32
- check(lib.quiver_database_describe(this._handle));
29
+ const out = allocPtrOut();
30
+ check(lib.quiver_database_describe(this._handle, out.buf));
31
+ const result = decodeStringFromBuf(out);
32
+ lib.quiver_database_free_string(readPtrOut(out));
33
+ return result;
34
+ };
35
+
36
+ Database.prototype.describeCollection = function (this: Database, collection: string): string {
37
+ const lib = getSymbols();
38
+ const collBuf = toCString(collection);
39
+ const out = allocPtrOut();
40
+ check(lib.quiver_database_describe_collection(this._handle, collBuf.buf, out.buf));
41
+ const result = decodeStringFromBuf(out);
42
+ lib.quiver_database_free_string(readPtrOut(out));
43
+ return result;
44
+ };
45
+
46
+ Database.prototype.summarizeCollection = function (this: Database, collection: string): string {
47
+ const lib = getSymbols();
48
+ const collBuf = toCString(collection);
49
+ const out = allocPtrOut();
50
+ check(lib.quiver_database_summarize_collection(this._handle, collBuf.buf, out.buf));
51
+ const result = decodeStringFromBuf(out);
52
+ lib.quiver_database_free_string(readPtrOut(out));
53
+ return result;
33
54
  };
package/src/loader.ts CHANGED
@@ -13,7 +13,6 @@ const I32 = "i32" as const;
13
13
  const I64 = "i64" as const;
14
14
  const USIZE = "usize" as const;
15
15
  const F64 = "f64" as const;
16
- const V = "void" as const;
17
16
 
18
17
  // Platform constants. `suffix` from bun:ffi is the platform-correct shared
19
18
  // library extension ("dll" | "dylib" | "so").
@@ -30,7 +29,6 @@ export type NativePointer = Pointer | null;
30
29
  const lifecycleSymbols = {
31
30
  quiver_version: { args: [], returns: P },
32
31
  quiver_get_last_error: { args: [], returns: P },
33
- quiver_clear_last_error: { args: [], returns: V },
34
32
  // quiver_database_options_default is intentionally omitted: it returns a
35
33
  // struct by value, which Bun FFI does not support (oven-sh/bun#6139). It was
36
34
  // never called -- makeDefaultOptions() in ffi-helpers.ts builds the options
@@ -42,7 +40,7 @@ const lifecycleSymbols = {
42
40
  quiver_database_is_healthy: { args: [P, P], returns: I32 },
43
41
  quiver_database_path: { args: [P, P], returns: I32 },
44
42
  quiver_database_current_version: { args: [P, P], returns: I32 },
45
- quiver_database_describe: { args: [P], returns: I32 },
43
+ quiver_database_describe: { args: [P, P], returns: I32 },
46
44
  } as const;
47
45
 
48
46
  const elementSymbols = {
@@ -114,8 +112,15 @@ const metadataSymbols = {
114
112
  quiver_database_list_time_series_groups: { args: [P, BUF, P, P], returns: I32 },
115
113
  } as const;
116
114
 
115
+ const describeSymbols = {
116
+ quiver_database_describe_collection: { args: [P, BUF, P], returns: I32 },
117
+ quiver_database_summarize_collection: { args: [P, BUF, P], returns: I32 },
118
+ } as const;
119
+
117
120
  const timeSeriesSymbols = {
118
121
  quiver_database_read_time_series_group: { args: [P, BUF, BUF, I64, P, P, P, P, P], returns: I32 },
122
+ quiver_database_read_time_series_row: { args: [P, BUF, BUF, BUF, BUF, P, P, P], returns: I32 },
123
+ quiver_database_add_time_series_row: { args: [P, BUF, BUF, I64, P, P, P, USIZE], returns: I32 },
119
124
  quiver_database_update_time_series_group: {
120
125
  args: [P, BUF, BUF, I64, P, P, P, USIZE, USIZE],
121
126
  returns: I32,
@@ -149,7 +154,6 @@ const luaSymbols = {
149
154
  quiver_lua_runner_new: { args: [P, P], returns: I32 },
150
155
  quiver_lua_runner_free: { args: [P], returns: I32 },
151
156
  quiver_lua_runner_run: { args: [P, BUF], returns: I32 },
152
- quiver_lua_runner_get_error: { args: [P, P], returns: I32 },
153
157
  } as const;
154
158
 
155
159
  // Combined symbol map for dlopen.
@@ -161,6 +165,7 @@ const allSymbols = {
161
165
  ...querySymbols,
162
166
  ...transactionSymbols,
163
167
  ...metadataSymbols,
168
+ ...describeSymbols,
164
169
  ...timeSeriesSymbols,
165
170
  ...csvSymbols,
166
171
  ...freeSymbols,
@@ -281,5 +286,3 @@ export function loadLibrary(): QuiverLib {
281
286
  export function getSymbols() {
282
287
  return loadLibrary().symbols;
283
288
  }
284
-
285
- export type Symbols = ReturnType<typeof getSymbols>;