@sqd-pipes/delta-db 0.0.1-alpha.6 → 0.0.1-alpha.8

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
@@ -1,83 +1,173 @@
1
- # @subsquid/delta-db
1
+ # @sqd-pipes/delta-db
2
2
 
3
- Embedded rollback-aware computation engine for blockchain data. Routes raw events through **reducers** and **materialized views**, producing delta records (insert/update/delete) for downstream targets.
3
+ Embedded rollback-aware computation engine for blockchain data. Routes raw events through **reducers** (TypeScript functions) and **materialized views**, producing delta records (insert/update/delete) for downstream targets.
4
4
 
5
- ## Build
6
-
7
- Requires **Rust** (stable) and **Node.js** >= 18.
5
+ ## Install
8
6
 
9
7
  ```bash
10
- cd packages/delta-db-node
11
- npm install
8
+ pnpm add @sqd-pipes/delta-db
9
+ ```
12
10
 
13
- # Debug build
14
- npx napi build --cargo-cwd ../.. --features napi
11
+ ## Build from source
12
+
13
+ Requires **Rust** (stable) and **Node.js** >= 18.
15
14
 
16
- # Release build
17
- npx napi build --cargo-cwd ../.. --features napi --release
15
+ ```bash
16
+ pnpm install
17
+ pnpm run build # release
18
+ pnpm run build:debug # debug
18
19
  ```
19
20
 
20
- This produces `delta-db.node` (native binary) and regenerates `index.d.ts`.
21
+ ## Quick start
21
22
 
22
- If `index.js` is missing after build, create it:
23
+ ```typescript
24
+ import { Pipeline, uint64, string, float64, interval } from '@sqd-pipes/delta-db'
23
25
 
24
- ```js
25
- const { DeltaDb } = require('./delta-db.node')
26
- module.exports.DeltaDb = DeltaDb
27
- ```
26
+ const p = new Pipeline()
28
27
 
29
- ## Test
28
+ const swaps = p.table('swaps', {
29
+ block_number: uint64(),
30
+ pool: string(),
31
+ amount: float64(),
32
+ })
30
33
 
31
- ```bash
32
- npm test
34
+ swaps
35
+ .createReducer('totals', {
36
+ groupBy: 'pool',
37
+ initialState: { volume: 0 },
38
+ reduce(state, row) {
39
+ const volume = state.volume + row.amount
40
+ return [{ volume }, { pool: row.pool, volume }]
41
+ },
42
+ })
43
+ .createView('pool_volume', {
44
+ groupBy: ['pool'],
45
+ select: (agg) => ({
46
+ pool: agg.key.pool,
47
+ totalVolume: agg.sum('volume'),
48
+ tradeCount: agg.count(),
49
+ }),
50
+ })
51
+
52
+ const db = p.build() // in-memory
53
+ // const db = p.build({ dataDir: './data' }) // persistent (RocksDB)
54
+
55
+ db.processBatch('swaps', 1000, [
56
+ { pool: 'ETH/USDC', amount: 100 },
57
+ { pool: 'ETH/USDC', amount: 200 },
58
+ ])
59
+
60
+ const batch = db.flush()!
61
+ // batch.tables.pool_volume → [{ key: { pool: 'ETH/USDC' }, values: { totalVolume: 300, tradeCount: 2 } }]
33
62
  ```
34
63
 
35
- ## Usage
64
+ ## API
36
65
 
37
- ### Direct API
66
+ ### Pipeline builder
38
67
 
39
68
  ```typescript
