remult 0.27.11 → 0.27.13

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 (45) hide show
  1. package/esm/index.js +0 -1
  2. package/esm/live-query/data-provider-live-query-storage.js +0 -2
  3. package/esm/postgres/schema-builder.js +0 -41
  4. package/esm/remult-duckdb.js +7 -12
  5. package/esm/remult-knex/index.js +0 -7
  6. package/esm/remult-mongo.js +33 -0
  7. package/esm/remult-sqlite-core.js +33 -5
  8. package/esm/server/get-remult-admin-html.js +1 -1
  9. package/esm/server/remult-admin.js +2 -0
  10. package/esm/server/remult-api-server.js +4 -5
  11. package/esm/src/data-providers/array-entity-data-provider.js +26 -11
  12. package/esm/src/data-providers/in-memory-database.js +1 -1
  13. package/esm/src/data-providers/sql-database.js +2 -25
  14. package/esm/src/filter/filter-interfaces.js +1 -0
  15. package/esm/src/remult3/RepositoryImplementation.js +15 -4
  16. package/esm/src/remult3/remult3.js +0 -3
  17. package/index.d.ts +0 -1
  18. package/index.js +1 -3
  19. package/live-query/data-provider-live-query-storage.js +0 -2
  20. package/package.json +1 -1
  21. package/postgres/schema-builder.d.ts +0 -4
  22. package/postgres/schema-builder.js +15 -118
  23. package/remult-duckdb.d.ts +1 -1
  24. package/remult-duckdb.js +7 -12
  25. package/remult-knex/index.d.ts +0 -2
  26. package/remult-knex/index.js +0 -18
  27. package/remult-mongo.d.ts +2 -1
  28. package/remult-mongo.js +128 -37
  29. package/remult-sqlite-core.d.ts +2 -1
  30. package/remult-sqlite-core.js +116 -29
  31. package/server/get-remult-admin-html.js +1 -1
  32. package/server/remult-admin.d.ts +4 -0
  33. package/server/remult-admin.js +12 -10
  34. package/server/remult-api-server.js +14 -14
  35. package/src/data-providers/array-entity-data-provider.js +82 -37
  36. package/src/data-providers/in-memory-database.js +1 -1
  37. package/src/data-providers/sql-database.js +10 -69
  38. package/src/entity.d.ts +4 -4
  39. package/src/filter/filter-interfaces.js +1 -0
  40. package/src/remult3/RepositoryImplementation.js +15 -4
  41. package/src/remult3/remult3.d.ts +17 -2
  42. package/src/remult3/remult3.js +0 -3
  43. package/esm/src/data-providers/web-sql-data-provider.js +0 -140
  44. package/src/data-providers/web-sql-data-provider.d.ts +0 -20
  45. package/src/data-providers/web-sql-data-provider.js +0 -228
