@justwant/warehouse 0.1.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.
- package/README.md +60 -0
- package/dist/buildOrderBy.d.ts +11 -0
- package/dist/buildOrderBy.d.ts.map +1 -0
- package/dist/buildOrderBy.js +34 -0
- package/dist/buildOrderBy.js.map +1 -0
- package/dist/buildWhere.d.ts +12 -0
- package/dist/buildWhere.d.ts.map +1 -0
- package/dist/buildWhere.js +26 -0
- package/dist/buildWhere.js.map +1 -0
- package/dist/clickhouse/index.d.ts +17 -0
- package/dist/clickhouse/index.d.ts.map +1 -0
- package/dist/clickhouse/index.js +20 -0
- package/dist/clickhouse/index.js.map +1 -0
- package/dist/core.d.ts +18 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +178 -0
- package/dist/core.js.map +1 -0
- package/dist/ddl/clickhouse.d.ts +14 -0
- package/dist/ddl/clickhouse.d.ts.map +1 -0
- package/dist/ddl/clickhouse.js +40 -0
- package/dist/ddl/clickhouse.js.map +1 -0
- package/dist/ddl/drop.d.ts +6 -0
- package/dist/ddl/drop.d.ts.map +1 -0
- package/dist/ddl/drop.js +11 -0
- package/dist/ddl/drop.js.map +1 -0
- package/dist/ddl/duckdb.d.ts +12 -0
- package/dist/ddl/duckdb.d.ts.map +1 -0
- package/dist/ddl/duckdb.js +37 -0
- package/dist/ddl/duckdb.js.map +1 -0
- package/dist/ddl/exist.d.ts +6 -0
- package/dist/ddl/exist.d.ts.map +1 -0
- package/dist/ddl/exist.js +19 -0
- package/dist/ddl/exist.js.map +1 -0
- package/dist/ddl/index.d.ts +13 -0
- package/dist/ddl/index.d.ts.map +1 -0
- package/dist/ddl/index.js +20 -0
- package/dist/ddl/index.js.map +1 -0
- package/dist/duckdb/index.d.ts +17 -0
- package/dist/duckdb/index.d.ts.map +1 -0
- package/dist/duckdb/index.js +20 -0
- package/dist/duckdb/index.js.map +1 -0
- package/dist/errors.d.ts +16 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +48 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/mapping.d.ts +20 -0
- package/dist/mapping.d.ts.map +1 -0
- package/dist/mapping.js +52 -0
- package/dist/mapping.js.map +1 -0
- package/dist/types.d.ts +73 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/docs/DRIVERS.md +69 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# @justwant/warehouse
|
|
2
|
+
|
|
3
|
+
DAL for data warehouses (OLAP). Contract-first, append-only. Batch insert, query, aggregate.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @justwant/warehouse @justwant/contract waddler
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
For ClickHouse: `bun add @clickhouse/client`
|
|
12
|
+
For DuckDB: `bun add @duckdb/node-api`
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { defineContract, uuid, string, number, date } from "@justwant/contract";
|
|
18
|
+
import { createWarehouse } from "@justwant/warehouse";
|
|
19
|
+
import { createDuckDbAdapter } from "@justwant/warehouse/duckdb";
|
|
20
|
+
|
|
21
|
+
const EventContract = defineContract("events", {
|
|
22
|
+
timestamp: date().required(),
|
|
23
|
+
user_id: uuid().required(),
|
|
24
|
+
event_type: string().required(),
|
|
25
|
+
amount: number().optional(),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const warehouse = createWarehouse(createDuckDbAdapter({ path: ":memory:" }));
|
|
29
|
+
const events = warehouse.table(EventContract);
|
|
30
|
+
await events.createTable();
|
|
31
|
+
|
|
32
|
+
await events.insert([
|
|
33
|
+
{ timestamp: new Date(), user_id: crypto.randomUUID(), event_type: "purchase", amount: 99 },
|
|
34
|
+
{ timestamp: new Date(), user_id: crypto.randomUUID(), event_type: "view" },
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
const rows = await events.query({ where: { event_type: "purchase" }, limit: 100 });
|
|
38
|
+
const agg = await events.aggregate({
|
|
39
|
+
groupBy: ["event_type"],
|
|
40
|
+
select: { total: "sum(amount)", count: "count()" },
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Drivers
|
|
45
|
+
|
|
46
|
+
- **ClickHouse**: `createClickHouseAdapter` from `@justwant/warehouse/clickhouse`
|
|
47
|
+
- **DuckDB**: `createDuckDbAdapter` from `@justwant/warehouse/duckdb`
|
|
48
|
+
|
|
49
|
+
Pass the driver config to `createWarehouse` for tree-shaking (import only the driver you need).
|
|
50
|
+
|
|
51
|
+
## Docs
|
|
52
|
+
|
|
53
|
+
- [Drivers](docs/DRIVERS.md) — config per driver, mapping
|
|
54
|
+
|
|
55
|
+
## API
|
|
56
|
+
|
|
57
|
+
- `createWarehouse(config)` — builds a `Warehouse` from driver config (createDuckDbAdapter, etc.)
|
|
58
|
+
- `createWarehouseFromSql(sql, { dialect })` — low-level: build from Waddler SQL client directly
|
|
59
|
+
- `table(contract)` — returns `WarehouseMappedTable` with `createTable`, `exist`, `drop`, `insert`, `query`, `aggregate`
|
|
60
|
+
- `adapter.createTable(contract)` — legacy DDL (prefer `table(contract).createTable()`)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build ORDER BY clause for warehouse SQL.
|
|
3
|
+
* Uses sql template to produce appendable SQLQuery (waddler expects .sqlWrapper).
|
|
4
|
+
*/
|
|
5
|
+
import type { WaddlerQuery, WaddlerSql } from "./types.js";
|
|
6
|
+
export type OrderDirection = "asc" | "desc";
|
|
7
|
+
/** Appends ORDER BY clause to the query. Mutates query in place. */
|
|
8
|
+
export declare function appendOrderBy(sql: WaddlerSql, query: WaddlerQuery, mapping: Record<string, {
|
|
9
|
+
name: string;
|
|
10
|
+
}>, orderBy: Record<string, OrderDirection>): void;
|
|
11
|
+
//# sourceMappingURL=buildOrderBy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildOrderBy.d.ts","sourceRoot":"","sources":["../src/buildOrderBy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE3D,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,CAAC;AAE5C,oEAAoE;AACpE,wBAAgB,aAAa,CAC3B,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EACzC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GACtC,IAAI,CAwBN"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build ORDER BY clause for warehouse SQL.
|
|
3
|
+
* Uses sql template to produce appendable SQLQuery (waddler expects .sqlWrapper).
|
|
4
|
+
*/
|
|
5
|
+
/** Appends ORDER BY clause to the query. Mutates query in place. */
|
|
6
|
+
export function appendOrderBy(sql, query, mapping, orderBy) {
|
|
7
|
+
const entries = Object.entries(orderBy)
|
|
8
|
+
.filter(([key]) => mapping[key])
|
|
9
|
+
.map(([key]) => {
|
|
10
|
+
const col = mapping[key];
|
|
11
|
+
const dir = orderBy[key];
|
|
12
|
+
if (!col || dir === undefined)
|
|
13
|
+
throw new Error("Unreachable");
|
|
14
|
+
return { colName: col.name, dir };
|
|
15
|
+
});
|
|
16
|
+
if (entries.length === 0)
|
|
17
|
+
return;
|
|
18
|
+
const append = query.append;
|
|
19
|
+
if (!append)
|
|
20
|
+
return;
|
|
21
|
+
const first = entries[0];
|
|
22
|
+
if (!first)
|
|
23
|
+
return;
|
|
24
|
+
let orderByClause = sql ` ORDER BY ${sql.identifier(first.colName)} ${sql.raw(first.dir === "desc" ? "DESC" : "ASC")}`;
|
|
25
|
+
for (let i = 1; i < entries.length; i++) {
|
|
26
|
+
const entry = entries[i];
|
|
27
|
+
if (!entry)
|
|
28
|
+
continue;
|
|
29
|
+
const { colName, dir } = entry;
|
|
30
|
+
orderByClause = sql `${orderByClause}, ${sql.identifier(colName)} ${sql.raw(dir === "desc" ? "DESC" : "ASC")}`;
|
|
31
|
+
}
|
|
32
|
+
append.call(query, orderByClause);
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=buildOrderBy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildOrderBy.js","sourceRoot":"","sources":["../src/buildOrderBy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,oEAAoE;AACpE,MAAM,UAAU,aAAa,CAC3B,GAAe,EACf,KAAmB,EACnB,OAAyC,EACzC,OAAuC;IAEvC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;SACpC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;SAC/B,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE;QACb,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QACzB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;QAC9D,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;IACL,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEjC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,CAAC,KAAK;QAAE,OAAO;IACnB,IAAI,aAAa,GAAG,GAAG,CAAA,aAAa,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;IACtH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;QAC/B,aAAa,GAAG,GAAG,CAAA,GAAG,aAAa,KAAK,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;IAChH,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build WHERE clause for warehouse SQL (parameterized).
|
|
3
|
+
*/
|
|
4
|
+
import type { WaddlerQuery, WaddlerSql } from "./types.js";
|
|
5
|
+
export interface AppendWhereOptions {
|
|
6
|
+
firstConnector?: " WHERE " | " AND ";
|
|
7
|
+
}
|
|
8
|
+
/** Appends WHERE conditions to the query. Mutates query in place. */
|
|
9
|
+
export declare function appendWhere(sql: WaddlerSql, query: WaddlerQuery, mapping: Record<string, {
|
|
10
|
+
name: string;
|
|
11
|
+
}>, where: Record<string, unknown>, options?: AppendWhereOptions): void;
|
|
12
|
+
//# sourceMappingURL=buildWhere.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildWhere.d.ts","sourceRoot":"","sources":["../src/buildWhere.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE3D,MAAM,WAAW,kBAAkB;IACjC,cAAc,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CACtC;AAED,qEAAqE;AACrE,wBAAgB,WAAW,CACzB,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EACzC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,CAAC,EAAE,kBAAkB,GAC3B,IAAI,CAmBN"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build WHERE clause for warehouse SQL (parameterized).
|
|
3
|
+
*/
|
|
4
|
+
/** Appends WHERE conditions to the query. Mutates query in place. */
|
|
5
|
+
export function appendWhere(sql, query, mapping, where, options) {
|
|
6
|
+
const entries = Object.entries(where).filter(([, v]) => v !== undefined);
|
|
7
|
+
if (entries.length === 0)
|
|
8
|
+
return;
|
|
9
|
+
const append = query.append;
|
|
10
|
+
if (!append)
|
|
11
|
+
return;
|
|
12
|
+
const useAnd = options?.firstConnector === " AND ";
|
|
13
|
+
for (let i = 0; i < entries.length; i++) {
|
|
14
|
+
const entry = entries[i];
|
|
15
|
+
if (entry === undefined)
|
|
16
|
+
continue;
|
|
17
|
+
const [key, val] = entry;
|
|
18
|
+
const colName = mapping[key]?.name;
|
|
19
|
+
if (!colName)
|
|
20
|
+
continue;
|
|
21
|
+
const connector = i === 0 && !useAnd ? sql ` WHERE ` : sql ` AND `;
|
|
22
|
+
append.call(query, connector);
|
|
23
|
+
append.call(query, sql `${sql.identifier(colName)} = ${val}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=buildWhere.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildWhere.js","sourceRoot":"","sources":["../src/buildWhere.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,qEAAqE;AACrE,MAAM,UAAU,WAAW,CACzB,GAAe,EACf,KAAmB,EACnB,OAAyC,EACzC,KAA8B,EAC9B,OAA4B;IAE5B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;IACzE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEjC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,MAAM,MAAM,GAAG,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC;IAEnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC;QACzB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;QACnC,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAA,SAAS,CAAC,CAAC,CAAC,GAAG,CAAA,OAAO,CAAC;QACjE,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAA,GAAG,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Warehouse connection for ClickHouse.
|
|
3
|
+
* @see https://waddler.drizzle.team/docs/clickhouse/get-started/clickhouse-new
|
|
4
|
+
*
|
|
5
|
+
* Peer deps: waddler, @clickhouse/client
|
|
6
|
+
*/
|
|
7
|
+
import type { WarehouseConnectionConfig } from "../types.js";
|
|
8
|
+
export interface CreateClickHouseAdapterConfig {
|
|
9
|
+
connection?: string;
|
|
10
|
+
client?: unknown;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Creates a ClickHouse connection config. Pass to createWarehouse.
|
|
14
|
+
* Pass connection string (e.g. http://localhost:8123) or existing ClickHouse client.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createClickHouseAdapter(config: CreateClickHouseAdapterConfig): WarehouseConnectionConfig;
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/clickhouse/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAc,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAIzE,MAAM,WAAW,6BAA6B;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,6BAA6B,GACpC,yBAAyB,CAQ3B"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Warehouse connection for ClickHouse.
|
|
3
|
+
* @see https://waddler.drizzle.team/docs/clickhouse/get-started/clickhouse-new
|
|
4
|
+
*
|
|
5
|
+
* Peer deps: waddler, @clickhouse/client
|
|
6
|
+
*/
|
|
7
|
+
import { createRequire } from "node:module";
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
/**
|
|
10
|
+
* Creates a ClickHouse connection config. Pass to createWarehouse.
|
|
11
|
+
* Pass connection string (e.g. http://localhost:8123) or existing ClickHouse client.
|
|
12
|
+
*/
|
|
13
|
+
export function createClickHouseAdapter(config) {
|
|
14
|
+
const { waddler } = require("waddler/clickhouse");
|
|
15
|
+
const sql = config.client
|
|
16
|
+
? waddler({ client: config.client })
|
|
17
|
+
: waddler(config.connection ?? "http://localhost:8123");
|
|
18
|
+
return { sql, dialect: "clickhouse", driver: config.client };
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/clickhouse/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAO/C;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAAqC;IAErC,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAE/C,CAAC;IACF,MAAM,GAAG,GAAe,MAAM,CAAC,MAAM;QACnC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QACpC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,IAAI,uBAAuB,CAAC,CAAC;IAC1D,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AAC/D,CAAC"}
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Warehouse adapter core - batch insert, query, aggregate.
|
|
3
|
+
*/
|
|
4
|
+
import type { WaddlerSql, Warehouse, WarehouseConnectionConfig, WarehouseDialect } from "./types.js";
|
|
5
|
+
export interface CreateWarehouseFromSqlOptions {
|
|
6
|
+
dialect: WarehouseDialect;
|
|
7
|
+
driver?: unknown;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Creates a warehouse from connection config. Use with driver factories (createDuckDbAdapter, etc.).
|
|
11
|
+
*/
|
|
12
|
+
export declare function createWarehouse(config: WarehouseConnectionConfig): Warehouse;
|
|
13
|
+
/**
|
|
14
|
+
* Creates a warehouse from a Waddler SQL client.
|
|
15
|
+
* Low-level: use createWarehouse with a driver factory for the common case.
|
|
16
|
+
*/
|
|
17
|
+
export declare function createWarehouseFromSql(sql: WaddlerSql, options: CreateWarehouseFromSqlOptions): Warehouse;
|
|
18
|
+
//# sourceMappingURL=core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,OAAO,KAAK,EAIV,UAAU,EACV,SAAS,EACT,yBAAyB,EACzB,gBAAgB,EAEjB,MAAM,YAAY,CAAC;AA0BpB,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,gBAAgB,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,yBAAyB,GAAG,SAAS,CAM5E;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,6BAA6B,GACrC,SAAS,CA4IX"}
|
package/dist/core.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Warehouse adapter core - batch insert, query, aggregate.
|
|
3
|
+
*/
|
|
4
|
+
import { appendOrderBy } from "./buildOrderBy.js";
|
|
5
|
+
import { appendWhere } from "./buildWhere.js";
|
|
6
|
+
import { getCreateTableSQL, getDropTableSQL, getExistTableSQL } from "./ddl/index.js";
|
|
7
|
+
import { parseWarehouseError } from "./errors.js";
|
|
8
|
+
import { mapContractToRow, mapRowToContract } from "./mapping.js";
|
|
9
|
+
/** Normalize query result to row array. */
|
|
10
|
+
function toRows(result) {
|
|
11
|
+
if (Array.isArray(result))
|
|
12
|
+
return result;
|
|
13
|
+
const r = result;
|
|
14
|
+
return (r?.rows ?? []);
|
|
15
|
+
}
|
|
16
|
+
/** Normalize BigInt to number in aggregate results (DuckDB, ClickHouse return BigInt for count/sum). */
|
|
17
|
+
function normalizeAggregateRow(row) {
|
|
18
|
+
const out = {};
|
|
19
|
+
for (const [k, v] of Object.entries(row)) {
|
|
20
|
+
out[k] = typeof v === "bigint" ? Number(v) : v;
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
/** Parse exist() query result to boolean. */
|
|
25
|
+
function parseExistResult(rows) {
|
|
26
|
+
const row = rows[0];
|
|
27
|
+
if (!row)
|
|
28
|
+
return false;
|
|
29
|
+
const val = Object.values(row)[0];
|
|
30
|
+
return val === 1 || val === true || (typeof val === "number" && val !== 0);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Creates a warehouse from connection config. Use with driver factories (createDuckDbAdapter, etc.).
|
|
34
|
+
*/
|
|
35
|
+
export function createWarehouse(config) {
|
|
36
|
+
const wh = createWarehouseFromSql(config.sql, config);
|
|
37
|
+
if (config.close) {
|
|
38
|
+
return { ...wh, close: config.close };
|
|
39
|
+
}
|
|
40
|
+
return wh;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Creates a warehouse from a Waddler SQL client.
|
|
44
|
+
* Low-level: use createWarehouse with a driver factory for the common case.
|
|
45
|
+
*/
|
|
46
|
+
export function createWarehouseFromSql(sql, options) {
|
|
47
|
+
const { dialect, driver } = options;
|
|
48
|
+
const adapter = {
|
|
49
|
+
sql,
|
|
50
|
+
dialect,
|
|
51
|
+
driver,
|
|
52
|
+
async createTable(contract) {
|
|
53
|
+
try {
|
|
54
|
+
const ddl = getCreateTableSQL(contract, dialect);
|
|
55
|
+
await sql `${sql.raw(ddl)}`;
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
throw parseWarehouseError(err);
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
table(contract) {
|
|
62
|
+
const mapping = contract.mapping;
|
|
63
|
+
const tableName = contract.tableName;
|
|
64
|
+
const tableId = sql.identifier(tableName);
|
|
65
|
+
const fromDbRow = (row) => mapRowToContract(row, mapping, contract.fields);
|
|
66
|
+
const mapped = {
|
|
67
|
+
contract,
|
|
68
|
+
async createTable() {
|
|
69
|
+
try {
|
|
70
|
+
const ddl = getCreateTableSQL(contract, dialect, { ifNotExists: true });
|
|
71
|
+
await sql `${sql.raw(ddl)}`;
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
throw parseWarehouseError(err);
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
async exist() {
|
|
78
|
+
try {
|
|
79
|
+
const existSql = getExistTableSQL(tableName, dialect);
|
|
80
|
+
const rows = toRows(await sql `${sql.raw(existSql)}`);
|
|
81
|
+
return parseExistResult(rows);
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
throw parseWarehouseError(err);
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
async drop() {
|
|
88
|
+
try {
|
|
89
|
+
const dropSql = getDropTableSQL(tableName, dialect);
|
|
90
|
+
await sql `${sql.raw(dropSql)}`;
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
throw parseWarehouseError(err);
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
async insert(rows) {
|
|
97
|
+
if (rows.length === 0)
|
|
98
|
+
return;
|
|
99
|
+
try {
|
|
100
|
+
const colOrder = Object.entries(mapping).map(([, col]) => col.name);
|
|
101
|
+
const sqlDefault = sql.default;
|
|
102
|
+
const tuples = rows.map((row) => {
|
|
103
|
+
const dbRow = mapContractToRow(row, mapping);
|
|
104
|
+
return colOrder.map((col) => {
|
|
105
|
+
const val = dbRow[col];
|
|
106
|
+
return val === undefined && sqlDefault !== undefined ? sqlDefault : val;
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
const colList = colOrder.map((c) => `"${String(c).replace(/"/g, '""')}"`).join(", ");
|
|
110
|
+
await sql `INSERT INTO ${tableId} (${sql.raw(colList)}) VALUES ${sql.values(tuples)}`;
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
throw parseWarehouseError(err);
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
async query(options) {
|
|
117
|
+
try {
|
|
118
|
+
const query = sql `SELECT * FROM ${tableId}`;
|
|
119
|
+
const append = query.append;
|
|
120
|
+
if (append && options) {
|
|
121
|
+
const where = (options.where ?? {});
|
|
122
|
+
const hasWhere = Object.entries(where).some(([, v]) => v !== undefined);
|
|
123
|
+
if (hasWhere) {
|
|
124
|
+
appendWhere(sql, query, mapping, where);
|
|
125
|
+
}
|
|
126
|
+
if (options.orderBy && Object.keys(options.orderBy).length > 0) {
|
|
127
|
+
appendOrderBy(sql, query, mapping, options.orderBy);
|
|
128
|
+
}
|
|
129
|
+
if (options.limit !== undefined) {
|
|
130
|
+
append.call(query, sql ` LIMIT ${options.limit}`);
|
|
131
|
+
}
|
|
132
|
+
if (options.offset !== undefined) {
|
|
133
|
+
append.call(query, sql ` OFFSET ${options.offset}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const rows = toRows(await query);
|
|
137
|
+
return rows.map((r) => fromDbRow(r));
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
throw parseWarehouseError(err);
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
async aggregate(options) {
|
|
144
|
+
try {
|
|
145
|
+
const groupBy = options.groupBy ?? [];
|
|
146
|
+
const selectEntries = Object.entries(options.select);
|
|
147
|
+
const selectExprs = selectEntries.map(([alias, expr]) => `${expr} AS ${alias}`);
|
|
148
|
+
const groupByCols = groupBy.map((k) => mapping[k]?.name).filter(Boolean);
|
|
149
|
+
const selectClause = groupByCols.length > 0
|
|
150
|
+
? [...groupByCols.map((c) => `"${c}"`), ...selectExprs].join(", ")
|
|
151
|
+
: selectExprs.join(", ");
|
|
152
|
+
const groupByClause = groupByCols.length > 0
|
|
153
|
+
? ` GROUP BY ${groupByCols.map((c) => `"${c}"`).join(", ")}`
|
|
154
|
+
: "";
|
|
155
|
+
const query = sql `SELECT ${sql.raw(selectClause)} FROM ${tableId}`;
|
|
156
|
+
const append = query.append;
|
|
157
|
+
const where = (options.where ?? {});
|
|
158
|
+
const hasWhere = Object.entries(where).some(([, v]) => v !== undefined);
|
|
159
|
+
if (append && hasWhere) {
|
|
160
|
+
appendWhere(sql, query, mapping, where);
|
|
161
|
+
}
|
|
162
|
+
if (append && groupByClause) {
|
|
163
|
+
append.call(query, sql `${sql.raw(groupByClause)}`);
|
|
164
|
+
}
|
|
165
|
+
const rows = toRows(await query);
|
|
166
|
+
return rows.map((r) => normalizeAggregateRow(r));
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
throw parseWarehouseError(err);
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
return mapped;
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
return adapter;
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=core.js.map
|
package/dist/core.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DDL for ClickHouse.
|
|
3
|
+
* MergeTree requires ORDER BY - use first column from mapping.
|
|
4
|
+
*/
|
|
5
|
+
import type { FieldDef } from "@justwant/contract";
|
|
6
|
+
import type { TableContract } from "@justwant/contract";
|
|
7
|
+
/**
|
|
8
|
+
* Generates CREATE TABLE SQL for ClickHouse (MergeTree).
|
|
9
|
+
* ORDER BY is required - uses first column from mapping.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getCreateTableSQL(contract: TableContract<Record<string, FieldDef<unknown, boolean>>>, options?: {
|
|
12
|
+
ifNotExists?: boolean;
|
|
13
|
+
}): string;
|
|
14
|
+
//# sourceMappingURL=clickhouse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clickhouse.d.ts","sourceRoot":"","sources":["../../src/ddl/clickhouse.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAiBxD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnE,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GAClC,MAAM,CAkBR"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DDL for ClickHouse.
|
|
3
|
+
* MergeTree requires ORDER BY - use first column from mapping.
|
|
4
|
+
*/
|
|
5
|
+
function escapeIdentifier(name) {
|
|
6
|
+
return `"${String(name).replace(/"/g, '""')}"`;
|
|
7
|
+
}
|
|
8
|
+
function columnTypeForClickHouse(field) {
|
|
9
|
+
const ct = field._columnType ?? "TEXT";
|
|
10
|
+
const map = {
|
|
11
|
+
TEXT: "String",
|
|
12
|
+
INTEGER: "Int64",
|
|
13
|
+
REAL: "Float64",
|
|
14
|
+
BOOLEAN: "UInt8",
|
|
15
|
+
};
|
|
16
|
+
return map[ct] ?? "String";
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Generates CREATE TABLE SQL for ClickHouse (MergeTree).
|
|
20
|
+
* ORDER BY is required - uses first column from mapping.
|
|
21
|
+
*/
|
|
22
|
+
export function getCreateTableSQL(contract, options) {
|
|
23
|
+
const { tableName, fields, mapping } = contract;
|
|
24
|
+
const entries = Object.entries(mapping);
|
|
25
|
+
const parts = [];
|
|
26
|
+
for (const [key, col] of entries) {
|
|
27
|
+
const field = fields[key];
|
|
28
|
+
if (!field)
|
|
29
|
+
continue;
|
|
30
|
+
const colName = col.name;
|
|
31
|
+
const type = columnTypeForClickHouse(field);
|
|
32
|
+
const nullable = !field._required ? " Nullable" : "";
|
|
33
|
+
parts.push(`${escapeIdentifier(colName)} ${type}${nullable}`);
|
|
34
|
+
}
|
|
35
|
+
const tableId = escapeIdentifier(tableName);
|
|
36
|
+
const orderByCol = entries[0]?.[1]?.name ?? "id";
|
|
37
|
+
const ifNotExists = options?.ifNotExists ? " IF NOT EXISTS" : "";
|
|
38
|
+
return `CREATE TABLE${ifNotExists} ${tableId} (${parts.join(", ")}) ENGINE = MergeTree() ORDER BY (${escapeIdentifier(orderByCol)})`;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=clickhouse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clickhouse.js","sourceRoot":"","sources":["../../src/ddl/clickhouse.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,SAAS,gBAAgB,CAAC,IAAY;IACpC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;AACjD,CAAC;AAED,SAAS,uBAAuB,CAAC,KAAiC;IAChE,MAAM,EAAE,GAAG,KAAK,CAAC,WAAW,IAAI,MAAM,CAAC;IACvC,MAAM,GAAG,GAA2B;QAClC,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,OAAO;KACjB,CAAC;IACF,OAAO,GAAG,CAAC,EAAE,CAAC,IAAI,QAAQ,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAmE,EACnE,OAAmC;IAEnC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC;IAChD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,OAAO,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,CAAC,GAA0B,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC;QACzB,MAAM,IAAI,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,KAAK,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC,IAAI,IAAI,GAAG,QAAQ,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,OAAO,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC;IACjD,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,OAAO,eAAe,WAAW,IAAI,OAAO,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,oCAAoC,gBAAgB,CAAC,UAAU,CAAC,GAAG,CAAC;AACvI,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drop.d.ts","sourceRoot":"","sources":["../../src/ddl/drop.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAMpD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAGpF"}
|
package/dist/ddl/drop.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQL to drop a table.
|
|
3
|
+
*/
|
|
4
|
+
function escapeIdentifier(name) {
|
|
5
|
+
return `"${String(name).replace(/"/g, '""')}"`;
|
|
6
|
+
}
|
|
7
|
+
export function getDropTableSQL(tableName, dialect) {
|
|
8
|
+
const escaped = escapeIdentifier(tableName);
|
|
9
|
+
return `DROP TABLE IF EXISTS ${escaped}`;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=drop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drop.js","sourceRoot":"","sources":["../../src/ddl/drop.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,SAAS,gBAAgB,CAAC,IAAY;IACpC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,SAAiB,EAAE,OAAyB;IAC1E,MAAM,OAAO,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC5C,OAAO,wBAAwB,OAAO,EAAE,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DDL for DuckDB.
|
|
3
|
+
*/
|
|
4
|
+
import type { FieldDef } from "@justwant/contract";
|
|
5
|
+
import type { TableContract } from "@justwant/contract";
|
|
6
|
+
/**
|
|
7
|
+
* Generates CREATE TABLE SQL for DuckDB.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getCreateTableSQL(contract: TableContract<Record<string, FieldDef<unknown, boolean>>>, options?: {
|
|
10
|
+
ifNotExists?: boolean;
|
|
11
|
+
}): string;
|
|
12
|
+
//# sourceMappingURL=duckdb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duckdb.d.ts","sourceRoot":"","sources":["../../src/ddl/duckdb.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAmBxD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnE,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GAClC,MAAM,CAeR"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DDL for DuckDB.
|
|
3
|
+
*/
|
|
4
|
+
function escapeIdentifier(name) {
|
|
5
|
+
return `"${String(name).replace(/"/g, '""')}"`;
|
|
6
|
+
}
|
|
7
|
+
function columnTypeForDuckDb(field) {
|
|
8
|
+
const ct = field._columnType ?? "TEXT";
|
|
9
|
+
const map = {
|
|
10
|
+
TEXT: "VARCHAR",
|
|
11
|
+
INTEGER: "BIGINT",
|
|
12
|
+
REAL: "DOUBLE",
|
|
13
|
+
BOOLEAN: "BOOLEAN",
|
|
14
|
+
DATE: "DATE",
|
|
15
|
+
JSON: "JSON",
|
|
16
|
+
};
|
|
17
|
+
return map[ct] ?? "VARCHAR";
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Generates CREATE TABLE SQL for DuckDB.
|
|
21
|
+
*/
|
|
22
|
+
export function getCreateTableSQL(contract, options) {
|
|
23
|
+
const { tableName, fields, mapping } = contract;
|
|
24
|
+
const parts = [];
|
|
25
|
+
for (const [key, col] of Object.entries(mapping)) {
|
|
26
|
+
const field = fields[key];
|
|
27
|
+
if (!field)
|
|
28
|
+
continue;
|
|
29
|
+
const colName = col.name;
|
|
30
|
+
const type = columnTypeForDuckDb(field);
|
|
31
|
+
parts.push(`${escapeIdentifier(colName)} ${type}`);
|
|
32
|
+
}
|
|
33
|
+
const tableId = escapeIdentifier(tableName);
|
|
34
|
+
const ifNotExists = options?.ifNotExists ? " IF NOT EXISTS" : "";
|
|
35
|
+
return `CREATE TABLE${ifNotExists} ${tableId} (${parts.join(", ")})`;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=duckdb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duckdb.js","sourceRoot":"","sources":["../../src/ddl/duckdb.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,SAAS,gBAAgB,CAAC,IAAY;IACpC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;AACjD,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAiC;IAC5D,MAAM,EAAE,GAAG,KAAK,CAAC,WAAW,IAAI,MAAM,CAAC;IACvC,MAAM,GAAG,GAA2B;QAClC,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,QAAQ;QACjB,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,MAAM;KACb,CAAC;IACF,OAAO,GAAG,CAAC,EAAE,CAAC,IAAI,SAAS,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAmE,EACnE,OAAmC;IAEnC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC;IAChD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACjD,MAAM,KAAK,GAAG,MAAM,CAAC,GAA0B,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC;QACzB,MAAM,IAAI,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,OAAO,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,OAAO,eAAe,WAAW,IAAI,OAAO,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AACvE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exist.d.ts","sourceRoot":"","sources":["../../src/ddl/exist.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAUpD,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAQrF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQL to check if a table exists.
|
|
3
|
+
*/
|
|
4
|
+
function escapeIdentifier(name) {
|
|
5
|
+
return `"${String(name).replace(/"/g, '""')}"`;
|
|
6
|
+
}
|
|
7
|
+
function escapeStringLiteral(value) {
|
|
8
|
+
return `'${String(value).replace(/'/g, "''")}'`;
|
|
9
|
+
}
|
|
10
|
+
export function getExistTableSQL(tableName, dialect) {
|
|
11
|
+
if (dialect === "clickhouse") {
|
|
12
|
+
return `EXISTS TABLE ${escapeIdentifier(tableName)}`;
|
|
13
|
+
}
|
|
14
|
+
if (dialect === "duckdb") {
|
|
15
|
+
return `SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = ${escapeStringLiteral(tableName)})`;
|
|
16
|
+
}
|
|
17
|
+
throw new Error(`Unsupported warehouse dialect: ${dialect}`);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=exist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exist.js","sourceRoot":"","sources":["../../src/ddl/exist.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,SAAS,gBAAgB,CAAC,IAAY;IACpC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;AACjD,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa;IACxC,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,SAAiB,EAAE,OAAyB;IAC3E,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;QAC7B,OAAO,gBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC;IACvD,CAAC;IACD,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,OAAO,6EAA6E,mBAAmB,CAAC,SAAS,CAAC,GAAG,CAAC;IACxH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,kCAAkC,OAAO,EAAE,CAAC,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DDL generation for warehouse dialects.
|
|
3
|
+
*/
|
|
4
|
+
import type { FieldDef, TableContract } from "@justwant/contract";
|
|
5
|
+
import type { WarehouseDialect } from "../types.js";
|
|
6
|
+
export { getCreateTableSQL as getCreateTableSQLClickHouse } from "./clickhouse.js";
|
|
7
|
+
export { getCreateTableSQL as getCreateTableSQLDuckDb } from "./duckdb.js";
|
|
8
|
+
export { getExistTableSQL } from "./exist.js";
|
|
9
|
+
export { getDropTableSQL } from "./drop.js";
|
|
10
|
+
export declare function getCreateTableSQL(contract: TableContract<Record<string, FieldDef<unknown, boolean>>>, dialect: WarehouseDialect, options?: {
|
|
11
|
+
ifNotExists?: boolean;
|
|
12
|
+
}): string;
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ddl/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpD,OAAO,EAAE,iBAAiB,IAAI,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EAAE,iBAAiB,IAAI,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE5C,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnE,OAAO,EAAE,gBAAgB,EACzB,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GAClC,MAAM,CASR"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DDL generation for warehouse dialects.
|
|
3
|
+
*/
|
|
4
|
+
import { getCreateTableSQL as getClickHouseDDL } from "./clickhouse.js";
|
|
5
|
+
import { getCreateTableSQL as getDuckDbDDL } from "./duckdb.js";
|
|
6
|
+
export { getCreateTableSQL as getCreateTableSQLClickHouse } from "./clickhouse.js";
|
|
7
|
+
export { getCreateTableSQL as getCreateTableSQLDuckDb } from "./duckdb.js";
|
|
8
|
+
export { getExistTableSQL } from "./exist.js";
|
|
9
|
+
export { getDropTableSQL } from "./drop.js";
|
|
10
|
+
export function getCreateTableSQL(contract, dialect, options) {
|
|
11
|
+
switch (dialect) {
|
|
12
|
+
case "clickhouse":
|
|
13
|
+
return getClickHouseDDL(contract, options);
|
|
14
|
+
case "duckdb":
|
|
15
|
+
return getDuckDbDDL(contract, options);
|
|
16
|
+
default:
|
|
17
|
+
throw new Error(`Unsupported warehouse dialect: ${dialect}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ddl/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,iBAAiB,IAAI,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,iBAAiB,IAAI,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,iBAAiB,IAAI,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EAAE,iBAAiB,IAAI,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE5C,MAAM,UAAU,iBAAiB,CAC/B,QAAmE,EACnE,OAAyB,EACzB,OAAmC;IAEnC,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,YAAY;YACf,OAAO,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC7C,KAAK,QAAQ;YACX,OAAO,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACzC;YACE,MAAM,IAAI,KAAK,CAAC,kCAAkC,OAAO,EAAE,CAAC,CAAC;IACjE,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Warehouse connection for DuckDB.
|
|
3
|
+
* @see https://waddler.drizzle.team/docs/duckdb/connect-duckdb-neo
|
|
4
|
+
*
|
|
5
|
+
* Peer deps: waddler, @duckdb/node-api
|
|
6
|
+
*/
|
|
7
|
+
import type { WarehouseConnectionConfig } from "../types.js";
|
|
8
|
+
export interface CreateDuckDbAdapterConfig {
|
|
9
|
+
path?: string;
|
|
10
|
+
client?: unknown;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Creates a DuckDB connection config. Pass to createWarehouse.
|
|
14
|
+
* Pass path (e.g. ":memory:" or file path) or existing DuckDB client.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createDuckDbAdapter(config: CreateDuckDbAdapterConfig): WarehouseConnectionConfig;
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/duckdb/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAc,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAIzE,MAAM,WAAW,yBAAyB;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,yBAAyB,GAAG,yBAAyB,CAQhG"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Warehouse connection for DuckDB.
|
|
3
|
+
* @see https://waddler.drizzle.team/docs/duckdb/connect-duckdb-neo
|
|
4
|
+
*
|
|
5
|
+
* Peer deps: waddler, @duckdb/node-api
|
|
6
|
+
*/
|
|
7
|
+
import { createRequire } from "node:module";
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
/**
|
|
10
|
+
* Creates a DuckDB connection config. Pass to createWarehouse.
|
|
11
|
+
* Pass path (e.g. ":memory:" or file path) or existing DuckDB client.
|
|
12
|
+
*/
|
|
13
|
+
export function createDuckDbAdapter(config) {
|
|
14
|
+
const { waddler } = require("waddler/duckdb-neo");
|
|
15
|
+
const sql = config.client
|
|
16
|
+
? waddler({ client: config.client })
|
|
17
|
+
: waddler({ url: config.path ?? ":memory:" });
|
|
18
|
+
return { sql, dialect: "duckdb", driver: config.client };
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/duckdb/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAO/C;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAiC;IACnE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAE/C,CAAC;IACF,MAAM,GAAG,GAAe,MAAM,CAAC,MAAM;QACnC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;QACpC,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,IAAI,UAAU,EAAE,CAAC,CAAC;IAChD,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AAC3D,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse warehouse (ClickHouse, DuckDB) errors into normalized errors.
|
|
3
|
+
*/
|
|
4
|
+
export declare class WarehouseError extends Error {
|
|
5
|
+
readonly code: string;
|
|
6
|
+
readonly metadata?: Record<string, unknown> | undefined;
|
|
7
|
+
constructor(message: string, code: string, metadata?: Record<string, unknown> | undefined);
|
|
8
|
+
}
|
|
9
|
+
export declare class WarehouseConnectionError extends WarehouseError {
|
|
10
|
+
constructor(message: string, metadata?: Record<string, unknown>);
|
|
11
|
+
}
|
|
12
|
+
export declare class WarehouseTimeoutError extends WarehouseError {
|
|
13
|
+
constructor(message: string, metadata?: Record<string, unknown>);
|
|
14
|
+
}
|
|
15
|
+
export declare function parseWarehouseError(raw: unknown): WarehouseError;
|
|
16
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,cAAe,SAAQ,KAAK;aAGrB,IAAI,EAAE,MAAM;aACZ,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBAFlD,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA;CAMrD;AAED,qBAAa,wBAAyB,SAAQ,cAAc;gBAC9C,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAKhE;AAED,qBAAa,qBAAsB,SAAQ,cAAc;gBAC3C,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAKhE;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAqBhE"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse warehouse (ClickHouse, DuckDB) errors into normalized errors.
|
|
3
|
+
*/
|
|
4
|
+
export class WarehouseError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
metadata;
|
|
7
|
+
constructor(message, code, metadata) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.metadata = metadata;
|
|
11
|
+
this.name = "WarehouseError";
|
|
12
|
+
Object.setPrototypeOf(this, WarehouseError.prototype);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export class WarehouseConnectionError extends WarehouseError {
|
|
16
|
+
constructor(message, metadata) {
|
|
17
|
+
super(message, "CONNECTION", metadata);
|
|
18
|
+
this.name = "WarehouseConnectionError";
|
|
19
|
+
Object.setPrototypeOf(this, WarehouseConnectionError.prototype);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export class WarehouseTimeoutError extends WarehouseError {
|
|
23
|
+
constructor(message, metadata) {
|
|
24
|
+
super(message, "TIMEOUT", metadata);
|
|
25
|
+
this.name = "WarehouseTimeoutError";
|
|
26
|
+
Object.setPrototypeOf(this, WarehouseTimeoutError.prototype);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function parseWarehouseError(raw) {
|
|
30
|
+
const err = raw;
|
|
31
|
+
const message = typeof err?.message === "string" ? err.message : String(raw ?? "Unknown error");
|
|
32
|
+
const causeMsg = typeof err?.cause?.message === "string"
|
|
33
|
+
? err.cause.message
|
|
34
|
+
: "";
|
|
35
|
+
const msgToCheck = causeMsg || message;
|
|
36
|
+
const code = err?.code;
|
|
37
|
+
if (typeof code === "string") {
|
|
38
|
+
switch (code) {
|
|
39
|
+
case "ECONNREFUSED":
|
|
40
|
+
case "ECONNRESET":
|
|
41
|
+
return new WarehouseConnectionError(message, { code });
|
|
42
|
+
case "ETIMEDOUT":
|
|
43
|
+
return new WarehouseTimeoutError(message, { code });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return new WarehouseError(String(message), "UNKNOWN", { original: raw });
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,OAAO,cAAe,SAAQ,KAAK;IAGrB;IACA;IAHlB,YACE,OAAe,EACC,IAAY,EACZ,QAAkC;QAElD,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,SAAI,GAAJ,IAAI,CAAQ;QACZ,aAAQ,GAAR,QAAQ,CAA0B;QAGlD,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;IACxD,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,cAAc;IAC1D,YAAY,OAAe,EAAE,QAAkC;QAC7D,KAAK,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;QACvC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,wBAAwB,CAAC,SAAS,CAAC,CAAC;IAClE,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,cAAc;IACvD,YAAY,OAAe,EAAE,QAAkC;QAC7D,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC/D,CAAC;CACF;AAED,MAAM,UAAU,mBAAmB,CAAC,GAAY;IAC9C,MAAM,GAAG,GAAG,GAA8B,CAAC;IAC3C,MAAM,OAAO,GAAG,OAAO,GAAG,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,eAAe,CAAC,CAAC;IAChG,MAAM,QAAQ,GACZ,OAAQ,GAAG,EAAE,KAA8B,EAAE,OAAO,KAAK,QAAQ;QAC/D,CAAC,CAAE,GAAG,CAAC,KAA6B,CAAC,OAAO;QAC5C,CAAC,CAAC,EAAE,CAAC;IACT,MAAM,UAAU,GAAG,QAAQ,IAAI,OAAO,CAAC;IACvC,MAAM,IAAI,GAAG,GAAG,EAAE,IAA0B,CAAC;IAE7C,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,cAAc,CAAC;YACpB,KAAK,YAAY;gBACf,OAAO,IAAI,wBAAwB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YACzD,KAAK,WAAW;gBACd,OAAO,IAAI,qBAAqB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;AAC3E,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @justwant/warehouse - DAL for data warehouses (OLAP).
|
|
3
|
+
*/
|
|
4
|
+
export { createWarehouse, createWarehouseFromSql } from "./core.js";
|
|
5
|
+
export type { Warehouse, WarehouseConnectionConfig, WarehouseDialect, WarehouseMappedTable, QueryOptions, AggregateOptions, WaddlerSql, WaddlerQuery, StringMapping, } from "./types.js";
|
|
6
|
+
export { parseWarehouseError, WarehouseError, WarehouseConnectionError, WarehouseTimeoutError, } from "./errors.js";
|
|
7
|
+
export { getCreateTableSQL, getCreateTableSQLClickHouse, getCreateTableSQLDuckDb, } from "./ddl/index.js";
|
|
8
|
+
export { appendWhere } from "./buildWhere.js";
|
|
9
|
+
export { appendOrderBy, type OrderDirection } from "./buildOrderBy.js";
|
|
10
|
+
export { mapRowToContract, mapContractToRow } from "./mapping.js";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACpE,YAAY,EACV,SAAS,EACT,yBAAyB,EACzB,gBAAgB,EAChB,oBAAoB,EACpB,YAAY,EACZ,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,2BAA2B,EAC3B,uBAAuB,GACxB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @justwant/warehouse - DAL for data warehouses (OLAP).
|
|
3
|
+
*/
|
|
4
|
+
export { createWarehouse, createWarehouseFromSql } from "./core.js";
|
|
5
|
+
export { parseWarehouseError, WarehouseError, WarehouseConnectionError, WarehouseTimeoutError, } from "./errors.js";
|
|
6
|
+
export { getCreateTableSQL, getCreateTableSQLClickHouse, getCreateTableSQLDuckDb, } from "./ddl/index.js";
|
|
7
|
+
export { appendWhere } from "./buildWhere.js";
|
|
8
|
+
export { appendOrderBy } from "./buildOrderBy.js";
|
|
9
|
+
export { mapRowToContract, mapContractToRow } from "./mapping.js";
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAYpE,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,2BAA2B,EAC3B,uBAAuB,GACxB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAuB,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map warehouse row to contract shape.
|
|
3
|
+
*/
|
|
4
|
+
import type { AnyContract } from "@justwant/contract";
|
|
5
|
+
/** Column-like with a name for row lookup. */
|
|
6
|
+
export interface ColumnLike {
|
|
7
|
+
name: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Maps a warehouse row to contract shape.
|
|
11
|
+
* Converts null to undefined for optional fields.
|
|
12
|
+
* Converts ISO date strings to Date for date fields.
|
|
13
|
+
*/
|
|
14
|
+
export declare function mapRowToContract<T>(row: Record<string, unknown>, mapping: Record<string, ColumnLike>, contract: AnyContract): T;
|
|
15
|
+
/**
|
|
16
|
+
* Maps contract row to DB values for insert.
|
|
17
|
+
* Date → ISO string, etc.
|
|
18
|
+
*/
|
|
19
|
+
export declare function mapContractToRow(row: Record<string, unknown>, mapping: Record<string, ColumnLike>): Record<string, unknown>;
|
|
20
|
+
//# sourceMappingURL=mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../src/mapping.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,8CAA8C;AAC9C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,EACnC,QAAQ,EAAE,WAAW,GACpB,CAAC,CAoBH;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAClC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAazB"}
|
package/dist/mapping.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map warehouse row to contract shape.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Maps a warehouse row to contract shape.
|
|
6
|
+
* Converts null to undefined for optional fields.
|
|
7
|
+
* Converts ISO date strings to Date for date fields.
|
|
8
|
+
*/
|
|
9
|
+
export function mapRowToContract(row, mapping, contract) {
|
|
10
|
+
const result = {};
|
|
11
|
+
for (const [contractKey, col] of Object.entries(mapping)) {
|
|
12
|
+
const colName = col.name;
|
|
13
|
+
let value = row[colName];
|
|
14
|
+
const fieldDef = contract[contractKey];
|
|
15
|
+
if (fieldDef && !fieldDef._required && value === null) {
|
|
16
|
+
result[contractKey] = undefined;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
if (value !== null && value !== undefined && typeof value === "string" && fieldDef) {
|
|
20
|
+
const ct = fieldDef._columnType;
|
|
21
|
+
if (ct === "TEXT" && /^\d{4}-\d{2}-\d{2}/.test(value)) {
|
|
22
|
+
const d = new Date(value);
|
|
23
|
+
if (!Number.isNaN(d.getTime()))
|
|
24
|
+
value = d;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
result[contractKey] = value;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Maps contract row to DB values for insert.
|
|
34
|
+
* Date → ISO string, etc.
|
|
35
|
+
*/
|
|
36
|
+
export function mapContractToRow(row, mapping) {
|
|
37
|
+
const result = {};
|
|
38
|
+
for (const [contractKey, col] of Object.entries(mapping)) {
|
|
39
|
+
const value = row[contractKey];
|
|
40
|
+
if (!(contractKey in row))
|
|
41
|
+
continue;
|
|
42
|
+
const colName = col.name;
|
|
43
|
+
if (value instanceof Date) {
|
|
44
|
+
result[colName] = value.toISOString();
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
result[colName] = value;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=mapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mapping.js","sourceRoot":"","sources":["../src/mapping.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAA4B,EAC5B,OAAmC,EACnC,QAAqB;IAErB,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,WAAW,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACzD,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC;QACzB,IAAI,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;QACzB,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAoC,CAAC,CAAC;QAChE,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAC,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACtD,MAAM,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,QAAQ,EAAE,CAAC;gBACnF,MAAM,EAAE,GAAG,QAAQ,CAAC,WAAW,CAAC;gBAChC,IAAI,EAAE,KAAK,MAAM,IAAI,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBACtD,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;oBAC1B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;wBAAE,KAAK,GAAG,CAAC,CAAC;gBAC5C,CAAC;YACH,CAAC;YACD,MAAM,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,OAAO,MAAW,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAA4B,EAC5B,OAAmC;IAEnC,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,WAAW,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACzD,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC;QAC/B,IAAI,CAAC,CAAC,WAAW,IAAI,GAAG,CAAC;YAAE,SAAS;QACpC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC;QACzB,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;YAC1B,MAAM,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QACxC,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;QAC1B,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Warehouse adapter types.
|
|
3
|
+
* OLAP: append-only, batch insert, query, aggregate.
|
|
4
|
+
*/
|
|
5
|
+
import type { InferContract, TableContract, TableFields } from "@justwant/contract";
|
|
6
|
+
export type WarehouseDialect = "clickhouse" | "duckdb";
|
|
7
|
+
/** Connection config passed to createWarehouse. Returned by driver factories (createDuckDbAdapter, etc.). */
|
|
8
|
+
export interface WarehouseConnectionConfig {
|
|
9
|
+
sql: WaddlerSql;
|
|
10
|
+
dialect: WarehouseDialect;
|
|
11
|
+
driver?: unknown;
|
|
12
|
+
/** Release connection when done. Call warehouse.close() or await on shutdown. */
|
|
13
|
+
close?: () => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
/** String-based mapping: contract key → column name. */
|
|
16
|
+
export type StringMapping<T extends Record<string, unknown>> = {
|
|
17
|
+
[K in keyof T]: {
|
|
18
|
+
name: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Waddler SQL client interface.
|
|
23
|
+
* Compatible with waddler/clickhouse, waddler/duckdb-neo.
|
|
24
|
+
*/
|
|
25
|
+
export interface WaddlerSql {
|
|
26
|
+
(strings: TemplateStringsArray, ...values: unknown[]): WaddlerQuery;
|
|
27
|
+
identifier: (name: string | {
|
|
28
|
+
schema?: string;
|
|
29
|
+
table: string;
|
|
30
|
+
column?: string;
|
|
31
|
+
as?: string;
|
|
32
|
+
}) => unknown;
|
|
33
|
+
raw: (sql: string) => unknown;
|
|
34
|
+
values: (tuples: unknown[][]) => unknown;
|
|
35
|
+
default?: unknown;
|
|
36
|
+
append?: (part: unknown) => WaddlerQuery;
|
|
37
|
+
}
|
|
38
|
+
/** Query result - thenable, may have append for building. */
|
|
39
|
+
export interface WaddlerQuery {
|
|
40
|
+
then<T>(onfulfilled?: (value: unknown) => T | PromiseLike<T>): Promise<T>;
|
|
41
|
+
catch<T>(onrejected?: (reason: unknown) => T | PromiseLike<T>): Promise<T>;
|
|
42
|
+
append?: (part: unknown) => WaddlerQuery;
|
|
43
|
+
}
|
|
44
|
+
export interface QueryOptions<T> {
|
|
45
|
+
where?: Partial<InferContract<T>>;
|
|
46
|
+
orderBy?: Record<string, "asc" | "desc">;
|
|
47
|
+
limit?: number;
|
|
48
|
+
offset?: number;
|
|
49
|
+
}
|
|
50
|
+
export interface AggregateOptions<T extends TableFields, A> {
|
|
51
|
+
groupBy?: (keyof T)[];
|
|
52
|
+
select: Record<string, string>;
|
|
53
|
+
where?: Partial<InferContract<T>>;
|
|
54
|
+
}
|
|
55
|
+
export interface WarehouseMappedTable<T extends TableFields> {
|
|
56
|
+
readonly contract: TableContract<T>;
|
|
57
|
+
createTable(): Promise<void>;
|
|
58
|
+
exist(): Promise<boolean>;
|
|
59
|
+
drop(): Promise<void>;
|
|
60
|
+
insert(rows: InferContract<TableContract<T>>[]): Promise<void>;
|
|
61
|
+
query(options?: QueryOptions<TableContract<T>>): Promise<InferContract<TableContract<T>>[]>;
|
|
62
|
+
aggregate<A>(options: AggregateOptions<T, A>): Promise<A[]>;
|
|
63
|
+
}
|
|
64
|
+
export interface Warehouse {
|
|
65
|
+
readonly sql: WaddlerSql;
|
|
66
|
+
readonly dialect: WarehouseDialect;
|
|
67
|
+
readonly driver?: unknown;
|
|
68
|
+
table<T extends TableFields>(contract: TableContract<T>): WarehouseMappedTable<T>;
|
|
69
|
+
createTable(contract: TableContract<TableFields>): Promise<void>;
|
|
70
|
+
/** Release connection. No-op if config had no close. */
|
|
71
|
+
close?(): Promise<void>;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
package/docs/DRIVERS.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Warehouse Drivers
|
|
2
|
+
|
|
3
|
+
Pass the driver config to `createWarehouse` for tree-shaking. Import only the driver you need.
|
|
4
|
+
|
|
5
|
+
## DuckDB
|
|
6
|
+
|
|
7
|
+
**Package:** `@justwant/warehouse/duckdb`
|
|
8
|
+
**Peer deps:** waddler, @duckdb/node-api
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { createWarehouse } from "@justwant/warehouse";
|
|
12
|
+
import { createDuckDbAdapter } from "@justwant/warehouse/duckdb";
|
|
13
|
+
|
|
14
|
+
const warehouse = createWarehouse(createDuckDbAdapter({ path: ":memory:" }));
|
|
15
|
+
// or with file
|
|
16
|
+
const warehouse = createWarehouse(createDuckDbAdapter({ path: "./data.duckdb" }));
|
|
17
|
+
// or with existing client
|
|
18
|
+
const warehouse = createWarehouse(createDuckDbAdapter({ client: myDuckDbClient }));
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
| Option | Type | Description |
|
|
22
|
+
|--------|------|-------------|
|
|
23
|
+
| `path` | `string` | `:memory:` or file path. Default: `:memory:` |
|
|
24
|
+
| `client` | `unknown` | Existing DuckDB client |
|
|
25
|
+
|
|
26
|
+
## ClickHouse
|
|
27
|
+
|
|
28
|
+
**Package:** `@justwant/warehouse/clickhouse`
|
|
29
|
+
**Peer deps:** waddler, @clickhouse/client
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { createWarehouse } from "@justwant/warehouse";
|
|
33
|
+
import { createClickHouseAdapter } from "@justwant/warehouse/clickhouse";
|
|
34
|
+
|
|
35
|
+
const warehouse = createWarehouse(
|
|
36
|
+
createClickHouseAdapter({ connection: "http://localhost:8123" })
|
|
37
|
+
);
|
|
38
|
+
// or with existing client
|
|
39
|
+
const warehouse = createWarehouse(createClickHouseAdapter({ client: myClickHouseClient }));
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
| Option | Type | Description |
|
|
43
|
+
|--------|------|-------------|
|
|
44
|
+
| `connection` | `string` | URL (e.g. http://localhost:8123). Default: `http://localhost:8123` |
|
|
45
|
+
| `client` | `unknown` | Existing ClickHouse client |
|
|
46
|
+
|
|
47
|
+
## Mapping
|
|
48
|
+
|
|
49
|
+
Contracts use `defineContract(tableName, fields, options?)`. By default, contract keys map 1:1 to column names.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
defineContract("events", { user_id: string().required() });
|
|
53
|
+
// → column "user_id"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**camelCase → snake_case:** use `defaultMapping: "camelToSnake"`:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
defineContract("events", { userId: string().required() }, { defaultMapping: "camelToSnake" });
|
|
60
|
+
// → column "user_id"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Override specific keys:** use `mapping`:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
defineContract("events", { userId: string().required() }, {
|
|
67
|
+
mapping: { userId: { name: "user_id" } },
|
|
68
|
+
});
|
|
69
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@justwant/warehouse",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "DAL for data warehouses (OLAP). Batch insert, query, aggregate. ClickHouse, DuckDB.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/elydelva/justwant",
|
|
10
|
+
"directory": "packages/warehouse"
|
|
11
|
+
},
|
|
12
|
+
"keywords": ["warehouse", "olap", "clickhouse", "duckdb", "dal", "contract"],
|
|
13
|
+
"sideEffects": false,
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"import": "./dist/index.js",
|
|
20
|
+
"default": "./dist/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./clickhouse": {
|
|
23
|
+
"types": "./dist/clickhouse/index.d.ts",
|
|
24
|
+
"import": "./dist/clickhouse/index.js",
|
|
25
|
+
"default": "./dist/clickhouse/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./duckdb": {
|
|
28
|
+
"types": "./dist/duckdb/index.d.ts",
|
|
29
|
+
"import": "./dist/duckdb/index.js",
|
|
30
|
+
"default": "./dist/duckdb/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc",
|
|
35
|
+
"typecheck": "tsc --noEmit",
|
|
36
|
+
"test": "bun test"
|
|
37
|
+
},
|
|
38
|
+
"files": ["dist", "README.md", "docs"],
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@justwant/contract": "0.2.1"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"waddler": "*"
|
|
47
|
+
},
|
|
48
|
+
"peerDependenciesMeta": {
|
|
49
|
+
"waddler": {
|
|
50
|
+
"optional": true
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@duckdb/node-api": "*",
|
|
55
|
+
"@justwant/tsconfig": "0.0.0",
|
|
56
|
+
"typescript": "^5.7.0",
|
|
57
|
+
"waddler": "*"
|
|
58
|
+
}
|
|
59
|
+
}
|