@visactor/vquery 0.2.5 → 0.2.6

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.
Files changed (127) hide show
  1. package/dist/node/esm/adapters/index.d.ts +1 -0
  2. package/dist/node/esm/adapters/query-adapter/duckdbNodeAdapter.d.ts +14 -0
  3. package/dist/node/esm/adapters/query-adapter/duckdbWebAdapter.d.ts +14 -0
  4. package/dist/node/esm/adapters/storage-adapter/index.d.ts +2 -0
  5. package/dist/node/esm/adapters/storage-adapter/indexeddbAdapter.d.ts +21 -0
  6. package/dist/node/esm/adapters/storage-adapter/inmemoryAdapter.d.ts +22 -0
  7. package/dist/node/esm/browser.d.ts +5 -0
  8. package/dist/node/esm/data-source-builder/dataSourceBuilder.d.ts +16 -0
  9. package/dist/node/esm/data-source-builder/index.d.ts +1 -0
  10. package/dist/node/esm/dataset/dataset.d.ts +30 -0
  11. package/dist/node/esm/dataset/index.d.ts +2 -0
  12. package/dist/node/esm/node.d.ts +5 -0
  13. package/dist/node/esm/node.js +476 -0
  14. package/dist/node/esm/sql-builder/builders/groupBy.d.ts +2 -0
  15. package/dist/node/esm/sql-builder/builders/index.d.ts +3 -0
  16. package/dist/node/esm/sql-builder/builders/limit.d.ts +2 -0
  17. package/dist/node/esm/sql-builder/builders/where.d.ts +3 -0
  18. package/dist/node/esm/sql-builder/compile/index.d.ts +1 -0
  19. package/dist/node/esm/sql-builder/compile/inlineParameters.d.ts +1 -0
  20. package/dist/node/esm/sql-builder/dialect/index.d.ts +1 -0
  21. package/dist/node/esm/sql-builder/dialect/postgresDialect.d.ts +11 -0
  22. package/dist/node/esm/sql-builder/dslToSQL.d.ts +2 -0
  23. package/dist/node/esm/sql-builder/index.d.ts +1 -0
  24. package/dist/node/esm/sql-builder/utils.d.ts +8 -0
  25. package/dist/node/esm/types/DataSet.d.ts +11 -0
  26. package/dist/node/esm/types/DataSource.d.ts +11 -0
  27. package/dist/node/esm/types/QueryResult.d.ts +1 -0
  28. package/dist/node/esm/types/adapters/QueryAdapter.d.ts +11 -0
  29. package/dist/node/esm/types/adapters/StorageAdapter.d.ts +17 -0
  30. package/dist/node/esm/types/adapters/index.d.ts +2 -0
  31. package/dist/node/esm/types/dsl/GroupBy.d.ts +1 -0
  32. package/dist/node/esm/types/dsl/OrderBy.d.ts +4 -0
  33. package/dist/node/esm/types/dsl/QueryDSL.d.ts +12 -0
  34. package/dist/node/esm/types/dsl/Select.d.ts +7 -0
  35. package/dist/node/esm/types/dsl/Where.d.ts +24 -0
  36. package/dist/node/esm/types/dsl/demo.d.ts +1 -0
  37. package/dist/node/esm/types/dsl/index.d.ts +5 -0
  38. package/dist/node/esm/types/index.d.ts +5 -0
  39. package/dist/node/esm/utils/index.d.ts +1 -0
  40. package/dist/node/esm/utils/url.d.ts +3 -0
  41. package/dist/node/esm/vquery-browser.d.ts +21 -0
  42. package/dist/node/esm/vquery-node.d.ts +21 -0
  43. package/package.json +14 -9
  44. /package/dist/{cjs → browser/esm}/adapters/index.d.ts +0 -0
  45. /package/dist/{cjs → browser/esm}/adapters/query-adapter/duckdbNodeAdapter.d.ts +0 -0
  46. /package/dist/{cjs → browser/esm}/adapters/query-adapter/duckdbWebAdapter.d.ts +0 -0
  47. /package/dist/{cjs → browser/esm}/adapters/storage-adapter/index.d.ts +0 -0
  48. /package/dist/{cjs → browser/esm}/adapters/storage-adapter/indexeddbAdapter.d.ts +0 -0
  49. /package/dist/{cjs → browser/esm}/adapters/storage-adapter/inmemoryAdapter.d.ts +0 -0
  50. /package/dist/{cjs → browser/esm}/browser.d.ts +0 -0
  51. /package/dist/{esm → browser/esm}/browser.js +0 -0
  52. /package/dist/{cjs → browser/esm}/data-source-builder/dataSourceBuilder.d.ts +0 -0
  53. /package/dist/{cjs → browser/esm}/data-source-builder/index.d.ts +0 -0
  54. /package/dist/{cjs → browser/esm}/dataset/dataset.d.ts +0 -0
  55. /package/dist/{cjs → browser/esm}/dataset/index.d.ts +0 -0
  56. /package/dist/{cjs → browser/esm}/node.d.ts +0 -0
  57. /package/dist/{cjs → browser/esm}/sql-builder/builders/groupBy.d.ts +0 -0
  58. /package/dist/{cjs → browser/esm}/sql-builder/builders/index.d.ts +0 -0
  59. /package/dist/{cjs → browser/esm}/sql-builder/builders/limit.d.ts +0 -0
  60. /package/dist/{cjs → browser/esm}/sql-builder/builders/where.d.ts +0 -0
  61. /package/dist/{cjs → browser/esm}/sql-builder/compile/index.d.ts +0 -0
  62. /package/dist/{cjs → browser/esm}/sql-builder/compile/inlineParameters.d.ts +0 -0
  63. /package/dist/{cjs → browser/esm}/sql-builder/dialect/index.d.ts +0 -0
  64. /package/dist/{cjs → browser/esm}/sql-builder/dialect/postgresDialect.d.ts +0 -0
  65. /package/dist/{cjs → browser/esm}/sql-builder/dslToSQL.d.ts +0 -0
  66. /package/dist/{cjs → browser/esm}/sql-builder/index.d.ts +0 -0
  67. /package/dist/{cjs → browser/esm}/sql-builder/utils.d.ts +0 -0
  68. /package/dist/{cjs → browser/esm}/types/DataSet.d.ts +0 -0
  69. /package/dist/{cjs → browser/esm}/types/DataSource.d.ts +0 -0
  70. /package/dist/{cjs → browser/esm}/types/QueryResult.d.ts +0 -0
  71. /package/dist/{cjs → browser/esm}/types/adapters/QueryAdapter.d.ts +0 -0
  72. /package/dist/{cjs → browser/esm}/types/adapters/StorageAdapter.d.ts +0 -0
  73. /package/dist/{cjs → browser/esm}/types/adapters/index.d.ts +0 -0
  74. /package/dist/{cjs → browser/esm}/types/dsl/GroupBy.d.ts +0 -0
  75. /package/dist/{cjs → browser/esm}/types/dsl/OrderBy.d.ts +0 -0
  76. /package/dist/{cjs → browser/esm}/types/dsl/QueryDSL.d.ts +0 -0
  77. /package/dist/{cjs → browser/esm}/types/dsl/Select.d.ts +0 -0
  78. /package/dist/{cjs → browser/esm}/types/dsl/Where.d.ts +0 -0
  79. /package/dist/{cjs → browser/esm}/types/dsl/demo.d.ts +0 -0
  80. /package/dist/{cjs → browser/esm}/types/dsl/index.d.ts +0 -0
  81. /package/dist/{cjs → browser/esm}/types/index.d.ts +0 -0
  82. /package/dist/{cjs → browser/esm}/utils/index.d.ts +0 -0
  83. /package/dist/{cjs → browser/esm}/utils/url.d.ts +0 -0
  84. /package/dist/{cjs → browser/esm}/vquery-browser.d.ts +0 -0
  85. /package/dist/{cjs → browser/esm}/vquery-node.d.ts +0 -0
  86. /package/dist/{esm → node/cjs}/adapters/index.d.ts +0 -0
  87. /package/dist/{esm → node/cjs}/adapters/query-adapter/duckdbNodeAdapter.d.ts +0 -0
  88. /package/dist/{esm → node/cjs}/adapters/query-adapter/duckdbWebAdapter.d.ts +0 -0
  89. /package/dist/{esm → node/cjs}/adapters/storage-adapter/index.d.ts +0 -0
  90. /package/dist/{esm → node/cjs}/adapters/storage-adapter/indexeddbAdapter.d.ts +0 -0
  91. /package/dist/{esm → node/cjs}/adapters/storage-adapter/inmemoryAdapter.d.ts +0 -0
  92. /package/dist/{esm → node/cjs}/browser.d.ts +0 -0
  93. /package/dist/{esm → node/cjs}/data-source-builder/dataSourceBuilder.d.ts +0 -0
  94. /package/dist/{esm → node/cjs}/data-source-builder/index.d.ts +0 -0
  95. /package/dist/{esm → node/cjs}/dataset/dataset.d.ts +0 -0
  96. /package/dist/{esm → node/cjs}/dataset/index.d.ts +0 -0
  97. /package/dist/{cjs → node/cjs}/node.cjs +0 -0
  98. /package/dist/{esm → node/cjs}/node.d.ts +0 -0
  99. /package/dist/{esm → node/cjs}/sql-builder/builders/groupBy.d.ts +0 -0
  100. /package/dist/{esm → node/cjs}/sql-builder/builders/index.d.ts +0 -0
  101. /package/dist/{esm → node/cjs}/sql-builder/builders/limit.d.ts +0 -0
  102. /package/dist/{esm → node/cjs}/sql-builder/builders/where.d.ts +0 -0
  103. /package/dist/{esm → node/cjs}/sql-builder/compile/index.d.ts +0 -0
  104. /package/dist/{esm → node/cjs}/sql-builder/compile/inlineParameters.d.ts +0 -0
  105. /package/dist/{esm → node/cjs}/sql-builder/dialect/index.d.ts +0 -0
  106. /package/dist/{esm → node/cjs}/sql-builder/dialect/postgresDialect.d.ts +0 -0
  107. /package/dist/{esm → node/cjs}/sql-builder/dslToSQL.d.ts +0 -0
  108. /package/dist/{esm → node/cjs}/sql-builder/index.d.ts +0 -0
  109. /package/dist/{esm → node/cjs}/sql-builder/utils.d.ts +0 -0
  110. /package/dist/{esm → node/cjs}/types/DataSet.d.ts +0 -0
  111. /package/dist/{esm → node/cjs}/types/DataSource.d.ts +0 -0
  112. /package/dist/{esm → node/cjs}/types/QueryResult.d.ts +0 -0
  113. /package/dist/{esm → node/cjs}/types/adapters/QueryAdapter.d.ts +0 -0
  114. /package/dist/{esm → node/cjs}/types/adapters/StorageAdapter.d.ts +0 -0
  115. /package/dist/{esm → node/cjs}/types/adapters/index.d.ts +0 -0
  116. /package/dist/{esm → node/cjs}/types/dsl/GroupBy.d.ts +0 -0
  117. /package/dist/{esm → node/cjs}/types/dsl/OrderBy.d.ts +0 -0
  118. /package/dist/{esm → node/cjs}/types/dsl/QueryDSL.d.ts +0 -0
  119. /package/dist/{esm → node/cjs}/types/dsl/Select.d.ts +0 -0
  120. /package/dist/{esm → node/cjs}/types/dsl/Where.d.ts +0 -0
  121. /package/dist/{esm → node/cjs}/types/dsl/demo.d.ts +0 -0
  122. /package/dist/{esm → node/cjs}/types/dsl/index.d.ts +0 -0
  123. /package/dist/{esm → node/cjs}/types/index.d.ts +0 -0
  124. /package/dist/{esm → node/cjs}/utils/index.d.ts +0 -0
  125. /package/dist/{esm → node/cjs}/utils/url.d.ts +0 -0
  126. /package/dist/{esm → node/cjs}/vquery-browser.d.ts +0 -0
  127. /package/dist/{esm → node/cjs}/vquery-node.d.ts +0 -0
