remult 3.0.1 → 3.0.2

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.
@@ -1,10 +1,13 @@
1
+ import { DuckDBTypeId } from '@duckdb/node-api';
1
2
  import { SqliteCoreDataProvider } from './remult-sqlite-core.js';
2
3
  import { ValueConverters, dbNamesOf, } from './index.js';
3
4
  import { shouldNotCreateField } from './src/filter/filter-consumer-bridge-to-sql-request.js';
4
5
  import { isAutoIncrement } from './src/remult3/RepositoryImplementation.js';
5
6
  export class DuckDBDataProvider extends SqliteCoreDataProvider {
6
- constructor(db) {
7
- super(() => new DuckDBCommand(db), async () => (await db).close(), false, true);
7
+ connection;
8
+ constructor(connection) {
9
+ super(() => new DuckDBCommand(this.connection), async () => this.connection.disconnectSync(), false, true);
10
+ this.connection = connection;
8
11
  }
9
12
  wrapIdentifier(name) {
10
13
  return `"${name}"`;
@@ -12,7 +15,8 @@ export class DuckDBDataProvider extends SqliteCoreDataProvider {
12
15
  async getCreateTableSql(entity) {
13
16
  let result = '';
14
17
  let e = await dbNamesOf(entity, this.wrapIdentifier);
15
- let sql = '';
18
+ const createSequenceStatements = [];
19
+ let createTableSql = '';
16
20
  for (const x of entity.fields) {
17
21
  if (!shouldNotCreateField(x, e) || isAutoIncrement(x)) {
18
22
  if (result.length != 0)
@@ -20,7 +24,7 @@ export class DuckDBDataProvider extends SqliteCoreDataProvider {
20
24
  result += '\r\n ';
21
25
  if (isAutoIncrement(x)) {
22
26
  const sequenceName = `${entity.dbName}_${x.dbName}_seq`;
23
- sql += `create sequence if not exists "${sequenceName}";\r\n`;
27
+ createSequenceStatements.push(`create sequence if not exists "${sequenceName}";`);
24
28
  result += `${e.$dbNameOf(x)} integer default nextval('${sequenceName}')`;
25
29
  }
26
30
  else {
@@ -31,9 +35,9 @@ export class DuckDBDataProvider extends SqliteCoreDataProvider {
31
35
  result += `,\r\n primary key (${entity.idMetadata.fields
32
36
  .map((f) => e.$dbNameOf(f))
33
37
  .join(',')})`;
34
- sql +=
38
+ createTableSql =
35
39
  'create table if not exists ' + e.$entityName + ' (' + result + '\r\n)';
36
- return [sql];
40
+ return [...createSequenceStatements, createTableSql];
37
41
  }
38
42
  addColumnSqlSyntax(x, dbName, isAlterColumn) {
39
43
  let result = dbName;
@@ -74,38 +78,83 @@ export class DuckDBDataProvider extends SqliteCoreDataProvider {
74
78
  }
75
79
  }
76
80
  class DuckDBCommand {
77
- db;
81
+ connection;
78
82
  values = [];
79
- constructor(db) {
80
- this.db = db;
83
+ constructor(connection) {
84
+ this.connection = connection;
81
85
  }
82
86
  async execute(sql) {
83
- return new Promise((resolve, error) => {
84
- this.db.all(sql, ...this.values, (err, rows) => {
85
- if (err)
86
- error(err);
87
- else
88
- resolve(new DuckDBSqlResult(rows));
89
- });
90
- });
87
+ try {
88
+ const result = await this.connection.run(sql, this.values);
89
+ this.values = [];
90
+ return new DuckDBSqlResult(result);
91
+ }
92
+ catch (err) {
93
+ this.values = [];
94
+ throw err;
95
+ }
96
+ }
97
+ addParamInternal(val) {
98
+ if (val === undefined) {
99
+ this.values.push(null);
100
+ }
101
+ else if (val instanceof Date) {
102
+ this.values.push(val.toISOString());
103
+ }
104
+ else {
105
+ this.values.push(val);
106
+ }
107
+ return '?';
91
108
  }
92
109
  addParameterAndReturnSqlToken(val) {
93
- return this.param(val);
110
+ return this.addParamInternal(val);
94
111
  }
95
112
  param(val) {
96
- const key = '?';
97
- this.values.push(val);
98
- return key;
113
+ return this.addParamInternal(val);
99
114
  }
100
115
  }
101
116
  class DuckDBSqlResult {
102
- result;
103
- constructor(result) {
104
- this.result = result;
105
- this.rows = result;
106
- }
117
+ duckDbResult;
107
118
  rows;
119
+ constructor(duckDbResult) {
120
+ this.duckDbResult = duckDbResult;
121
+ this.rows = [];
122
+ const columnNames = this.duckDbResult.columnNames();
123
+ const columnTypes = this.duckDbResult.columnTypes();
124
+ const chunkCount = this.duckDbResult.chunkCount;
125
+ for (let i = 0; i < chunkCount; i++) {
126
+ const chunk = this.duckDbResult.getChunk(i);
127
+ const chunkRowObjects = chunk.getRowObjects(columnNames).map((row) => {
128
+ const convertedRow = {};
129
+ columnNames.forEach((colName, colIndex) => {
130
+ const value = row[colName];
131
+ if (value === null) {
132
+ convertedRow[colName] = null;
133
+ }
134
+ else {
135
+ const colType = columnTypes[colIndex];
136
+ const typeId = colType.typeId;
137
+ if (typeId === DuckDBTypeId.TIMESTAMP) {
138
+ const timestampValue = value;
139
+ const parts = timestampValue.toParts();
140
+ convertedRow[colName] = new Date(Date.UTC(parts.date.year, parts.date.month - 1, parts.date.day, parts.time.hour, parts.time.min, parts.time.sec, Math.floor(parts.time.micros / 1000)));
141
+ }
142
+ else if (typeId === DuckDBTypeId.DATE) {
143
+ const dateValue = value;
144
+ const parts = dateValue.toParts();
145
+ convertedRow[colName] = new Date(Date.UTC(parts.year, parts.month - 1, parts.day));
146
+ }
147
+ else {
148
+ convertedRow[colName] = value;
149
+ }
150
+ }
151
+ });
152
+ return convertedRow;
153
+ });
154
+ this.rows.push(...chunkRowObjects);
155
+ }
156
+ }
108
157
  getColumnKeyInResultForIndexInSelect(index) {
109
- return Object.keys(this.result[0])[index];
158
+ return this.duckDbResult.columnName(index);
110
159
  }
111
160
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remult",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "description": "A CRUD framework for full-stack TypeScript",
5
5
  "homepage": "https://remult.dev",
6
6
  "repository": {
@@ -1,8 +1,9 @@
1
- import type { Database } from 'duckdb';
1
+ import type { DuckDBConnection } from '@duckdb/node-api';
2
2
  import { SqliteCoreDataProvider } from './remult-sqlite-core.js';
3
3
  import { type FieldMetadata, type EntityMetadata } from './index.js';
4
4
  export declare class DuckDBDataProvider extends SqliteCoreDataProvider {
5
- constructor(db: Database);
5
+ private connection;
6
+ constructor(connection: DuckDBConnection);
6
7
  wrapIdentifier(name: string): string;
7
8
  getCreateTableSql(entity: EntityMetadata<any>): Promise<string[]>;
8
9
  addColumnSqlSyntax(x: FieldMetadata, dbName: string, isAlterColumn: boolean): string;
package/remult-duckdb.js CHANGED
@@ -2,19 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DuckDBDataProvider = void 0;
4
4
  var tslib_1 = require("tslib");
5
+ var node_api_1 = require("@duckdb/node-api");
5
6
  var remult_sqlite_core_js_1 = require("./remult-sqlite-core.js");
6
7
  var index_js_1 = require("./index.js");
7
8
  var filter_consumer_bridge_to_sql_request_js_1 = require("./src/filter/filter-consumer-bridge-to-sql-request.js");
8
9
  var RepositoryImplementation_js_1 = require("./src/remult3/RepositoryImplementation.js");
9
10
  var DuckDBDataProvider = /** @class */ (function (_super) {
10
11
  tslib_1.__extends(DuckDBDataProvider, _super);
11
- function DuckDBDataProvider(db) {
12
- var _this = _super.call(this, function () { return new DuckDBCommand(db); }, function () { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) {
13
- switch (_a.label) {
14
- case 0: return [4 /*yield*/, db];
15
- case 1: return [2 /*return*/, (_a.sent()).close()];
16
- }
12
+ function DuckDBDataProvider(connection) {
13
+ var _this = _super.call(this, function () { return new DuckDBCommand(_this.connection); }, function () { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) {
14
+ return [2 /*return*/, this.connection.disconnectSync()];
17
15
  }); }); }, false, true) || this;
16
+ _this.connection = connection;
18
17
  return _this;
19
18
  }
20
19
  DuckDBDataProvider.prototype.wrapIdentifier = function (name) {
@@ -22,7 +21,7 @@ var DuckDBDataProvider = /** @class */ (function (_super) {
22
21
  };
23
22
  DuckDBDataProvider.prototype.getCreateTableSql = function (entity) {
24
23
  return tslib_1.__awaiter(this, void 0, void 0, function () {
25
- var result, e, sql, _a, _b, x, sequenceName;
24
+ var result, e, createSequenceStatements, createTableSql, _a, _b, x, sequenceName;
26
25
  var e_1, _c;
27
26
  return tslib_1.__generator(this, function (_d) {
28
27
  switch (_d.label) {
@@ -31,7 +30,8 @@ var DuckDBDataProvider = /** @class */ (function (_super) {
31
30
  return [4 /*yield*/, (0, index_js_1.dbNamesOf)(entity, this.wrapIdentifier)];
32
31
  case 1:
33
32
  e = _d.sent();
34
- sql = '';
33
+ createSequenceStatements = [];
34
+ createTableSql = '';
35
35
  try {
36
36
  for (_a = tslib_1.__values(entity.fields), _b = _a.next(); !_b.done; _b = _a.next()) {
37
37
  x = _b.value;
@@ -41,7 +41,7 @@ var DuckDBDataProvider = /** @class */ (function (_super) {
41
41
  result += '\r\n ';
42
42
  if ((0, RepositoryImplementation_js_1.isAutoIncrement)(x)) {
43
43
  sequenceName = "".concat(entity.dbName, "_").concat(x.dbName, "_seq");
44
- sql += "create sequence if not exists \"".concat(sequenceName, "\";\r\n");
44
+ createSequenceStatements.push("create sequence if not exists \"".concat(sequenceName, "\";"));
45
45
  result += "".concat(e.$dbNameOf(x), " integer default nextval('").concat(sequenceName, "')");
46
46
  }
47
47
  else {
@@ -60,9 +60,9 @@ var DuckDBDataProvider = /** @class */ (function (_super) {
60
60
  result += ",\r\n primary key (".concat(entity.idMetadata.fields
61
61
  .map(function (f) { return e.$dbNameOf(f); })
62
62
  .join(','), ")");
63
- sql +=
63
+ createTableSql =
64
64
  'create table if not exists ' + e.$entityName + ' (' + result + '\r\n)';
65
- return [2 /*return*/, [sql]];
65
+ return [2 /*return*/, tslib_1.__spreadArray(tslib_1.__spreadArray([], tslib_1.__read(createSequenceStatements), false), [createTableSql], false)];
66
66
  }
67
67
  });
68
68
  });
@@ -108,43 +108,93 @@ var DuckDBDataProvider = /** @class */ (function (_super) {
108
108
  }(remult_sqlite_core_js_1.SqliteCoreDataProvider));
109
109
  exports.DuckDBDataProvider = DuckDBDataProvider;
110
110
  var DuckDBCommand = /** @class */ (function () {
111
- function DuckDBCommand(db) {
112
- this.db = db;
111
+ function DuckDBCommand(connection) {
112
+ this.connection = connection;
113
113
  this.values = [];
114
114
  }
115
115
  DuckDBCommand.prototype.execute = function (sql) {
116
116
  return tslib_1.__awaiter(this, void 0, void 0, function () {
117
- var _this = this;
117
+ var result, err_1;
118
118
  return tslib_1.__generator(this, function (_a) {
119
- return [2 /*return*/, new Promise(function (resolve, error) {
120
- var _a;
121
- (_a = _this.db).all.apply(_a, tslib_1.__spreadArray(tslib_1.__spreadArray([sql], tslib_1.__read(_this.values), false), [function (err, rows) {
122
- if (err)
123
- error(err);
124
- else
125
- resolve(new DuckDBSqlResult(rows));
126
- }], false));
127
- })];
119
+ switch (_a.label) {
120
+ case 0:
121
+ _a.trys.push([0, 2, , 3]);
122
+ return [4 /*yield*/, this.connection.run(sql, this.values)];
123
+ case 1:
124
+ result = _a.sent();
125
+ this.values = [];
126
+ return [2 /*return*/, new DuckDBSqlResult(result)];
127
+ case 2:
128
+ err_1 = _a.sent();
129
+ this.values = [];
130
+ throw err_1;
131
+ case 3: return [2 /*return*/];
132
+ }
128
133
  });
129
134
  });
130
135
  };
136
+ DuckDBCommand.prototype.addParamInternal = function (val) {
137
+ if (val === undefined) {
138
+ this.values.push(null);
139
+ }
140
+ else if (val instanceof Date) {
141
+ this.values.push(val.toISOString());
142
+ }
143
+ else {
144
+ this.values.push(val);
145
+ }
146
+ return '?';
147
+ };
131
148
  DuckDBCommand.prototype.addParameterAndReturnSqlToken = function (val) {
132
- return this.param(val);
149
+ return this.addParamInternal(val);
133
150
  };
134
151
  DuckDBCommand.prototype.param = function (val) {
135
- var key = '?';
136
- this.values.push(val);
137
- return key;
152
+ return this.addParamInternal(val);
138
153
  };
139
154
  return DuckDBCommand;
140
155
  }());
141
156
  var DuckDBSqlResult = /** @class */ (function () {
142
- function DuckDBSqlResult(result) {
143
- this.result = result;
144
- this.rows = result;
157
+ function DuckDBSqlResult(duckDbResult) {
158
+ var _a;
159
+ this.duckDbResult = duckDbResult;
160
+ this.rows = [];
161
+ var columnNames = this.duckDbResult.columnNames();
162
+ var columnTypes = this.duckDbResult.columnTypes();
163
+ var chunkCount = this.duckDbResult.chunkCount;
164
+ for (var i = 0; i < chunkCount; i++) {
165
+ var chunk = this.duckDbResult.getChunk(i);
166
+ var chunkRowObjects = chunk.getRowObjects(columnNames).map(function (row) {
167
+ var convertedRow = {};
168
+ columnNames.forEach(function (colName, colIndex) {
169
+ var value = row[colName];
170
+ if (value === null) {
171
+ convertedRow[colName] = null;
172
+ }
173
+ else {
174
+ var colType = columnTypes[colIndex];
175
+ var typeId = colType.typeId;
176
+ if (typeId === node_api_1.DuckDBTypeId.TIMESTAMP) {
177
+ var timestampValue = value;
178
+ var parts = timestampValue.toParts();
179
+ convertedRow[colName] = new Date(Date.UTC(parts.date.year, parts.date.month - 1, parts.date.day, parts.time.hour, parts.time.min, parts.time.sec, Math.floor(parts.time.micros / 1000)));
180
+ }
181
+ else if (typeId === node_api_1.DuckDBTypeId.DATE) {
182
+ var dateValue = value;
183
+ var parts = dateValue.toParts();
184
+ convertedRow[colName] = new Date(Date.UTC(parts.year, parts.month - 1, parts.day));
185
+ }
186
+ else {
187
+ convertedRow[colName] = value;
188
+ }
189
+ }
190
+ });
191
+ return convertedRow;
192
+ });
193
+ (_a = this.rows).push.apply(_a, tslib_1.__spreadArray([], tslib_1.__read(chunkRowObjects), false));
194
+ }
145
195
  }
146
196
  DuckDBSqlResult.prototype.getColumnKeyInResultForIndexInSelect = function (index) {
147
- return Object.keys(this.result[0])[index];
197
+ return this.duckDbResult.columnName(index);
148
198
  };
149
199
  return DuckDBSqlResult;
150
200
  }());