@@ -446,7 +446,6 @@ export interface Repository<entityType> {
446
446
  /**
447
447
  * Performs an aggregation on the repository's entity type based on the specified options.
448
448
  * @template entityType The type of the entity being aggregated.
449
- * @template groupByFields The fields to group by, provided as an array of keys from the entity type.
450
449
  * @template sumFields The fields to sum, provided as an array of numeric keys from the entity type.
451
450
  * @template averageFields The fields to average, provided as an array of numeric keys from the entity type.
452
451
  *
@@ -461,7 +460,7 @@ export interface Repository<entityType> {
461
460
  * console.log(totalSalary.salary.sum); // Outputs the total sum of salaries
462
461
 
463
462
  */
464
- aggregate<sumFields extends NumericKeys<entityType>[] | undefined = undefined, averageFields extends NumericKeys<entityType>[] | undefined = undefined, minFields extends (keyof MembersOnly<entityType>)[] | undefined = undefined, maxFields extends (keyof MembersOnly<entityType>)[] | undefined = undefined, distinctCountFields extends (keyof MembersOnly<entityType>)[] | undefined = undefined>(options: Omit<GroupByOptions<entityType, never, sumFields extends undefined ? never : sumFields, averageFields extends undefined ? never : averageFields, minFields extends undefined ? never : minFields, maxFields extends undefined ? never : maxFields, distinctCountFields extends undefined ? never : distinctCountFields>, 'orderBy' | 'limit' | 'page'>): Promise<GroupByResult<entityType, never, sumFields extends undefined ? never : sumFields, averageFields extends undefined ? never : averageFields, minFields extends undefined ? never : minFields, maxFields extends undefined ? never : maxFields, distinctCountFields extends undefined ? never : distinctCountFields>>;
463
+ aggregate<sumFields extends NumericKeys<entityType>[] | undefined = undefined, averageFields extends NumericKeys<entityType>[] | undefined = undefined, minFields extends (keyof MembersOnly<entityType>)[] | undefined = undefined, maxFields extends (keyof MembersOnly<entityType>)[] | undefined = undefined, distinctCountFields extends (keyof MembersOnly<entityType>)[] | undefined = undefined>(options: Omit<GroupByOptions<entityType, never, sumFields extends undefined ? never : sumFields, averageFields extends undefined ? never : averageFields, minFields extends undefined ? never : minFields, maxFields extends undefined ? never : maxFields, distinctCountFields extends undefined ? never : distinctCountFields>, 'orderBy' | 'limit' | 'page' | 'group'>): Promise<GroupByResult<entityType, never, sumFields extends undefined ? never : sumFields, averageFields extends undefined ? never : averageFields, minFields extends undefined ? never : minFields, maxFields extends undefined ? never : maxFields, distinctCountFields extends undefined ? never : distinctCountFields>>;
465
464
  /** An alternative form of fetching data from the API server, which is intended for operating on large numbers of entity objects.
466
465
  *
467
466
  * It also has it's own paging mechanism that can be used n paging scenarios.
@@ -725,6 +724,22 @@ export type ValueFilter<valueType> = valueType | valueType[] | {
725
724
  * status: { $ne: [1, 2, 3] }
726
725
  * };
727
726
  */
727
+ $not?: valueType | valueType[];
728
+ /**
729
+ * Represents a 'NOT EQUAL' filter condition where the value must not match the specified value or values.
730
+ *
731
+ * @example
732
+ * // Matches entities where the status is not 1
733
+ * const filter = {
734
+ * status: { $not: 1 }
735
+ * };
736
+ *
737
+ * @example
738
+ * // Matches entities where the status is not 1, 2, or 3
739
+ * const filter = {
740
+ * status: { $not: [1, 2, 3] }
741
+ * };
742
+ */
728
743
  $ne?: valueType | valueType[];
729
744
  /**
730
745
  * Represents a 'NOT EQUAL' filter condition using the '!=' operator where the value must not match the specified value or values.
@@ -22,7 +22,6 @@ exports.flags = {
22
22
  };
23
23
  //p1 - add parameter all to deleteMany, and updateMany
24
24
  //p1 filter.apply ApiPreFilter
25
- //p1 - add not as an overload to not equal
26
25
  /*p1 - add id and use uuid by default, but allow changes with Fields.id.defaultIdProvider NO but defaultProvider yes???
27
26
  //p1 - replace uuid with crypto.randomUUID and allow custom fallback NO
28
27
  //p1 - Add example for luid
@@ -30,7 +29,6 @@ exports.flags = {
30
29
  //p1 - explain the benefits of changing the default provider for testing in docs.
31
30
  */
32
31
  //p1 - consider upsert (where,set)
33
- //p1 TODO - consider id to also support keyof (id:['company','index']) - had problem with | (keyof Partial<entityType>)[] & `entity`
34
32
  //p2 - add some kind of options handler that will help with translation etc... like in hagai - something that runs at the stage where options are being built
35
33
  /*y1 - https://github.com/remult/remult/discussions/438
36
34
  - https://github.com/remult/remult/blob/query-argumets/projects/tests/dbs/test-sql-database.spec.ts#L100-L128
@@ -44,7 +42,6 @@ exports.flags = {
44
42
  //p1 - tutorial about controller - and mutable controller
45
43
  //p1 - docs abount subscription channel
46
44
  //p1 - Consider enforcing serial operations on JSON database to prevent data loss
47
- //p1 - fix sqlite to support alter table when adding a column with ensure schema = on
48
45
  //p1 - add LifecycleEvent to documentation
49
46
  //p1 - fix chaining of saving and saved in multiple entity options args
50
47
  //p1 - review starter and examples and separate remult * auth from the routes
@@ -1,140 +0,0 @@
1
- import { dbNamesOf, isDbReadonly, } from '../filter/filter-consumer-bridge-to-sql-request.js';
2
- import { isAutoIncrement } from '../remult3/RepositoryImplementation.js';
3
- import { SqlDatabase } from './sql-database.js';
4
- //SqlDatabase.LogToConsole = true;
5
- export class WebSqlDataProvider {
6
- databaseName;
7
- rows;
8
- /** @internal */
9
- //@ts-ignore
10
- db;
11
- constructor(databaseName, databaseSize = 2 * 1024 * 1024) {
12
- this.databaseName = databaseName;
13
- //@ts-ignore
14
- this.db = window.openDatabase(databaseName, '1.0', databaseName, databaseSize);
15
- }
16
- async end() { }
17
- getLimitSqlSyntax(limit, offset) {
18
- return ' limit ' + limit + ' offset ' + offset;
19
- }
20
- async entityIsUsedForTheFirstTime(entity) {
21
- await this.createTable(entity);
22
- }
23
- async ensureSchema(entities) {
24
- for (const entity of entities) {
25
- await this.createTable(entity);
26
- }
27
- }
28
- async dropTable(entity) {
29
- let e = await dbNamesOf(entity);
30
- let sql = 'drop table if exists ' + e.$entityName;
31
- if (SqlDatabase.LogToConsole)
32
- console.info(sql);
33
- await this.createCommand().execute(sql);
34
- }
35
- async createTable(entity) {
36
- let result = '';
37
- let e = await dbNamesOf(entity);
38
- for (const x of entity.fields) {
39
- if (!isDbReadonly(x, e) || isAutoIncrement(x)) {
40
- if (result.length != 0)
41
- result += ',';
42
- result += '\r\n ';
43
- if (isAutoIncrement(x)) {
44
- if (x.key != entity.idMetadata.field.key)
45
- throw 'in web sql, autoincrement is only allowed for primary key';
46
- result += e.$dbNameOf(x) + ' integer primary key autoincrement';
47
- }
48
- else {
49
- result += this.addColumnSqlSyntax(x, e.$dbNameOf(x));
50
- if (x.key == entity.idMetadata.field.key) {
51
- result += ' primary key';
52
- }
53
- }
54
- }
55
- }
56
- let sql = 'create table if not exists ' + e.$entityName + ' (' + result + '\r\n)';
57
- if (SqlDatabase.LogToConsole)
58
- console.log(sql);
59
- await this.createCommand().execute(sql);
60
- }
61
- createCommand() {
62
- return new WebSqlBridgeToSQLCommand(this.db);
63
- }
64
- async transaction(action) {
65
- throw new Error('Method not implemented.');
66
- }
67
- addColumnSqlSyntax(x, dbName) {
68
- let result = dbName;
69
- const nullNumber = x.allowNull ? '' : ' default 0 not null';
70
- if (x.valueType == Date)
71
- result += ' integer';
72
- else if (x.valueType == Boolean)
73
- result += ' integer ' + nullNumber;
74
- else if (x.valueType == Number) {
75
- if (!x.valueConverter.fieldTypeInDb)
76
- result += ' real ' + nullNumber;
77
- else
78
- result += ' ' + x.valueConverter.fieldTypeInDb + ' ' + nullNumber;
79
- }
80
- else
81
- result += ' text' + (x.allowNull ? ' ' : " default '' not null ");
82
- return result;
83
- }
84
- toString() {
85
- return 'WebSqlDataProvider';
86
- }
87
- }
88
- class WebSqlBridgeToSQLCommand {
89
- source;
90
- //@ts-ignore
91
- constructor(source) {
92
- this.source = source;
93
- }
94
- values = [];
95
- addParameterAndReturnSqlToken(val) {
96
- return this.param(val);
97
- }
98
- param(val) {
99
- this.values.push(val);
100
- return '~' + this.values.length + '~';
101
- }
102
- execute(sql) {
103
- return new Promise((resolve, reject) => this.source.transaction((t) => {
104
- let s = sql;
105
- let v = [];
106
- var m = s.match(/~\d+~/g);
107
- if (m != null)
108
- m.forEach((mr) => {
109
- s = s.replace(mr, '?');
110
- v.push(this.values[Number.parseInt(mr.substring(1, mr.length - 1)) - 1]);
111
- });
112
- t.executeSql(s, v, (t1, r) => resolve(new WebSqlBridgeToSQLQueryResult(r)), (t2, err) => {
113
- reject(err.message);
114
- return false;
115
- });
116
- }));
117
- }
118
- }
119
- class WebSqlBridgeToSQLQueryResult {
120
- r;
121
- getColumnKeyInResultForIndexInSelect(index) {
122
- if (this.rows.length == 0)
123
- throw Error('No rows');
124
- let i = 0;
125
- for (let m in this.rows[0]) {
126
- if (i++ == index)
127
- return m;
128
- }
129
- throw Error('index not found');
130
- }
131
- //@ts-ignore
132
- constructor(r) {
133
- this.r = r;
134
- this.rows = [];
135
- for (let i = 0; i < r.rows.length; i++) {
136
- this.rows.push(r.rows.item(i));
137
- }
138
- }
139
- rows;
140
- }
@@ -1,20 +0,0 @@
1
- import type { __RowsOfDataForTesting } from '../__RowsOfDataForTesting.js';
2
- import type { SqlCommand, SqlImplementation } from '../sql-command.js';
3
- import type { EntityMetadata } from '../remult3/remult3.js';
4
- export declare class WebSqlDataProvider implements SqlImplementation, __RowsOfDataForTesting {
5
- private databaseName;
6
- rows: {
7
- [tableName: string]: any;
8
- };
9
- constructor(databaseName: string, databaseSize?: number);
10
- end(): Promise<void>;
11
- getLimitSqlSyntax(limit: number, offset: number): string;
12
- entityIsUsedForTheFirstTime(entity: EntityMetadata): Promise<void>;
13
- ensureSchema(entities: EntityMetadata[]): Promise<void>;
14
- dropTable(entity: EntityMetadata): Promise<void>;
15
- createTable(entity: EntityMetadata): Promise<void>;
16
- createCommand(): SqlCommand;
17
- transaction(action: (dataProvider: SqlImplementation) => Promise<void>): Promise<void>;
18
- private addColumnSqlSyntax;
19
- toString(): string;
20
- }
@@ -1,228 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WebSqlDataProvider = void 0;
4
- var tslib_1 = require("tslib");
5
- var filter_consumer_bridge_to_sql_request_js_1 = require("../filter/filter-consumer-bridge-to-sql-request.js");
6
- var RepositoryImplementation_js_1 = require("../remult3/RepositoryImplementation.js");
7
- var sql_database_js_1 = require("./sql-database.js");
8
- //SqlDatabase.LogToConsole = true;
9
- var WebSqlDataProvider = /** @class */ (function () {
10
- function WebSqlDataProvider(databaseName, databaseSize) {
11
- if (databaseSize === void 0) { databaseSize = 2 * 1024 * 1024; }
12
- this.databaseName = databaseName;
13
- //@ts-ignore
14
- this.db = window.openDatabase(databaseName, '1.0', databaseName, databaseSize);
15
- }
16
- WebSqlDataProvider.prototype.end = function () {
17
- return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) {
18
- return [2 /*return*/];
19
- }); });
20
- };
21
- WebSqlDataProvider.prototype.getLimitSqlSyntax = function (limit, offset) {
22
- return ' limit ' + limit + ' offset ' + offset;
23
- };
24
- WebSqlDataProvider.prototype.entityIsUsedForTheFirstTime = function (entity) {
25
- return tslib_1.__awaiter(this, void 0, void 0, function () {
26
- return tslib_1.__generator(this, function (_a) {
27
- switch (_a.label) {
28
- case 0: return [4 /*yield*/, this.createTable(entity)];
29
- case 1:
30
- _a.sent();
31
- return [2 /*return*/];
32
- }
33
- });
34
- });
35
- };
36
- WebSqlDataProvider.prototype.ensureSchema = function (entities) {
37
- return tslib_1.__awaiter(this, void 0, void 0, function () {
38
- var entities_1, entities_1_1, entity, e_1_1;
39
- var e_1, _a;
40
- return tslib_1.__generator(this, function (_b) {
41
- switch (_b.label) {
42
- case 0:
43
- _b.trys.push([0, 5, 6, 7]);
44
- entities_1 = tslib_1.__values(entities), entities_1_1 = entities_1.next();
45
- _b.label = 1;
46
- case 1:
47
- if (!!entities_1_1.done) return [3 /*break*/, 4];
48
- entity = entities_1_1.value;
49
- return [4 /*yield*/, this.createTable(entity)];
50
- case 2:
51
- _b.sent();
52
- _b.label = 3;
53
- case 3:
54
- entities_1_1 = entities_1.next();
55
- return [3 /*break*/, 1];
56
- case 4: return [3 /*break*/, 7];
57
- case 5:
58
- e_1_1 = _b.sent();
59
- e_1 = { error: e_1_1 };
60
- return [3 /*break*/, 7];
61
- case 6:
62
- try {
63
- if (entities_1_1 && !entities_1_1.done && (_a = entities_1.return)) _a.call(entities_1);
64
- }
65
- finally { if (e_1) throw e_1.error; }
66
- return [7 /*endfinally*/];
67
- case 7: return [2 /*return*/];
68
- }
69
- });
70
- });
71
- };
72
- WebSqlDataProvider.prototype.dropTable = function (entity) {
73
- return tslib_1.__awaiter(this, void 0, void 0, function () {
74
- var e, sql;
75
- return tslib_1.__generator(this, function (_a) {
76
- switch (_a.label) {
77
- case 0: return [4 /*yield*/, (0, filter_consumer_bridge_to_sql_request_js_1.dbNamesOf)(entity)];
78
- case 1:
79
- e = _a.sent();
80
- sql = 'drop table if exists ' + e.$entityName;
81
- if (sql_database_js_1.SqlDatabase.LogToConsole)
82
- console.info(sql);
83
- return [4 /*yield*/, this.createCommand().execute(sql)];
84
- case 2:
85
- _a.sent();
86
- return [2 /*return*/];
87
- }
88
- });
89
- });
90
- };
91
- WebSqlDataProvider.prototype.createTable = function (entity) {
92
- return tslib_1.__awaiter(this, void 0, void 0, function () {
93
- var result, e, _a, _b, x, sql;
94
- var e_2, _c;
95
- return tslib_1.__generator(this, function (_d) {
96
- switch (_d.label) {
97
- case 0:
98
- result = '';
99
- return [4 /*yield*/, (0, filter_consumer_bridge_to_sql_request_js_1.dbNamesOf)(entity)];
100
- case 1:
101
- e = _d.sent();
102
- try {
103
- for (_a = tslib_1.__values(entity.fields), _b = _a.next(); !_b.done; _b = _a.next()) {
104
- x = _b.value;
105
- if (!(0, filter_consumer_bridge_to_sql_request_js_1.isDbReadonly)(x, e) || (0, RepositoryImplementation_js_1.isAutoIncrement)(x)) {
106
- if (result.length != 0)
107
- result += ',';
108
- result += '\r\n ';
109
- if ((0, RepositoryImplementation_js_1.isAutoIncrement)(x)) {
110
- if (x.key != entity.idMetadata.field.key)
111
- throw 'in web sql, autoincrement is only allowed for primary key';
112
- result += e.$dbNameOf(x) + ' integer primary key autoincrement';
113
- }
114
- else {
115
- result += this.addColumnSqlSyntax(x, e.$dbNameOf(x));
116
- if (x.key == entity.idMetadata.field.key) {
117
- result += ' primary key';
118
- }
119
- }
120
- }
121
- }
122
- }
123
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
124
- finally {
125
- try {
126
- if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
127
- }
128
- finally { if (e_2) throw e_2.error; }
129
- }
130
- sql = 'create table if not exists ' + e.$entityName + ' (' + result + '\r\n)';
131
- if (sql_database_js_1.SqlDatabase.LogToConsole)
132
- console.log(sql);
133
- return [4 /*yield*/, this.createCommand().execute(sql)];
134
- case 2:
135
- _d.sent();
136
- return [2 /*return*/];
137
- }
138
- });
139
- });
140
- };
141
- WebSqlDataProvider.prototype.createCommand = function () {
142
- return new WebSqlBridgeToSQLCommand(this.db);
143
- };
144
- WebSqlDataProvider.prototype.transaction = function (action) {
145
- return tslib_1.__awaiter(this, void 0, void 0, function () {
146
- return tslib_1.__generator(this, function (_a) {
147
- throw new Error('Method not implemented.');
148
- });
149
- });
150
- };
151
- WebSqlDataProvider.prototype.addColumnSqlSyntax = function (x, dbName) {
152
- var result = dbName;
153
- var nullNumber = x.allowNull ? '' : ' default 0 not null';
154
- if (x.valueType == Date)
155
- result += ' integer';
156
- else if (x.valueType == Boolean)
157
- result += ' integer ' + nullNumber;
158
- else if (x.valueType == Number) {
159
- if (!x.valueConverter.fieldTypeInDb)
160
- result += ' real ' + nullNumber;
161
- else
162
- result += ' ' + x.valueConverter.fieldTypeInDb + ' ' + nullNumber;
163
- }
164
- else
165
- result += ' text' + (x.allowNull ? ' ' : " default '' not null ");
166
- return result;
167
- };
168
- WebSqlDataProvider.prototype.toString = function () {
169
- return 'WebSqlDataProvider';
170
- };
171
- return WebSqlDataProvider;
172
- }());
173
- exports.WebSqlDataProvider = WebSqlDataProvider;
174
- var WebSqlBridgeToSQLCommand = /** @class */ (function () {
175
- //@ts-ignore
176
- function WebSqlBridgeToSQLCommand(source) {
177
- this.source = source;
178
- this.values = [];
179
- }
180
- WebSqlBridgeToSQLCommand.prototype.addParameterAndReturnSqlToken = function (val) {
181
- return this.param(val);
182
- };
183
- WebSqlBridgeToSQLCommand.prototype.param = function (val) {
184
- this.values.push(val);
185
- return '~' + this.values.length + '~';
186
- };
187
- WebSqlBridgeToSQLCommand.prototype.execute = function (sql) {
188
- var _this = this;
189
- return new Promise(function (resolve, reject) {
190
- return _this.source.transaction(function (t) {
191
- var s = sql;
192
- var v = [];
193
- var m = s.match(/~\d+~/g);
194
- if (m != null)
195
- m.forEach(function (mr) {
196
- s = s.replace(mr, '?');
197
- v.push(_this.values[Number.parseInt(mr.substring(1, mr.length - 1)) - 1]);
198
- });
199
- t.executeSql(s, v, function (t1, r) { return resolve(new WebSqlBridgeToSQLQueryResult(r)); }, function (t2, err) {
200
- reject(err.message);
201
- return false;
202
- });
203
- });
204
- });
205
- };
206
- return WebSqlBridgeToSQLCommand;
207
- }());
208
- var WebSqlBridgeToSQLQueryResult = /** @class */ (function () {
209
- //@ts-ignore
210
- function WebSqlBridgeToSQLQueryResult(r) {
211
- this.r = r;
212
- this.rows = [];
213
- for (var i = 0; i < r.rows.length; i++) {
214
- this.rows.push(r.rows.item(i));
215
- }
216
- }
217
- WebSqlBridgeToSQLQueryResult.prototype.getColumnKeyInResultForIndexInSelect = function (index) {
218
- if (this.rows.length == 0)
219
- throw Error('No rows');
220
- var i = 0;
221
- for (var m in this.rows[0]) {
222
- if (i++ == index)
223
- return m;
224
- }
225
- throw Error('index not found');
226
- };
227
- return WebSqlBridgeToSQLQueryResult;
228
- }());