@@ -0,0 +1 @@
1
+ export { IndexedDBAdapter, InMemoryAdapter } from './storage-adapter';
@@ -0,0 +1,14 @@
1
+ import { QueryAdapter } from '../../types';
2
+ export declare class DuckDBNodeQueryAdapter implements QueryAdapter {
3
+ private bindings;
4
+ private connection;
5
+ constructor();
6
+ open: () => Promise<void>;
7
+ close: () => Promise<void>;
8
+ writeFile: <T extends Blob>(fileName: string, source: T) => Promise<void>;
9
+ query: (sql: string) => Promise<{
10
+ dataset: any[];
11
+ table: any;
12
+ }>;
13
+ getSchema: (fileName: string) => Promise<any>;
14
+ }
@@ -0,0 +1,14 @@
1
+ import { QueryAdapter } from '../../types';
2
+ export declare class DuckDBWebQueryAdapter implements QueryAdapter {
3
+ private db;
4
+ private connection;
5
+ constructor();
6
+ open: () => Promise<void>;
7
+ close: () => Promise<void>;
8
+ writeFile: <T extends Blob>(fileName: string, source: T) => Promise<void>;
9
+ query: (sql: string) => Promise<{
10
+ dataset: any[];
11
+ table: any;
12
+ }>;
13
+ getSchema: (fileName: string) => Promise<any>;
14
+ }
@@ -0,0 +1,2 @@
1
+ export { IndexedDBAdapter } from './indexeddbAdapter';
2
+ export { InMemoryAdapter } from './inmemoryAdapter';
@@ -0,0 +1,21 @@
1
+ import { DatasetSource, StorageAdapter } from '../../types';
2
+ import { DatasetSchema } from '../../types/DataSet';
3
+ export declare class IndexedDBAdapter implements StorageAdapter {
4
+ private db;
5
+ private dbName;
6
+ private datasetStoreName;
7
+ constructor(dbName?: string);
8
+ open: () => Promise<void>;
9
+ close: () => Promise<void>;
10
+ writeDataset: (datasetId: string, datasetSchema: DatasetSchema, datasetSource?: DatasetSource) => Promise<void>;
11
+ readDataset: (datasetId: string) => Promise<{
12
+ datasetSource?: DatasetSource;
13
+ datasetSchema: DatasetSchema;
14
+ } | null>;
15
+ deleteDataset: (datasetId: string) => Promise<void>;
16
+ listDatasets: () => Promise<{
17
+ datasetId: string;
18
+ dataSource?: DatasetSource;
19
+ datasetSchema: DatasetSchema;
20
+ }[]>;
21
+ }
@@ -0,0 +1,22 @@
1
+ import { DatasetSource, StorageAdapter } from '../../types';
2
+ import { DatasetSchema } from '../../types/DataSet';
3
+ type StoredDataset = {
4
+ datasetId: string;
5
+ datasetSchema: DatasetSchema;
6
+ datasetSource?: DatasetSource;
7
+ };
8
+ export declare class InMemoryAdapter implements StorageAdapter {
9
+ private datasets;
10
+ private isOpen;
11
+ constructor();
12
+ open: () => Promise<void>;
13
+ close: () => Promise<void>;
14
+ writeDataset: (datasetId: string, datasetSchema: DatasetSchema, datasetSource?: DatasetSource) => Promise<void>;
15
+ readDataset: (datasetId: string) => Promise<{
16
+ datasetSource?: DatasetSource;
17
+ datasetSchema: DatasetSchema;
18
+ } | null>;
19
+ deleteDataset: (datasetId: string) => Promise<void>;
20
+ listDatasets: () => Promise<StoredDataset[]>;
21
+ }
22
+ export {};
@@ -0,0 +1,5 @@
1
+ export { convertDSLToSQL } from './dataset';
2
+ export { DatasetSourceBuilder } from './data-source-builder/dataSourceBuilder';
3
+ export * from './utils';
4
+ export * from './types';
5
+ export { VQuery } from './vquery-browser';
@@ -0,0 +1,16 @@
1
+ import { DatasetSourceType, RawDatasetSource } from '../types';
2
+ export declare class DatasetSourceBuilder {
3
+ private type;
4
+ private value;
5
+ constructor(raw: RawDatasetSource);
6
+ static from(raw: RawDatasetSource): DatasetSourceBuilder;
7
+ build(): Promise<{
8
+ type: DatasetSourceType;
9
+ blob: Blob;
10
+ }>;
11
+ /**
12
+ * 将不同类型的数据转换为Blob
13
+ */
14
+ private static convertToBlob;
15
+ private static fetchBlob;
16
+ }
@@ -0,0 +1 @@
1
+ export { DatasetSourceBuilder } from './dataSourceBuilder';
@@ -0,0 +1,30 @@
1
+ import { DatasetColumn, DatasetSource, QueryDSL } from '../types';
2
+ import { QueryAdapter, StorageAdapter } from '../types';
3
+ export declare class Dataset {
4
+ private queryAdapter;
5
+ private storageAdapter;
6
+ private _datasetId;
7
+ constructor(duckDB: QueryAdapter, indexedDB: StorageAdapter, datasetId: string);
8
+ init(temporaryColumns?: DatasetColumn[], temporaryDatasetSource?: DatasetSource): Promise<void>;
9
+ createOrReplaceView(columns: DatasetColumn[], datasetSource: DatasetSource): Promise<void>;
10
+ query<T extends Record<string, number | string>>(queryDSL: QueryDSL<T>): Promise<{
11
+ performance: {
12
+ startAt: string;
13
+ endAt: string;
14
+ duration: number;
15
+ };
16
+ dataset: any[];
17
+ table: any;
18
+ }>;
19
+ queryBySQL(sql: string): Promise<{
20
+ performance: {
21
+ startAt: string;
22
+ endAt: string;
23
+ duration: number;
24
+ };
25
+ dataset: any[];
26
+ table: any;
27
+ }>;
28
+ disconnect(): Promise<void>;
29
+ get datasetId(): string;
30
+ }
@@ -0,0 +1,2 @@
1
+ export { Dataset } from './dataset';
2
+ export { convertDSLToSQL } from '../sql-builder';
@@ -0,0 +1,5 @@
1
+ export { convertDSLToSQL } from './dataset';
2
+ export { DatasetSourceBuilder } from './data-source-builder/dataSourceBuilder';
3
+ export * from './utils';
4
+ export * from './types';
5
+ export { VQuery } from './vquery-node';
@@ -0,0 +1,476 @@
1
+ import { DummyDriver, Kysely, PostgresAdapter, PostgresQueryCompiler, sql as external_kysely_sql } from "kysely";
2
+ import { ConsoleLogger, NODE_RUNTIME, createDuckDB } from "@duckdb/duckdb-wasm/blocking";
3
+ import { createRequire } from "node:module";
4
+ class PostgresDialect {
5
+ createDriver() {
6
+ return new DummyDriver();
7
+ }
8
+ createQueryCompiler() {
9
+ return new PostgresQueryCompiler();
10
+ }
11
+ createAdapter() {
12
+ return new PostgresAdapter();
13
+ }
14
+ createIntrospector(db) {
15
+ class NullIntrospector {
16
+ async getSchemas() {
17
+ return [];
18
+ }
19
+ async getTables(options) {
20
+ options?.withInternalKyselyTables;
21
+ return [];
22
+ }
23
+ async getMetadata(options) {
24
+ options?.withInternalKyselyTables;
25
+ return {
26
+ tables: []
27
+ };
28
+ }
29
+ }
30
+ return new NullIntrospector();
31
+ }
32
+ }
33
+ const isSelectItem = (item)=>'object' == typeof item && 'field' in item;
34
+ const escapeValue = (value)=>{
35
+ if (null === value) return 'null';
36
+ if ('string' == typeof value) return `'${value.replace(/'/g, "''")}'`;
37
+ if ('number' == typeof value) return `${value}`;
38
+ if ('boolean' == typeof value) return value ? 'TRUE' : 'FALSE';
39
+ return `'${String(value).replace(/'/g, "''")}'`;
40
+ };
41
+ const inlineParameters = (sql, params)=>{
42
+ if (0 === params.length) return sql;
43
+ if (sql.includes('?')) {
44
+ let out = sql;
45
+ for (const p of params)out = out.replace(/\?/, escapeValue(p));
46
+ return out;
47
+ }
48
+ if (/\$\d+/.test(sql)) return sql.replace(/\$(\d+)/g, (_, idx)=>{
49
+ const i = Number(idx) - 1;
50
+ const v = params[i];
51
+ return escapeValue(v);
52
+ });
53
+ return sql;
54
+ };
55
+ const applyWhere = (where)=>{
56
+ const toRaw = (w)=>{
57
+ if ('op' in w && 'conditions' in w) {
58
+ const parts = w.conditions.map((c)=>toRaw(c));
59
+ const sep = external_kysely_sql` ${external_kysely_sql.raw(w.op)} `;
60
+ return external_kysely_sql`(${external_kysely_sql.join(parts, sep)})`;
61
+ }
62
+ const leaf = w;
63
+ const field = leaf.field;
64
+ const value = leaf.value;
65
+ switch(leaf.op){
66
+ case 'is null':
67
+ return external_kysely_sql`${external_kysely_sql.ref(field)} is null`;
68
+ case 'is not null':
69
+ return external_kysely_sql`${external_kysely_sql.ref(field)} is not null`;
70
+ case 'in':
71
+ {
72
+ const items = Array.isArray(value) ? value : [
73
+ value
74
+ ];
75
+ return external_kysely_sql`${external_kysely_sql.ref(field)} in (${external_kysely_sql.join(items.map((v)=>external_kysely_sql.val(v)))})`;
76
+ }
77
+ case 'not in':
78
+ {
79
+ const items = Array.isArray(value) ? value : [
80
+ value
81
+ ];
82
+ return external_kysely_sql`not ${external_kysely_sql.ref(field)} in (${external_kysely_sql.join(items.map((v)=>external_kysely_sql.val(v)))})`;
83
+ }
84
+ case 'between':
85
+ {
86
+ const [a, b] = value;
87
+ return external_kysely_sql`${external_kysely_sql.ref(field)} between (${external_kysely_sql.val(a)}, ${external_kysely_sql.val(b)})`;
88
+ }
89
+ case 'not between':
90
+ {
91
+ const [a, b] = value;
92
+ return external_kysely_sql`not ${external_kysely_sql.ref(field)} between (${external_kysely_sql.val(a)}, ${external_kysely_sql.val(b)})`;
93
+ }
94
+ default:
95
+ return external_kysely_sql`${external_kysely_sql.ref(field)} ${external_kysely_sql.raw(leaf.op)} ${external_kysely_sql.val(value)}`;
96
+ }
97
+ };
98
+ return toRaw(where);
99
+ };
100
+ const applyGroupBy = (qb, fields)=>{
101
+ if (fields && fields.length > 0) {
102
+ const exprs = fields.map((f)=>external_kysely_sql.id(f));
103
+ qb = qb.groupBy(exprs);
104
+ }
105
+ return qb;
106
+ };
107
+ const applyLimit = (qb, limit)=>{
108
+ if (limit && 'number' == typeof limit) qb = qb.limit(limit);
109
+ return qb;
110
+ };
111
+ const convertDSLToSQL = (dsl, tableName)=>{
112
+ const db = new Kysely({
113
+ dialect: new PostgresDialect()
114
+ });
115
+ let qb = db.selectFrom(tableName);
116
+ qb = dsl.select && dsl.select.length > 0 ? qb.select((eb)=>dsl.select.map((item)=>{
117
+ if (isSelectItem(item)) {
118
+ const field = item.field;
119
+ if (item.func) {
120
+ const alias = item.alias ?? field;
121
+ switch(item.func){
122
+ case 'avg':
123
+ return eb.fn.avg(field).as(alias);
124
+ case 'sum':
125
+ return eb.fn.sum(field).as(alias);
126
+ case 'min':
127
+ return eb.fn.min(field).as(alias);
128
+ case 'max':
129
+ return eb.fn.max(field).as(alias);
130
+ case 'count':
131
+ return eb.fn.count(field).as(alias);
132
+ }
133
+ }
134
+ return item.alias ? eb.ref(field).as(item.alias) : field;
135
+ }
136
+ return item;
137
+ })) : qb.selectAll();
138
+ if (dsl.where) qb = qb.where(applyWhere(dsl.where));
139
+ qb = applyGroupBy(qb, dsl.groupBy);
140
+ if (dsl.orderBy && dsl.orderBy.length > 0) for (const o of dsl.orderBy)qb = qb.orderBy(o.field, o.order ?? 'asc');
141
+ qb = applyLimit(qb, dsl.limit);
142
+ const compiled = qb.compile();
143
+ return inlineParameters(compiled.sql, compiled.parameters);
144
+ };
145
+ class Dataset {
146
+ queryAdapter;
147
+ storageAdapter;
148
+ _datasetId;
149
+ constructor(duckDB, indexedDB, datasetId){
150
+ this.queryAdapter = duckDB;
151
+ this.storageAdapter = indexedDB;
152
+ this._datasetId = datasetId;
153
+ }
154
+ async init(temporaryColumns, temporaryDatasetSource) {
155
+ const datasetInfo = await this.storageAdapter.readDataset(this._datasetId);
156
+ if (!datasetInfo) throw new Error(`Dataset ${this._datasetId} not found`);
157
+ const columns = temporaryColumns ? temporaryColumns : datasetInfo.datasetSchema.columns;
158
+ const datasetSource = temporaryDatasetSource || datasetInfo.datasetSource;
159
+ if (columns.length > 0 && datasetSource) await this.createOrReplaceView(columns, datasetSource);
160
+ }
161
+ async createOrReplaceView(columns, datasetSource) {
162
+ const readFunctionMap = {
163
+ csv: 'read_csv_auto',
164
+ json: 'read_json_auto',
165
+ xlsx: 'read_excel',
166
+ parquet: 'read_parquet'
167
+ };
168
+ const dataTypeMap = {
169
+ number: 'DOUBLE',
170
+ string: 'VARCHAR',
171
+ date: 'DATE',
172
+ datetime: 'TIMESTAMP',
173
+ timestamp: 'TIMESTAMP'
174
+ };
175
+ if (datasetSource) {
176
+ const readFunction = readFunctionMap[datasetSource.type];
177
+ if (!readFunction) throw new Error(`Unsupported dataSource type: ${datasetSource.type}`);
178
+ await this.queryAdapter.writeFile(this._datasetId, datasetSource.blob);
179
+ const columnsStruct = `{${columns.map((c)=>`'${c.name}': '${dataTypeMap[c.type] || 'VARCHAR'}'`).join(', ')}}`;
180
+ const columnNames = columns.map((c)=>`"${c.name}"`).join(', ');
181
+ const createViewSql = `CREATE OR REPLACE VIEW "${this._datasetId}" AS SELECT ${columnNames} FROM ${readFunction}('${this._datasetId}', columns=${columnsStruct})`;
182
+ await this.queryAdapter.query(createViewSql);
183
+ }
184
+ }
185
+ async query(queryDSL) {
186
+ const sql = convertDSLToSQL(queryDSL, this.datasetId);
187
+ return this.queryBySQL(sql);
188
+ }
189
+ async queryBySQL(sql) {
190
+ const start = performance?.now?.()?.toFixed(3) ?? Date.now().toFixed(3);
191
+ const result = await this.queryAdapter.query(sql);
192
+ const end = performance?.now?.()?.toFixed(3) ?? Date.now().toFixed(3);
193
+ return {
194
+ ...result,
195
+ performance: {
196
+ startAt: start,
197
+ endAt: end,
198
+ duration: Number(end) - Number(start)
199
+ }
200
+ };
201
+ }
202
+ async disconnect() {
203
+ await this.queryAdapter.query(`DROP VIEW IF EXISTS "${this._datasetId}"`);
204
+ }
205
+ get datasetId() {
206
+ return this._datasetId;
207
+ }
208
+ }
209
+ const isUrl = (url)=>isHttpUrl(url) || isBase64Url(url);
210
+ const isHttpUrl = (url)=>url.startsWith('http://') || url.startsWith('https://');
211
+ const isBase64Url = (url)=>url.startsWith('data:');
212
+ class DatasetSourceBuilder {
213
+ type;
214
+ value;
215
+ constructor(raw){
216
+ this.type = raw.type;
217
+ this.value = raw.rawDataset;
218
+ }
219
+ static from(raw) {
220
+ return new DatasetSourceBuilder(raw);
221
+ }
222
+ async build() {
223
+ const blob = await DatasetSourceBuilder.convertToBlob(this.type, this.value);
224
+ return {
225
+ type: this.type,
226
+ blob: blob
227
+ };
228
+ }
229
+ static async convertToBlob(type, value) {
230
+ if (value instanceof Blob) return value;
231
+ const convertCsvToBlob = (csvSource)=>{
232
+ if (csvSource instanceof ArrayBuffer) return new Blob([
233
+ csvSource
234
+ ], {
235
+ type: 'text/csv'
236
+ });
237
+ if ('string' == typeof csvSource && isUrl(csvSource)) return DatasetSourceBuilder.fetchBlob(csvSource);
238
+ return new Blob([
239
+ JSON.stringify(csvSource)
240
+ ], {
241
+ type: 'text/csv'
242
+ });
243
+ };
244
+ const convertJsonToBlob = (jsonSource)=>{
245
+ if (jsonSource instanceof ArrayBuffer) return new Blob([
246
+ jsonSource
247
+ ], {
248
+ type: 'application/json'
249
+ });
250
+ if ('string' == typeof jsonSource && isUrl(jsonSource)) return DatasetSourceBuilder.fetchBlob(jsonSource);
251
+ return new Blob([
252
+ JSON.stringify(jsonSource)
253
+ ], {
254
+ type: 'application/json'
255
+ });
256
+ };
257
+ const convertParquetToBlob = (parquetSource)=>{
258
+ if (parquetSource instanceof ArrayBuffer) return new Blob([
259
+ parquetSource
260
+ ], {
261
+ type: 'application/parquet'
262
+ });
263
+ if ('string' == typeof parquetSource && isUrl(parquetSource)) return DatasetSourceBuilder.fetchBlob(parquetSource);
264
+ return new Blob([
265
+ parquetSource
266
+ ], {
267
+ type: 'application/parquet'
268
+ });
269
+ };
270
+ const convertXlsxToBlob = (xlsxSource)=>{
271
+ if (xlsxSource instanceof ArrayBuffer) return new Blob([
272
+ xlsxSource
273
+ ], {
274
+ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
275
+ });
276
+ if ('string' == typeof xlsxSource && isUrl(xlsxSource)) return DatasetSourceBuilder.fetchBlob(xlsxSource);
277
+ return new Blob([
278
+ xlsxSource
279
+ ], {
280
+ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
281
+ });
282
+ };
283
+ switch(type){
284
+ case 'csv':
285
+ return convertCsvToBlob(value);
286
+ case 'json':
287
+ return convertJsonToBlob(value);
288
+ case 'xlsx':
289
+ return convertXlsxToBlob(value);
290
+ case 'parquet':
291
+ return convertParquetToBlob(value);
292
+ default:
293
+ return new Blob([
294
+ value
295
+ ]);
296
+ }
297
+ }
298
+ static async fetchBlob(url) {
299
+ const response = await fetch(url);
300
+ return await response.blob();
301
+ }
302
+ }
303
+ class InMemoryAdapter {
304
+ datasets = new Map();
305
+ isOpen = false;
306
+ constructor(){}
307
+ open = async ()=>{
308
+ this.isOpen = true;
309
+ if (!this.isOpen) this.datasets = new Map();
310
+ };
311
+ close = async ()=>{
312
+ this.isOpen = false;
313
+ this.datasets.clear();
314
+ };
315
+ writeDataset = (datasetId, datasetSchema, datasetSource)=>new Promise((resolve, reject)=>{
316
+ try {
317
+ const record = {
318
+ datasetId,
319
+ datasetSchema,
320
+ datasetSource
321
+ };
322
+ this.datasets.set(datasetId, record);
323
+ resolve();
324
+ } catch (error) {
325
+ reject(error);
326
+ }
327
+ });
328
+ readDataset = (datasetId)=>new Promise((resolve, reject)=>{
329
+ try {
330
+ const record = this.datasets.get(datasetId);
331
+ resolve(record ? record : null);
332
+ } catch (error) {
333
+ reject(error);
334
+ }
335
+ });
336
+ deleteDataset = (datasetId)=>new Promise((resolve, reject)=>{
337
+ try {
338
+ this.datasets.delete(datasetId);
339
+ resolve();
340
+ } catch (error) {
341
+ reject(error);
342
+ }
343
+ });
344
+ listDatasets = ()=>new Promise((resolve, reject)=>{
345
+ try {
346
+ resolve(Array.from(this.datasets.values()));
347
+ } catch (error) {
348
+ reject(error);
349
+ }
350
+ });
351
+ }
352
+ class DuckDBNodeQueryAdapter {
353
+ bindings = null;
354
+ connection = null;
355
+ constructor(){}
356
+ open = async ()=>{
357
+ const require = createRequire(import.meta.url);
358
+ const MANUAL_BUNDLES = {
359
+ mvp: {
360
+ mainModule: require.resolve('@duckdb/duckdb-wasm/dist/duckdb-mvp.wasm'),
361
+ mainWorker: ''
362
+ },
363
+ eh: {
364
+ mainModule: require.resolve('@duckdb/duckdb-wasm/dist/duckdb-eh.wasm'),
365
+ mainWorker: ''
366
+ }
367
+ };
368
+ const logger = new ConsoleLogger();
369
+ this.bindings = await createDuckDB(MANUAL_BUNDLES, logger, NODE_RUNTIME);
370
+ await this.bindings.instantiate(()=>{});
371
+ this.bindings.open({});
372
+ this.connection = this.bindings.connect();
373
+ };
374
+ close = async ()=>{
375
+ if (this.connection) {
376
+ this.connection.close();
377
+ this.connection = null;
378
+ }
379
+ if (this.bindings) {
380
+ this.bindings.reset();
381
+ this.bindings = null;
382
+ }
383
+ };
384
+ writeFile = async (fileName, source)=>{
385
+ if (!this.bindings) throw new Error('bindings is null');
386
+ let uint8Array;
387
+ if (source instanceof Blob) {
388
+ const buffer = await source.arrayBuffer();
389
+ uint8Array = new Uint8Array(buffer);
390
+ } else throw new Error('Unsupported source type');
391
+ await this.bindings.registerFileBuffer(fileName, uint8Array);
392
+ };
393
+ query = async (sql)=>{
394
+ if (!this.connection) throw new Error('connection is null');
395
+ const table = await this.connection.query(sql);
396
+ const dataset = table.toArray().map((row)=>row.toJSON());
397
+ return {
398
+ dataset,
399
+ table
400
+ };
401
+ };
402
+ getSchema = async (fileName)=>{
403
+ if (!this.connection) throw new Error('connection is null');
404
+ const result = await this.connection.query(`PRAGMA table_info('${fileName}')`);
405
+ return result.toArray().map((row)=>row.toJSON());
406
+ };
407
+ }
408
+ class VQuery {
409
+ queryAdapter;
410
+ storageAdapter;
411
+ isInitialized = false;
412
+ constructor(){
413
+ this.queryAdapter = new DuckDBNodeQueryAdapter();
414
+ this.storageAdapter = new InMemoryAdapter();
415
+ }
416
+ async checkInitialized() {
417
+ if (!this.isInitialized) {
418
+ await this.queryAdapter.open();
419
+ await this.storageAdapter.open();
420
+ this.isInitialized = true;
421
+ }
422
+ }
423
+ async checkDatasetExists(datasetId) {
424
+ if (!await this.hasDataset(datasetId)) throw new Error(`dataset ${datasetId} not exists, please create it first`);
425
+ }
426
+ async createDataset(datasetId, columns = [], rawDatasetSource) {
427
+ await this.checkInitialized();
428
+ const datasetSource = rawDatasetSource ? await DatasetSourceBuilder.from(rawDatasetSource).build() : void 0;
429
+ if (await this.hasDataset(datasetId)) throw new Error(`dataset ${datasetId} already exists`);
430
+ const datasetSchema = {
431
+ datasetId,
432
+ datasetAlias: datasetId,
433
+ columns: columns
434
+ };
435
+ await this.storageAdapter.writeDataset(datasetId, datasetSchema, datasetSource);
436
+ }
437
+ async updateDatasetSource(datasetId, columns = [], rawDatasetSource) {
438
+ await this.checkInitialized();
439
+ await this.checkDatasetExists(datasetId);
440
+ const datasetSource = rawDatasetSource ? await DatasetSourceBuilder.from(rawDatasetSource).build() : void 0;
441
+ const datasetSchema = {
442
+ datasetId,
443
+ datasetAlias: datasetId,
444
+ columns: columns
445
+ };
446
+ await this.storageAdapter.writeDataset(datasetId, datasetSchema, datasetSource);
447
+ }
448
+ async dropDataset(datasetId) {
449
+ await this.checkInitialized();
450
+ await this.checkDatasetExists(datasetId);
451
+ await this.storageAdapter.deleteDataset(datasetId);
452
+ }
453
+ async connectDataset(datasetId, temporaryColumns, temporaryRawDatasetSource) {
454
+ await this.checkInitialized();
455
+ await this.checkDatasetExists(datasetId);
456
+ const dataset = new Dataset(this.queryAdapter, this.storageAdapter, datasetId);
457
+ const temporaryDatasetSource = temporaryRawDatasetSource ? await DatasetSourceBuilder.from(temporaryRawDatasetSource).build() : void 0;
458
+ await dataset.init(temporaryColumns, temporaryDatasetSource);
459
+ return dataset;
460
+ }
461
+ async hasDataset(datasetId) {
462
+ await this.checkInitialized();
463
+ const datasets = await this.storageAdapter.listDatasets();
464
+ return datasets.some((item)=>item.datasetId === datasetId);
465
+ }
466
+ async listDatasets() {
467
+ await this.checkInitialized();
468
+ return this.storageAdapter.listDatasets();
469
+ }
470
+ async close() {
471
+ await this.checkInitialized();
472
+ await this.queryAdapter.close();
473
+ await this.storageAdapter.close();
474
+ }
475
+ }
476
+ export { DatasetSourceBuilder, VQuery, convertDSLToSQL, isBase64Url, isHttpUrl, isUrl };
@@ -0,0 +1,2 @@
1
+ import type { SelectQueryBuilder } from 'kysely';
2
+ export declare const applyGroupBy: <DB, TB extends keyof DB & string, O>(qb: SelectQueryBuilder<DB, TB, O>, fields?: Array<string>) => SelectQueryBuilder<DB, TB, O>;
@@ -0,0 +1,3 @@
1
+ export { applyWhere } from './where';
2
+ export { applyGroupBy } from './groupBy';
3
+ export { applyLimit } from './limit';
@@ -0,0 +1,2 @@
1
+ import type { SelectQueryBuilder } from 'kysely';
2
+ export declare const applyLimit: <DB, TB extends keyof DB & string, O>(qb: SelectQueryBuilder<DB, TB, O>, limit?: number) => SelectQueryBuilder<DB, TB, O>;
@@ -0,0 +1,3 @@
1
+ import { Where, WhereClause } from '../../types';
2
+ import type { RawBuilder } from 'kysely';
3
+ export declare const applyWhere: <T>(where: Where<T> | WhereClause<T>) => RawBuilder<boolean>;
@@ -0,0 +1 @@
1
+ export { inlineParameters } from './inlineParameters';
@@ -0,0 +1 @@
1
+ export declare const inlineParameters: (sql: string, params: readonly unknown[]) => string;
@@ -0,0 +1 @@
1
+ export { PostgresDialect } from './postgresDialect';
@@ -0,0 +1,11 @@
1
+ import { Dialect, DummyDriver } from 'kysely';
2
+ import { PostgresQueryCompiler } from 'kysely';
3
+ import { PostgresAdapter } from 'kysely';
4
+ import { Kysely } from 'kysely';
5
+ import type { DatabaseIntrospector } from 'kysely';
6
+ export declare class PostgresDialect implements Dialect {
7
+ createDriver(): DummyDriver;
8
+ createQueryCompiler(): PostgresQueryCompiler;
9
+ createAdapter(): PostgresAdapter;
10
+ createIntrospector<DB = unknown>(db: Kysely<DB>): DatabaseIntrospector;
11
+ }
@@ -0,0 +1,2 @@
1
+ import { QueryDSL } from '../types';
2
+ export declare const convertDSLToSQL: <T, TableName extends string>(dsl: QueryDSL<T>, tableName: TableName) => string;
@@ -0,0 +1 @@
1
+ export { convertDSLToSQL } from './dslToSQL';