40
- import { DeltaDb } from '@subsquid/delta-db'
41
-
42
- const db = DeltaDb.open({
43
- schema: `
44
- CREATE TABLE swaps (
45
- block_number UInt64,
46
- pool String,
47
- amount Float64
48
- );
49
- CREATE MATERIALIZED VIEW volume AS
50
- SELECT pool, sum(amount) AS total, count() AS cnt
51
- FROM swaps GROUP BY pool;
52
- `,
53
- dataDir: './data', // optional, enables persistence
69
+ const p = new Pipeline()
70
+
71
+ // Define a table — column types are inferred into the row type
72
+ const table = p.table('name', {
73
+ block_number: uint64(),
74
+ user: string(),
75
+ amount: float64(),
76
+ timestamp: datetime(),
77
+ metadata: json<MyType>(), // json() is generic
54
78
  })
55
79
 
56
- const batch = db.ingest({
57
- data: {
58
- swaps: [
59
- { block_number: 1000, pool: 'ETH/USDC', amount: 100 },
60
- ],
80
+ // Create a reducer from a table (or another reducer)
81
+ const reducer = table.createReducer('reducer_name', {
82
+ groupBy: 'user', // validated against row keys
83
+ initialState: { total: 0 }, // state type inferred
84
+ reduce(state, row) { // state & row fully typed
85
+ return [
86
+ { total: state.total + row.amount }, // new state
87
+ { user: row.user, total: ... }, // emit (or null to skip)
88
+ ]
61
89
  },
62
- rollbackChain: [{ number: 1000, hash: '0x...' }],
63
- finalizedHead: { number: 999, hash: '0x...' },
64
90
  })
65
- // batch.records → [{ table: 'swaps', op: 'insert', ... }, { table: 'volume', op: 'insert', ... }]
91
+
92
+ // Chain a reducer from another reducer's output
93
+ const chained = reducer.createReducer('downstream', { ... })
94
+
95
+ // Create a materialized view
96
+ reducer.createView('summary', {
97
+ groupBy: ['user'],
98
+ select: (agg) => ({
99
+ user: agg.key.user,
100
+ total: agg.sum('total'), // validated against emit keys
101
+ count: agg.count(),
102
+ first: agg.first('total'),
103
+ last: agg.last('total'),
104
+ }),
105
+ })
106
+
107
+ // Time-window grouping
108
+ reducer.createView('candles_5m', {
109
+ groupBy: ['pool', interval('timestamp', '5 minutes').as('window_start')],
110
+ select: (agg) => ({
111
+ pool: agg.key.pool,
112
+ windowStart: agg.key.window_start,
113
+ open: agg.first('price'),
114
+ high: agg.max('price'),
115
+ low: agg.min('price'),
116
+ close: agg.last('price'),
117
+ volume: agg.sum('volume'),
118
+ }),
119
+ })
120
+
121
+ // Build the database
122
+ const db = p.build() // in-memory
123
+ const db = p.build({ dataDir: './data' }) // RocksDB persistence
124
+ const db = p.build({ dataDir: ':memory:' }) // explicit in-memory (SQLite convention)
66
125
  ```
67
126
 
68
- ### Pipes SDK
127
+ ### Column types
128
+
129
+ | Function | SQL type | TypeScript type |
130
+ |-------------|------------|-----------------|
131
+ | `uint64()` | `UInt64` | `number` |
132
+ | `int64()` | `Int64` | `number` |
133
+ | `float64()` | `Float64` | `number` |
134
+ | `uint256()` | `Uint256` | `bigint` |
135
+ | `string()` | `String` | `string` |
136
+ | `datetime()` | `DateTime` | `number` |
137
+ | `boolean()` | `Boolean` | `boolean` |
138
+ | `bytes()` | `Bytes` | `Uint8Array` |
139
+ | `base58()` | `Base58` | `string` |
140
+ | `json<T>()` | `Json` | `T` (default `any`) |
141
+
142
+ ### DeltaDb (low-level)
69
143
 
70
144
  ```typescript
71
- import { deltaDbTarget } from '@subsquid/delta-db/pipes'
72
-
73
- await source
74
- .pipe(decoder)
75
- .pipeTo(deltaDbTarget({
76
- schema: '...',
77
- dataDir: './data',
78
- transform: (data) => ({ transfers: data.transfers.map(formatRow) }),
79
- onDelta: async ({ batch }) => {
80
- await clickhouse.insert(batch.records)
81
- },
82
- }))
145
+ import { DeltaDb } from '@sqd-pipes/delta-db'
146
+
147
+ const db = DeltaDb.open({ schema: 'CREATE TABLE ...', dataDir: './data' })
148
+
149
+ db.processBatch('table', blockNumber, rows)
150
+ db.rollback(forkPoint)
151
+ db.finalize(blockNumber)
152
+ db.flush() // DeltaBatch | null
153
+ db.ingest(input) // atomic: process + finalize + flush
154
+ ```
155
+
156
+ ### Aggregation functions
157
+
158
+ `sum`, `count`, `min`, `max`, `avg`, `first`, `last`
159
+
160
+ ### Virtual tables
161
+
162
+ Tables declared with `{ virtual: true }` are processed by reducers but don't emit raw row deltas:
163
+
164
+ ```typescript
165
+ const orders = p.table('orders', { ... }, { virtual: true })
166
+ ```
167
+
168
+ ## Test
169
+
170
+ ```bash
171
+ pnpm test
172
+ pnpm run lint
83
173
  ```
@@ -0,0 +1,20 @@
1
+ export interface ColumnType<T = any> {
2
+ readonly _sql: string;
3
+ /** Phantom field for type inference — not present at runtime. */
4
+ readonly _type?: T;
5
+ }
6
+ export declare const uint64: () => ColumnType<number>;
7
+ export declare const int64: () => ColumnType<number>;
8
+ export declare const float64: () => ColumnType<number>;
9
+ export declare const uint256: () => ColumnType<bigint>;
10
+ export declare const string: () => ColumnType<string>;
11
+ export declare const datetime: () => ColumnType<number>;
12
+ export declare const boolean: () => ColumnType<boolean>;
13
+ export declare const bytes: () => ColumnType<Uint8Array<ArrayBufferLike>>;
14
+ export declare const base58: () => ColumnType<string>;
15
+ export declare function json<T = any>(): ColumnType<T>;
16
+ /** Infer the row type from a column definition record. */
17
+ export type InferRow<T extends Record<string, ColumnType>> = {
18
+ [K in keyof T]: T[K] extends ColumnType<infer V> ? V : unknown;
19
+ };
20
+ //# sourceMappingURL=column.d.ts.map
package/dist/column.js ADDED
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.base58 = exports.bytes = exports.boolean = exports.datetime = exports.string = exports.uint256 = exports.float64 = exports.int64 = exports.uint64 = void 0;
4
+ exports.json = json;
5
+ function col(sql) {
6
+ return () => ({ _sql: sql });
7
+ }
8
+ exports.uint64 = col('UInt64');
9
+ exports.int64 = col('Int64');
10
+ exports.float64 = col('Float64');
11
+ exports.uint256 = col('Uint256');
12
+ exports.string = col('String');
13
+ exports.datetime = col('DateTime');
14
+ exports.boolean = col('Boolean');
15
+ exports.bytes = col('Bytes');
16
+ exports.base58 = col('Base58');
17
+ function json() {
18
+ return { _sql: 'Json' };
19
+ }
20
+ //# sourceMappingURL=column.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column.js","sourceRoot":"","sources":["../src/column.ts"],"names":[],"mappings":";;;AAmBA,oBAEC;AAfD,SAAS,GAAG,CAAI,GAAW;IACzB,OAAO,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAA;AAC9B,CAAC;AAEY,QAAA,MAAM,GAAG,GAAG,CAAS,QAAQ,CAAC,CAAA;AAC9B,QAAA,KAAK,GAAG,GAAG,CAAS,OAAO,CAAC,CAAA;AAC5B,QAAA,OAAO,GAAG,GAAG,CAAS,SAAS,CAAC,CAAA;AAChC,QAAA,OAAO,GAAG,GAAG,CAAS,SAAS,CAAC,CAAA;AAChC,QAAA,MAAM,GAAG,GAAG,CAAS,QAAQ,CAAC,CAAA;AAC9B,QAAA,QAAQ,GAAG,GAAG,CAAS,UAAU,CAAC,CAAA;AAClC,QAAA,OAAO,GAAG,GAAG,CAAU,SAAS,CAAC,CAAA;AACjC,QAAA,KAAK,GAAG,GAAG,CAAa,OAAO,CAAC,CAAA;AAChC,QAAA,MAAM,GAAG,GAAG,CAAS,QAAQ,CAAC,CAAA;AAC3C,SAAgB,IAAI;IAClB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;AACzB,CAAC"}
package/dist/ddl.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ import type { ColumnType } from './column';
2
+ import type { StateFieldDef } from './delta-db';
3
+ export declare function parseDuration(s: string): number;
4
+ export interface IntervalExpr {
5
+ _type: 'interval';
6
+ column: string;
7
+ seconds: number;
8
+ alias?: string;
9
+ as(alias: string): IntervalExpr;
10
+ }
11
+ export declare function interval(column: string, duration: string): IntervalExpr;
12
+ export interface AggExpr {
13
+ _type: 'agg';
14
+ func: string;
15
+ column: string | null;
16
+ }
17
+ export interface KeyRef {
18
+ _type: 'key';
19
+ column: string;
20
+ }
21
+ export interface AggProxy<TSource = any> {
22
+ key: Record<string, KeyRef>;
23
+ sum(column: string & keyof TSource): AggExpr;
24
+ count(): AggExpr;
25
+ first(column: string & keyof TSource): AggExpr;
26
+ last(column: string & keyof TSource): AggExpr;
27
+ min(column: string & keyof TSource): AggExpr;
28
+ max(column: string & keyof TSource): AggExpr;
29
+ avg(column: string & keyof TSource): AggExpr;
30
+ }
31
+ export type GroupByItem = string | IntervalExpr;
32
+ export interface ReducerOptions<TState, TRow, TEmit> {
33
+ groupBy: (string & keyof TRow) | (string & keyof TRow)[];
34
+ initialState: TState;
35
+ reduce: (state: TState, row: TRow) => [TState, TEmit | TEmit[] | null];
36
+ }
37
+ export interface ViewOptions<TSource = any> {
38
+ groupBy: GroupByItem | GroupByItem[];
39
+ select: (agg: AggProxy<TSource>) => Record<string, AggExpr | KeyRef>;
40
+ }
41
+ export declare function inferStateFields(initialState: Record<string, unknown>): StateFieldDef[];
42
+ export declare function tableToSql(name: string, columns: Record<string, ColumnType>, virtual: boolean): string;
43
+ export declare function reducerToSql(name: string, source: string, groupBy: string[], stateFields: StateFieldDef[]): string;
44
+ export declare function viewToSql(name: string, source: string, groupByItems: GroupByItem[], selectFn: (agg: AggProxy<any>) => Record<string, AggExpr | KeyRef>): string;
45
+ //# sourceMappingURL=ddl.d.ts.map
package/dist/ddl.js ADDED
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseDuration = parseDuration;
4
+ exports.interval = interval;
5
+ exports.inferStateFields = inferStateFields;
6
+ exports.tableToSql = tableToSql;
7
+ exports.reducerToSql = reducerToSql;
8
+ exports.viewToSql = viewToSql;
9
+ // ─── Duration parsing ────────────────────────────────────────────
10
+ const DURATION_UNITS = {
11
+ second: 1,
12
+ seconds: 1,
13
+ sec: 1,
14
+ s: 1,
15
+ minute: 60,
16
+ minutes: 60,
17
+ min: 60,
18
+ m: 60,
19
+ hour: 3600,
20
+ hours: 3600,
21
+ hr: 3600,
22
+ h: 3600,
23
+ day: 86400,
24
+ days: 86400,
25
+ d: 86400,
26
+ };
27
+ function parseDuration(s) {
28
+ const match = s.trim().match(/^(\d+)\s*(\w+)$/);
29
+ if (!match) {
30
+ throw new Error(`invalid duration: '${s}'`);
31
+ }
32
+ const n = parseInt(match[1], 10);
33
+ const unit = match[2].toLowerCase();
34
+ const mult = DURATION_UNITS[unit];
35
+ if (!mult) {
36
+ throw new Error(`unknown duration unit: '${unit}'`);
37
+ }
38
+ return n * mult;
39
+ }
40
+ function makeInterval(column, seconds, alias) {
41
+ return {
42
+ _type: 'interval',
43
+ column,
44
+ seconds,
45
+ alias,
46
+ as(a) {
47
+ return makeInterval(column, seconds, a);
48
+ },
49
+ };
50
+ }
51
+ function interval(column, duration) {
52
+ return makeInterval(column, parseDuration(duration));
53
+ }
54
+ // ─── Type inference from initialState ────────────────────────────
55
+ function inferStateFields(initialState) {
56
+ const fields = [];
57
+ for (const [name, value] of Object.entries(initialState)) {
58
+ let columnType;
59
+ let defaultValue;
60
+ switch (typeof value) {
61
+ case 'number':
62
+ columnType = 'Float64';
63
+ defaultValue = String(value);
64
+ break;
65
+ case 'bigint':
66
+ columnType = 'UInt64';
67
+ defaultValue = String(value);
68
+ break;
69
+ case 'string':
70
+ columnType = 'String';
71
+ defaultValue = `'${value}'`;
72
+ break;
73
+ case 'boolean':
74
+ columnType = 'Boolean';
75
+ defaultValue = value ? 'true' : 'false';
76
+ break;
77
+ case 'object':
78
+ columnType = 'Json';
79
+ defaultValue = `'${JSON.stringify(value)}'`;
80
+ break;
81
+ default:
82
+ columnType = 'String';
83
+ defaultValue = `'${String(value)}'`;
84
+ }
85
+ fields.push({ name, columnType, defaultValue });
86
+ }
87
+ return fields;
88
+ }
89
+ // ─── DDL generators ──────────────────────────────────────────────
90
+ function tableToSql(name, columns, virtual) {
91
+ const prefix = virtual ? 'CREATE VIRTUAL TABLE' : 'CREATE TABLE';
92
+ const cols = Object.entries(columns)
93
+ .map(([name, ct]) => `${name} ${ct._sql}`)
94
+ .join(', ');
95
+ return `${prefix} ${name} (${cols});`;
96
+ }
97
+ function reducerToSql(name, source, groupBy, stateFields) {
98
+ const gb = groupBy.join(', ');
99
+ const state = stateFields
100
+ .map((f) => `${f.name} ${f.columnType} DEFAULT ${f.defaultValue}`)
101
+ .join(', ');
102
+ return `CREATE REDUCER ${name} SOURCE ${source} GROUP BY ${gb} STATE (${state}) LANGUAGE EXTERNAL;`;
103
+ }
104
+ function viewToSql(name, source, groupByItems, selectFn) {
105
+ const groupByCols = [];
106
+ const intervalDefs = [];
107
+ for (const item of groupByItems) {
108
+ if (typeof item === 'string') {
109
+ groupByCols.push(item);
110
+ }
111
+ else if (item._type === 'interval') {
112
+ const alias = item.alias || `${item.column}_interval`;
113
+ intervalDefs.push({ column: item.column, seconds: item.seconds, alias });
114
+ groupByCols.push(alias);
115
+ }
116
+ }
117
+ const keyProxy = new Proxy({}, {
118
+ get(_target, prop) {
119
+ return { _type: 'key', column: prop };
120
+ },
121
+ });
122
+ const aggProxy = {
123
+ key: keyProxy,
124
+ sum(col) {
125
+ return { _type: 'agg', func: 'sum', column: col };
126
+ },
127
+ count() {
128
+ return { _type: 'agg', func: 'count', column: null };
129
+ },
130
+ first(col) {
131
+ return { _type: 'agg', func: 'first', column: col };
132
+ },
133
+ last(col) {
134
+ return { _type: 'agg', func: 'last', column: col };
135
+ },
136
+ min(col) {
137
+ return { _type: 'agg', func: 'min', column: col };
138
+ },
139
+ max(col) {
140
+ return { _type: 'agg', func: 'max', column: col };
141
+ },
142
+ avg(col) {
143
+ return { _type: 'agg', func: 'avg', column: col };
144
+ },
145
+ };
146
+ const selectResult = selectFn(aggProxy);
147
+ const selectItems = [];
148
+ for (const [alias, expr] of Object.entries(selectResult)) {
149
+ if (expr._type === 'key') {
150
+ const intv = intervalDefs.find((d) => d.alias === expr.column);
151
+ if (intv) {
152
+ selectItems.push(`toStartOfInterval(${intv.column}, INTERVAL ${intv.seconds} SECOND) AS ${alias}`);
153
+ }
154
+ else {
155
+ selectItems.push(alias === expr.column ? alias : `${expr.column} AS ${alias}`);
156
+ }
157
+ }
158
+ else if (expr._type === 'agg') {
159
+ const arg = expr.column ? `(${expr.column})` : '()';
160
+ selectItems.push(`${expr.func}${arg} AS ${alias}`);
161
+ }
162
+ }
163
+ return `CREATE MATERIALIZED VIEW ${name} AS SELECT ${selectItems.join(', ')} FROM ${source} GROUP BY ${groupByCols.join(', ')};`;
164
+ }
165
+ //# sourceMappingURL=ddl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ddl.js","sourceRoot":"","sources":["../src/ddl.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ export interface DeltaDbConfig {
2
+ schema: string;
3
+ dataDir?: string;
4
+ maxBufferSize?: number;
5
+ }
6
+ export interface DeltaDbCursor {
7
+ number: number;
8
+ hash: string;
9
+ }
10
+ export type DeltaOperation = 'insert' | 'update' | 'delete';
11
+ export interface DeltaRecord {
12
+ table: string;
13
+ operation: DeltaOperation;
14
+ key: Record<string, any>;
15
+ values: Record<string, any>;
16
+ prevValues: Record<string, any> | null;
17
+ }
18
+ export interface DeltaBatch {
19
+ sequence: number;
20
+ finalizedHead: DeltaDbCursor | null;
21
+ latestHead: DeltaDbCursor | null;
22
+ tables: Record<string, DeltaRecord[]>;
23
+ }
24
+ export interface IngestInput {
25
+ data: Record<string, Record<string, any>[]>;
26
+ rollbackChain?: DeltaDbCursor[];
27
+ finalizedHead: DeltaDbCursor;
28
+ onDelta?: (batch: DeltaBatch) => void;
29
+ }
30
+ export interface StateFieldDef {
31
+ name: string;
32
+ columnType: string;
33
+ defaultValue: string;
34
+ }
35
+ export interface ExternalReducerOptions<TState = any, TRow = any, TEmit = any> {
36
+ name: string;
37
+ source: string;
38
+ groupBy: string[];
39
+ state: StateFieldDef[];
40
+ reduce: (state: TState, row: TRow) => [TState, TEmit | TEmit[] | null];
41
+ }
42
+ export declare class DeltaDb {
43
+ #private;
44
+ private constructor();
45
+ static open(config: DeltaDbConfig): DeltaDb;
46
+ processBatch(table: string, block: number, rows: Record<string, any>[]): boolean;
47
+ rollback(forkPoint: number): void;
48
+ finalize(block: number): void;
49
+ ingest(input: IngestInput): DeltaBatch | null;
50
+ resolveForkCursor(previousBlocks: DeltaDbCursor[]): DeltaDbCursor | null;
51
+ flush(): DeltaBatch | null;
52
+ ack(sequence: number): void;
53
+ get pendingCount(): number;
54
+ get isBackpressured(): boolean;
55
+ get cursor(): DeltaDbCursor | null;
56
+ registerReducer<TState = any, TRow = any, TEmit = any>(options: ExternalReducerOptions<TState, TRow, TEmit>): void;
57
+ }
58
+ //# sourceMappingURL=delta-db.d.ts.map
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DeltaDb = void 0;
4
+ const msgpack_1 = require("@msgpack/msgpack");
5
+ const native_js_1 = require("./native/native.js");
6
+ const encoder = new msgpack_1.Encoder({ useBigInt64: true });
7
+ // ─── DeltaDb class ───────────────────────────────────────────────
8
+ class DeltaDb {
9
+ #native;
10
+ constructor(native) {
11
+ this.#native = native;
12
+ }
13
+ static open(config) {
14
+ return new DeltaDb(native_js_1.DeltaDb.open(config));
15
+ }
16
+ processBatch(table, block, rows) {
17
+ return this.#native.processBatch(table, block, Buffer.from(encoder.encode(rows)));
18
+ }
19
+ rollback(forkPoint) {
20
+ this.#native.rollback(forkPoint);
21
+ }
22
+ finalize(block) {
23
+ this.#native.finalize(block);
24
+ }
25
+ ingest(input) {
26
+ const buf = this.#native.ingest({
27
+ data: Buffer.from(encoder.encode(input.data)),
28
+ rollbackChain: input.rollbackChain,
29
+ finalizedHead: input.finalizedHead,
30
+ });
31
+ const batch = buf ? (0, msgpack_1.decode)(buf) : null;
32
+ if (batch && input.onDelta) {
33
+ input.onDelta(batch);
34
+ this.#native.ack(batch.sequence);
35
+ }
36
+ return batch;
37
+ }
38
+ resolveForkCursor(previousBlocks) {
39
+ return this.#native.resolveForkCursor(previousBlocks);
40
+ }
41
+ flush() {
42
+ const buf = this.#native.flush();
43
+ return buf ? (0, msgpack_1.decode)(buf) : null;
44
+ }
45
+ ack(sequence) {
46
+ this.#native.ack(sequence);
47
+ }
48
+ get pendingCount() {
49
+ return this.#native.pendingCount;
50
+ }
51
+ get isBackpressured() {
52
+ return this.#native.isBackpressured;
53
+ }
54
+ get cursor() {
55
+ return this.#native.cursor;
56
+ }
57
+ registerReducer(options) {
58
+ const { reduce } = options;
59
+ const batchFn = (groups) => {
60
+ return groups.map(({ state, rows }) => {
61
+ let s = state;
62
+ const emits = [];
63
+ for (const row of rows) {
64
+ const [newState, emit] = reduce(s, row);
65
+ s = newState;
66
+ if (emit != null) {
67
+ if (Array.isArray(emit)) {
68
+ for (let i = 0; i < emit.length; i++)
69
+ emits.push(emit[i]);
70
+ }
71
+ else {
72
+ emits.push(emit);
73
+ }
74
+ }
75
+ }
76
+ return { state: s, emits };
77
+ });
78
+ };
79
+ this.#native.registerReducer({
80
+ name: options.name,
81
+ source: options.source,
82
+ groupBy: options.groupBy,
83
+ state: options.state,
84
+ }, batchFn);
85
+ }
86
+ }
87
+ exports.DeltaDb = DeltaDb;
88
+ //# sourceMappingURL=delta-db.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delta-db.js","sourceRoot":"","sources":["../src/delta-db.ts"],"names":[],"mappings":";;;AAAA,8CAAkD;AAClD,kDAA6D;AAE7D,MAAM,OAAO,GAAG,IAAI,iBAAO,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAA;AAqDlD,oEAAoE;AAEpE,MAAa,OAAO;IAClB,OAAO,CAAoC;IAE3C,YAAoB,MAA0C;QAC5D,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;IACvB,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,MAAqB;QAC/B,OAAO,IAAI,OAAO,CAAC,mBAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;IAChD,CAAC;IAED,YAAY,CAAC,KAAa,EAAE,KAAa,EAAE,IAA2B;QACpE,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACnF,CAAC;IAED,QAAQ,CAAC,SAAiB;QACxB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;IAClC,CAAC;IAED,QAAQ,CAAC,KAAa;QACpB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC9B,CAAC;IAED,MAAM,CAAC,KAAkB;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YAC9B,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC7C,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,aAAa,EAAE,KAAK,CAAC,aAAa;SACnC,CAAC,CAAA;QACF,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAE,IAAA,gBAAM,EAAC,GAAG,CAAgB,CAAC,CAAC,CAAC,IAAI,CAAA;QACtD,IAAI,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAC3B,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YACpB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;QAClC,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,iBAAiB,CAAC,cAA+B;QAC/C,OAAO,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAA;IACvD,CAAC;IAED,KAAK;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;QAChC,OAAO,GAAG,CAAC,CAAC,CAAE,IAAA,gBAAM,EAAC,GAAG,CAAgB,CAAC,CAAC,CAAC,IAAI,CAAA;IACjD,CAAC;IAED,GAAG,CAAC,QAAgB;QAClB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAC5B,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,CAAA;IAClC,CAAC;IAED,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,OAAO,CAAC,eAAe,CAAA;IACrC,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAA;IAC5B,CAAC;IAED,eAAe,CACb,OAAoD;QAEpD,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAA;QAE1B,MAAM,OAAO,GAAG,CAAC,MAAyC,EAAE,EAAE;YAC5D,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE;gBACpC,IAAI,CAAC,GAAG,KAAK,CAAA;gBACb,MAAM,KAAK,GAAU,EAAE,CAAA;gBACvB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;oBACvB,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;oBACvC,CAAC,GAAG,QAAQ,CAAA;oBACZ,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;wBACjB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;4BACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;gCAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;wBAC3D,CAAC;6BAAM,CAAC;4BACN,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;wBAClB,CAAC;oBACH,CAAC;gBACH,CAAC;gBACD,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAA;YAC5B,CAAC,CAAC,CAAA;QACJ,CAAC,CAAA;QAED,IAAI,CAAC,OAAO,CAAC,eAAe,CAC1B;YACE,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,EACD,OAAO,CACR,CAAA;IACH,CAAC;CACF;AAhGD,0BAgGC"}
@@ -0,0 +1,5 @@
1
+ export * from './column';
2
+ export { type AggExpr, type AggProxy, type GroupByItem, type IntervalExpr, interval, type KeyRef, type ReducerOptions, type ViewOptions, } from './ddl';
3
+ export { type DeltaBatch, DeltaDb, type DeltaDbConfig, type DeltaDbCursor, type DeltaOperation, type DeltaRecord, type ExternalReducerOptions, type IngestInput, type StateFieldDef, } from './delta-db';
4
+ export { Pipeline, ReducerHandle, TableHandle, ViewHandle } from './pipeline';
5
+ //# sourceMappingURL=index.d.ts.map