remult 0.14.7 → 0.14.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/LICENSE +21 -0
  2. package/esm/assign.d.ts +1 -0
  3. package/esm/assign.js +5 -0
  4. package/esm/classType.d.ts +3 -0
  5. package/esm/classType.js +1 -0
  6. package/esm/graphql.d.ts +5 -0
  7. package/esm/graphql.js +102 -0
  8. package/esm/index.d.ts +36 -0
  9. package/esm/index.js +30 -0
  10. package/esm/inputTypes.d.ts +9 -0
  11. package/esm/inputTypes.js +9 -0
  12. package/esm/postgres/index.d.ts +2 -0
  13. package/esm/postgres/index.js +2 -0
  14. package/esm/postgres/postgres-data-provider.d.ts +28 -0
  15. package/esm/postgres/postgres-data-provider.js +97 -0
  16. package/esm/postgres/schema-builder.d.ts +15 -0
  17. package/esm/postgres/schema-builder.js +128 -0
  18. package/esm/remult-express.d.ts +5 -0
  19. package/esm/remult-express.js +16 -0
  20. package/esm/remult-knex/index.d.ts +51 -0
  21. package/esm/remult-knex/index.js +381 -0
  22. package/esm/remult-middleware.d.ts +2 -0
  23. package/esm/remult-middleware.js +63 -0
  24. package/esm/remult-mongo.d.ts +9 -0
  25. package/esm/remult-mongo.js +220 -0
  26. package/esm/server/JsonEntityFileStorage.d.ts +7 -0
  27. package/esm/server/JsonEntityFileStorage.js +20 -0
  28. package/esm/server/expressBridge.d.ts +140 -0
  29. package/esm/server/expressBridge.js +668 -0
  30. package/esm/server/index.d.ts +4 -0
  31. package/esm/server/index.js +4 -0
  32. package/esm/server/register-actions-on-server.d.ts +3 -0
  33. package/esm/server/register-actions-on-server.js +24 -0
  34. package/esm/server/register-entities-on-server.d.ts +3 -0
  35. package/esm/server/register-entities-on-server.js +15 -0
  36. package/esm/src/__EntityValueProvider.d.ts +10 -0
  37. package/esm/src/__EntityValueProvider.js +1 -0
  38. package/esm/src/__RowsOfDataForTesting.d.ts +3 -0
  39. package/esm/src/__RowsOfDataForTesting.js +1 -0
  40. package/esm/src/backend-tests/backend-database-test-setup.backend-spec.d.ts +5 -0
  41. package/esm/src/backend-tests/backend-database-test-setup.backend-spec.js +113 -0
  42. package/esm/src/backend-tests/my-test.backend-spec.d.ts +1 -0
  43. package/esm/src/backend-tests/my-test.backend-spec.js +49 -0
  44. package/esm/src/column-interfaces.d.ts +95 -0
  45. package/esm/src/column-interfaces.js +7 -0
  46. package/esm/src/column.d.ts +49 -0
  47. package/esm/src/column.js +133 -0
  48. package/esm/src/context.d.ts +124 -0
  49. package/esm/src/context.js +285 -0
  50. package/esm/src/data-api.d.ts +33 -0
  51. package/esm/src/data-api.js +204 -0
  52. package/esm/src/data-interfaces.d.ts +37 -0
  53. package/esm/src/data-interfaces.js +12 -0
  54. package/esm/src/data-providers/array-entity-data-provider.d.ts +22 -0
  55. package/esm/src/data-providers/array-entity-data-provider.js +264 -0
  56. package/esm/src/data-providers/in-memory-database.d.ts +9 -0
  57. package/esm/src/data-providers/in-memory-database.js +16 -0
  58. package/esm/src/data-providers/json-data-provider.d.ts +12 -0
  59. package/esm/src/data-providers/json-data-provider.js +52 -0
  60. package/esm/src/data-providers/rest-data-provider.d.ts +35 -0
  61. package/esm/src/data-providers/rest-data-provider.js +188 -0
  62. package/esm/src/data-providers/sql-database.d.ts +16 -0
  63. package/esm/src/data-providers/sql-database.js +261 -0
  64. package/esm/src/data-providers/web-sql-data-provider.d.ts +18 -0
  65. package/esm/src/data-providers/web-sql-data-provider.js +121 -0
  66. package/esm/src/entity.d.ts +82 -0
  67. package/esm/src/entity.js +1 -0
  68. package/esm/src/filter/filter-consumer-bridge-to-sql-request.d.ts +50 -0
  69. package/esm/src/filter/filter-consumer-bridge-to-sql-request.js +139 -0
  70. package/esm/src/filter/filter-consumer-bridge-to-url-builder.d.ts +1 -0
  71. package/esm/src/filter/filter-consumer-bridge-to-url-builder.js +1 -0
  72. package/esm/src/filter/filter-interfaces.d.ts +85 -0
  73. package/esm/src/filter/filter-interfaces.js +467 -0
  74. package/esm/src/id-entity.d.ts +4 -0
  75. package/esm/src/id-entity.js +8 -0
  76. package/esm/src/remult3/RepositoryImplementation.d.ts +326 -0
  77. package/esm/src/remult3/RepositoryImplementation.js +1806 -0
  78. package/esm/src/remult3/index.d.ts +2 -0
  79. package/esm/src/remult3/index.js +2 -0
  80. package/esm/src/remult3/remult3.d.ts +312 -0
  81. package/esm/src/remult3/remult3.js +1 -0
  82. package/esm/src/server-action.d.ts +70 -0
  83. package/esm/src/server-action.js +365 -0
  84. package/esm/src/shared-tests/db-tests-setup.d.ts +23 -0
  85. package/esm/src/shared-tests/db-tests-setup.js +66 -0
  86. package/esm/src/shared-tests/db-tests.db-tests.d.ts +26 -0
  87. package/esm/src/shared-tests/db-tests.db-tests.js +723 -0
  88. package/esm/src/shared-tests/deleteAll.d.ts +2 -0
  89. package/esm/src/shared-tests/deleteAll.js +4 -0
  90. package/esm/src/shared-tests/entityWithValidations.d.ts +14 -0
  91. package/esm/src/shared-tests/entityWithValidations.js +53 -0
  92. package/esm/src/shared-tests/index.d.ts +4 -0
  93. package/esm/src/shared-tests/index.js +4 -0
  94. package/esm/src/shared-tests/test-custom-id-column.spec.d.ts +1 -0
  95. package/esm/src/shared-tests/test-custom-id-column.spec.js +62 -0
  96. package/esm/src/shared-tests/test-special-value.spec.d.ts +10 -0
  97. package/esm/src/shared-tests/test-special-value.spec.js +88 -0
  98. package/esm/src/shared-tests/test-update-with-null.spec.d.ts +1 -0
  99. package/esm/src/shared-tests/test-update-with-null.spec.js +47 -0
  100. package/esm/src/sort.d.ts +15 -0
  101. package/esm/src/sort.js +82 -0
  102. package/esm/src/sql-command.d.ts +15 -0
  103. package/esm/src/sql-command.js +1 -0
  104. package/esm/src/tests/Done.d.ts +5 -0
  105. package/esm/src/tests/Done.js +11 -0
  106. package/esm/src/tests/TestDataApiResponse.d.ts +10 -0
  107. package/esm/src/tests/TestDataApiResponse.js +22 -0
  108. package/esm/src/tests/c.d.ts +8 -0
  109. package/esm/src/tests/c.js +22 -0
  110. package/esm/src/tests/createData.d.ts +7 -0
  111. package/esm/src/tests/createData.js +22 -0
  112. package/esm/src/tests/d.d.ts +6 -0
  113. package/esm/src/tests/d.js +19 -0
  114. package/esm/src/tests/dWithPrefilter.d.ts +7 -0
  115. package/esm/src/tests/dWithPrefilter.js +32 -0
  116. package/esm/src/tests/entityForCustomFilter.d.ts +16 -0
  117. package/esm/src/tests/entityForCustomFilter.js +44 -0
  118. package/esm/src/tests/entityWithValidationsOnColumn.d.ts +5 -0
  119. package/esm/src/tests/entityWithValidationsOnColumn.js +21 -0
  120. package/esm/src/tests/frontend-database-tests-setup.spec.d.ts +4 -0
  121. package/esm/src/tests/frontend-database-tests-setup.spec.js +38 -0
  122. package/esm/src/tests/h.d.ts +6 -0
  123. package/esm/src/tests/h.js +35 -0
  124. package/esm/src/tests/remult-3-entities.d.ts +23 -0
  125. package/esm/src/tests/remult-3-entities.js +72 -0
  126. package/esm/src/tests/tasks.d.ts +6 -0
  127. package/esm/src/tests/tasks.js +24 -0
  128. package/esm/src/tests/testHelper.spec.d.ts +34 -0
  129. package/esm/src/tests/testHelper.spec.js +217 -0
  130. package/esm/src/tests/testModel/models.d.ts +16 -0
  131. package/esm/src/tests/testModel/models.js +31 -0
  132. package/esm/src/validators.d.ts +14 -0
  133. package/esm/src/validators.js +33 -0
  134. package/esm/urlBuilder.d.ts +6 -0
  135. package/esm/urlBuilder.js +19 -0
  136. package/esm/valueConverters.d.ts +12 -0
  137. package/esm/valueConverters.js +169 -0
  138. package/index.d.ts +1 -0
  139. package/index.js +1 -0
  140. package/package.json +22 -1
  141. package/postgres/index.d.ts +1 -0
  142. package/postgres/index.js +1 -0
  143. package/postgres/postgres-data-provider.d.ts +1 -13
  144. package/postgres/postgres-data-provider.js +28 -262
  145. package/postgres/schema-builder.d.ts +15 -0
  146. package/postgres/schema-builder.js +270 -0
  147. package/readme.md +68 -30
  148. package/src/data-providers/web-sql-data-provider.js +4 -3
  149. package/src/entity.d.ts +9 -2
  150. package/src/remult3/RepositoryImplementation.js +11 -3
  151. package/src/shared-tests/test-update-with-null.spec.js +38 -0
  152. package/valueConverters.js +4 -0
@@ -0,0 +1,261 @@
1
+ import { CompoundIdField } from "../column";
2
+ import { FilterConsumerBridgeToSqlRequest, getDbNameProvider } from "../filter/filter-consumer-bridge-to-sql-request";
3
+ import { customDatabaseFilterToken, Filter } from '../filter/filter-interfaces';
4
+ import { Sort } from '../sort';
5
+ // @dynamic
6
+ export class SqlDatabase {
7
+ constructor(sql) {
8
+ this.sql = sql;
9
+ this.createdEntities = [];
10
+ }
11
+ createCommand() {
12
+ return new LogSQLCommand(this.sql.createCommand(), SqlDatabase.LogToConsole);
13
+ }
14
+ async execute(sql) {
15
+ return await this.createCommand().execute(sql);
16
+ }
17
+ getEntityDataProvider(entity) {
18
+ return new ActualSQLServerDataProvider(entity, this, async (dbName) => {
19
+ if (this.createdEntities.indexOf(dbName.entityName) < 0) {
20
+ this.createdEntities.push(dbName.entityName);
21
+ await this.sql.entityIsUsedForTheFirstTime(entity);
22
+ }
23
+ }, this.sql);
24
+ }
25
+ transaction(action) {
26
+ return this.sql.transaction(async (x) => {
27
+ let completed = false;
28
+ try {
29
+ await action(new SqlDatabase({
30
+ createCommand: () => {
31
+ let c = x.createCommand();
32
+ return {
33
+ addParameterAndReturnSqlToken: x => c.addParameterAndReturnSqlToken(x),
34
+ execute: async (sql) => {
35
+ if (completed)
36
+ throw "can't run a command after the transaction was completed";
37
+ return c.execute(sql);
38
+ }
39
+ };
40
+ },
41
+ getLimitSqlSyntax: this.sql.getLimitSqlSyntax,
42
+ entityIsUsedForTheFirstTime: y => x.entityIsUsedForTheFirstTime(y),
43
+ transaction: z => x.transaction(z),
44
+ }));
45
+ }
46
+ finally {
47
+ completed = true;
48
+ }
49
+ });
50
+ }
51
+ static customFilter(build) {
52
+ return {
53
+ [customDatabaseFilterToken]: {
54
+ buildSql: build
55
+ }
56
+ };
57
+ }
58
+ }
59
+ SqlDatabase.LogToConsole = false;
60
+ SqlDatabase.durationThreshold = 0;
61
+ class LogSQLCommand {
62
+ constructor(origin, allQueries) {
63
+ this.origin = origin;
64
+ this.allQueries = allQueries;
65
+ this.args = {};
66
+ }
67
+ addParameterAndReturnSqlToken(val) {
68
+ let r = this.origin.addParameterAndReturnSqlToken(val);
69
+ this.args[r] = val;
70
+ return r;
71
+ }
72
+ async execute(sql) {
73
+ try {
74
+ let start = new Date();
75
+ let r = await this.origin.execute(sql);
76
+ if (this.allQueries) {
77
+ var d = new Date().valueOf() - start.valueOf();
78
+ if (d > SqlDatabase.durationThreshold) {
79
+ console.log({ query: sql, arguments: this.args, duration: d / 1000 });
80
+ }
81
+ }
82
+ return r;
83
+ }
84
+ catch (err) {
85
+ console.error({ error: err, query: sql, arguments: this.args });
86
+ throw err;
87
+ }
88
+ }
89
+ }
90
+ class ActualSQLServerDataProvider {
91
+ constructor(entity, sql, iAmUsed, strategy) {
92
+ this.entity = entity;
93
+ this.sql = sql;
94
+ this.iAmUsed = iAmUsed;
95
+ this.strategy = strategy;
96
+ }
97
+ async init() {
98
+ let dbNameProvider = await getDbNameProvider(this.entity);
99
+ await this.iAmUsed(dbNameProvider);
100
+ return dbNameProvider;
101
+ }
102
+ async count(where) {
103
+ let e = await this.init();
104
+ let select = 'select count(*) count from ' + e.entityName;
105
+ let r = this.sql.createCommand();
106
+ if (where) {
107
+ let wc = new FilterConsumerBridgeToSqlRequest(r, e);
108
+ where.__applyToConsumer(wc);
109
+ select += await wc.resolveWhere();
110
+ }
111
+ return r.execute(select).then(r => {
112
+ return +r.rows[0].count;
113
+ });
114
+ }
115
+ async find(options) {
116
+ let e = await this.init();
117
+ let { colKeys, select } = this.buildSelect(e);
118
+ select = 'select ' + select;
119
+ select += '\n from ' + e.entityName;
120
+ let r = this.sql.createCommand();
121
+ if (options) {
122
+ if (options.where) {
123
+ let where = new FilterConsumerBridgeToSqlRequest(r, e);
124
+ options.where.__applyToConsumer(where);
125
+ select += await where.resolveWhere();
126
+ }
127
+ if (options.limit) {
128
+ options.orderBy = Sort.createUniqueSort(this.entity, options.orderBy);
129
+ }
130
+ if (options.orderBy) {
131
+ let first = true;
132
+ let segs = [];
133
+ for (const s of options.orderBy.Segments) {
134
+ if (s.field instanceof CompoundIdField) {
135
+ segs.push(...s.field.fields.map(c => ({ field: c, isDescending: s.isDescending })));
136
+ }
137
+ else
138
+ segs.push(s);
139
+ }
140
+ for (const c of segs) {
141
+ if (first) {
142
+ select += ' Order By ';
143
+ first = false;
144
+ }
145
+ else
146
+ select += ', ';
147
+ select += e.nameOf(c.field);
148
+ if (c.isDescending)
149
+ select += ' desc';
150
+ }
151
+ }
152
+ if (options.limit) {
153
+ let page = 1;
154
+ if (options.page)
155
+ page = options.page;
156
+ if (page < 1)
157
+ page = 1;
158
+ select += ' ' + this.strategy.getLimitSqlSyntax(options.limit, (page - 1) * options.limit);
159
+ }
160
+ }
161
+ return r.execute(select).then(r => {
162
+ return r.rows.map(y => {
163
+ return this.buildResultRow(colKeys, y, r);
164
+ });
165
+ });
166
+ }
167
+ buildResultRow(colKeys, y, r) {
168
+ let result = {};
169
+ for (let index = 0; index < colKeys.length; index++) {
170
+ const col = colKeys[index];
171
+ try {
172
+ result[col.key] = col.valueConverter.fromDb(y[r.getColumnKeyInResultForIndexInSelect(index)]);
173
+ }
174
+ catch (err) {
175
+ throw new Error("Failed to load from db:" + col.key + "\r\n" + err);
176
+ }
177
+ }
178
+ return result;
179
+ }
180
+ buildSelect(e) {
181
+ let select = '';
182
+ let colKeys = [];
183
+ for (const x of this.entity.fields) {
184
+ if (x.isServerExpression) {
185
+ }
186
+ else {
187
+ if (colKeys.length > 0)
188
+ select += ', ';
189
+ select += e.nameOf(x);
190
+ colKeys.push(x);
191
+ }
192
+ }
193
+ return { colKeys, select };
194
+ }
195
+ async update(id, data) {
196
+ let e = await this.init();
197
+ let r = this.sql.createCommand();
198
+ let f = new FilterConsumerBridgeToSqlRequest(r, e);
199
+ Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)).__applyToConsumer(f);
200
+ let statement = 'update ' + e.entityName + ' set ';
201
+ let added = false;
202
+ for (const x of this.entity.fields) {
203
+ if (x instanceof CompoundIdField) {
204
+ }
205
+ if (e.isDbReadonly(x)) { }
206
+ else if (data[x.key] !== undefined) {
207
+ let v = x.valueConverter.toDb(data[x.key]);
208
+ if (v !== undefined) {
209
+ if (!added)
210
+ added = true;
211
+ else
212
+ statement += ', ';
213
+ statement += e.nameOf(x) + ' = ' + r.addParameterAndReturnSqlToken(v);
214
+ }
215
+ }
216
+ }
217
+ statement += await f.resolveWhere();
218
+ let { colKeys, select } = this.buildSelect(e);
219
+ statement += ' returning ' + select;
220
+ return r.execute(statement).then(sqlResult => {
221
+ return this.buildResultRow(colKeys, sqlResult.rows[0], sqlResult);
222
+ });
223
+ }
224
+ async delete(id) {
225
+ let e = await this.init();
226
+ let r = this.sql.createCommand();
227
+ let f = new FilterConsumerBridgeToSqlRequest(r, e);
228
+ Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)).__applyToConsumer(f);
229
+ let statement = 'delete from ' + e.entityName;
230
+ statement += await f.resolveWhere();
231
+ return r.execute(statement).then(() => { });
232
+ }
233
+ async insert(data) {
234
+ let e = await this.init();
235
+ let r = this.sql.createCommand();
236
+ let cols = '';
237
+ let vals = '';
238
+ let added = false;
239
+ for (const x of this.entity.fields) {
240
+ if (e.isDbReadonly(x)) { }
241
+ else {
242
+ let v = x.valueConverter.toDb(data[x.key]);
243
+ if (v != undefined) {
244
+ if (!added)
245
+ added = true;
246
+ else {
247
+ cols += ', ';
248
+ vals += ', ';
249
+ }
250
+ cols += e.nameOf(x);
251
+ vals += r.addParameterAndReturnSqlToken(v);
252
+ }
253
+ }
254
+ }
255
+ let statement = `insert into ${e.entityName} (${cols}) values (${vals})`;
256
+ let { colKeys, select } = this.buildSelect(e);
257
+ statement += ' returning ' + select;
258
+ return await r.execute(statement).then(sql => this.buildResultRow(colKeys, sql.rows[0], sql));
259
+ }
260
+ }
261
+ ActualSQLServerDataProvider.LogToConsole = false;
@@ -0,0 +1,18 @@
1
+ import { __RowsOfDataForTesting } from "../__RowsOfDataForTesting";
2
+ import { SqlCommand, SqlImplementation } from "../sql-command";
3
+ import { EntityMetadata } from "../remult3";
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
+ getLimitSqlSyntax(limit: number, offset: number): string;
11
+ entityIsUsedForTheFirstTime(entity: EntityMetadata): Promise<void>;
12
+ dropTable(entity: EntityMetadata): Promise<void>;
13
+ createTable(entity: EntityMetadata<any>): Promise<void>;
14
+ createCommand(): SqlCommand;
15
+ transaction(action: (dataProvider: SqlImplementation) => Promise<void>): Promise<void>;
16
+ private addColumnSqlSyntax;
17
+ toString(): string;
18
+ }
@@ -0,0 +1,121 @@
1
+ import { isAutoIncrement } from "../remult3";
2
+ import { SqlDatabase } from "./sql-database";
3
+ import { getDbNameProvider } from "../filter/filter-consumer-bridge-to-sql-request";
4
+ //SqlDatabase.LogToConsole = true;
5
+ export class WebSqlDataProvider {
6
+ constructor(databaseName, databaseSize = 2 * 1024 * 1024) {
7
+ this.databaseName = databaseName;
8
+ //@ts-ignore
9
+ this.db = window.openDatabase(databaseName, '1.0', databaseName, databaseSize);
10
+ }
11
+ getLimitSqlSyntax(limit, offset) {
12
+ return ' limit ' + limit + ' offset ' + offset;
13
+ }
14
+ async entityIsUsedForTheFirstTime(entity) {
15
+ await this.createTable(entity);
16
+ }
17
+ async dropTable(entity) {
18
+ let e = await getDbNameProvider(entity);
19
+ let sql = 'drop table if exists ' + e.entityName;
20
+ if (SqlDatabase.LogToConsole)
21
+ console.log(sql);
22
+ await this.createCommand().execute(sql);
23
+ }
24
+ async createTable(entity) {
25
+ let result = '';
26
+ let e = await getDbNameProvider(entity);
27
+ for (const x of entity.fields) {
28
+ if (!e.isDbReadonly(x) || isAutoIncrement(x)) {
29
+ if (result.length != 0)
30
+ result += ',';
31
+ result += '\r\n ';
32
+ if (isAutoIncrement(x)) {
33
+ if (x.key != entity.idMetadata.field.key)
34
+ throw "in web sql, autoincrement is only allowed for primary key";
35
+ result += e.nameOf(x) + ' integer primary key autoincrement';
36
+ }
37
+ else {
38
+ result += this.addColumnSqlSyntax(x, e.nameOf(x));
39
+ if (x.key == entity.idMetadata.field.key) {
40
+ result += ' primary key';
41
+ }
42
+ }
43
+ }
44
+ }
45
+ let sql = 'create table if not exists ' + e.entityName + ' (' + result + '\r\n)';
46
+ if (SqlDatabase.LogToConsole)
47
+ console.log(sql);
48
+ await this.createCommand().execute(sql);
49
+ }
50
+ createCommand() {
51
+ return new WebSqlBridgeToSQLCommand(this.db);
52
+ }
53
+ async transaction(action) {
54
+ throw new Error("Method not implemented.");
55
+ }
56
+ addColumnSqlSyntax(x, dbName) {
57
+ let result = dbName;
58
+ const nullNumber = x.allowNull ? "" : " default 0 not null";
59
+ if (x.valueType == Date)
60
+ result += " integer";
61
+ else if (x.valueType == Boolean)
62
+ result += " integer " + nullNumber;
63
+ else if (x.valueType == Number) {
64
+ if (!x.valueConverter.fieldTypeInDb)
65
+ result += ' real ' + nullNumber;
66
+ else
67
+ result += ' ' + x.valueConverter.fieldTypeInDb + ' ' + nullNumber;
68
+ }
69
+ else
70
+ result += " text" + (x.allowNull ? " " : " default '' not null ");
71
+ return result;
72
+ }
73
+ toString() { return "WebSqlDataProvider"; }
74
+ }
75
+ class WebSqlBridgeToSQLCommand {
76
+ //@ts-ignore
77
+ constructor(source) {
78
+ this.source = source;
79
+ this.values = [];
80
+ }
81
+ addParameterAndReturnSqlToken(val) {
82
+ this.values.push(val);
83
+ return '~' + this.values.length + '~';
84
+ }
85
+ execute(sql) {
86
+ return new Promise((resolve, reject) => this.source.transaction(t => {
87
+ let s = sql;
88
+ let v = [];
89
+ var m = s.match(/~\d+~/g);
90
+ if (m != null)
91
+ m.forEach(mr => {
92
+ s = s.replace(mr, '?');
93
+ v.push(this.values[Number.parseInt(mr.substring(1, mr.length - 1)) - 1]);
94
+ });
95
+ t.executeSql(s, v, (t1, r) => resolve(new WebSqlBridgeToSQLQueryResult(r)), (t2, err) => {
96
+ reject(err.message);
97
+ return undefined;
98
+ });
99
+ }));
100
+ }
101
+ }
102
+ class WebSqlBridgeToSQLQueryResult {
103
+ //@ts-ignore
104
+ constructor(r) {
105
+ this.r = r;
106
+ this.rows = [];
107
+ for (let i = 0; i < r.rows.length; i++) {
108
+ this.rows.push(r.rows.item(i));
109
+ }
110
+ }
111
+ getColumnKeyInResultForIndexInSelect(index) {
112
+ if (this.rows.length == 0)
113
+ return undefined;
114
+ let i = 0;
115
+ for (let m in this.rows[0]) {
116
+ if (i++ == index)
117
+ return m;
118
+ }
119
+ return undefined;
120
+ }
121
+ }
@@ -0,0 +1,82 @@
1
+ import { Allowed, AllowedForInstance } from "./context";
2
+ import { FieldMetadata as FieldMetadata } from './column-interfaces';
3
+ import { EntityOrderBy, FieldsMetadata, EntityFilter, EntityRef } from "./remult3";
4
+ export interface EntityOptions<entityType = any> {
5
+ /**A human readable name for the entity */
6
+ caption?: string;
7
+ /**
8
+ * Determines if this Entity is available for get requests using Rest Api
9
+ * @see [allowed](http://remult.dev/docs/allowed.html)*/
10
+ allowApiRead?: Allowed;
11
+ /**
12
+ * Determines if this entity can be updated through the api.
13
+ * @see [allowed](http://remult.dev/docs/allowed.html)*/
14
+ allowApiUpdate?: AllowedForInstance<entityType>;
15
+ /** Determines if entries for this entity can be deleted through the api.
16
+ * @see [allowed](http://remult.dev/docs/allowed.html)*/
17
+ allowApiDelete?: AllowedForInstance<entityType>;
18
+ /** Determines if new entries for this entity can be posted through the api.
19
+ * @see [allowed](http://remult.dev/docs/allowed.html)*/
20
+ allowApiInsert?: AllowedForInstance<entityType>;
21
+ /** sets the `allowApiUpdate`, `allowApiDelete` and `allowApiInsert` properties in a single set */
22
+ allowApiCrud?: Allowed;
23
+ /** A filter that determines which rows can be queries using the api.
24
+ * @example
25
+ * apiPrefilter: { archive:false }
26
+ *
27
+ * @see [EntityFilter](http://remult.dev/docs/entityFilter.html)
28
+ */
29
+ apiPrefilter?: EntityFilter<entityType> | (() => EntityFilter<entityType> | Promise<EntityFilter<entityType>>);
30
+ /** A filter that will be used for all queries from this entity both from the API and from within the backend.
31
+ * @example
32
+ * backendPrefilter: { archive:false }
33
+ * @see [EntityFilter](http://remult.dev/docs/entityFilter.html)
34
+ */
35
+ backendPrefilter?: EntityFilter<entityType> | (() => EntityFilter<entityType> | Promise<EntityFilter<entityType>>);
36
+ /** An order by to be used, in case no order by was specified
37
+ * @example
38
+ * defaultOrderBy: { name: "asc" }
39
+ *
40
+ * @example
41
+ * defaultOrderBy: { price: "desc", name: "asc" }
42
+ */
43
+ defaultOrderBy?: EntityOrderBy<entityType>;
44
+ /** An event that will be fired before the Entity will be saved to the database.
45
+ * If the `error` property of the entity's ref or any of it's fields will be set, the save will be aborted and an exception will be thrown.
46
+ * this is the place to run logic that we want to run in any case before an entity is saved.
47
+ * @example
48
+ * @Entity<Task>("tasks", {
49
+ * saving: async task => {
50
+ * task.lastUpdated = new Date()
51
+ * }
52
+ *})
53
+ */
54
+ saving?: (row: entityType, proceedWithoutSavingToDb: () => void) => Promise<any> | any;
55
+ /** will be called after the Entity was saved to the data source. */
56
+ saved?: (row: entityType) => Promise<any> | any;
57
+ /** Will be called before an Entity is deleted. */
58
+ deleting?: (row: entityType) => Promise<any> | any;
59
+ /** Will be called after an Entity is deleted */
60
+ deleted?: (row: entityType) => Promise<any> | any;
61
+ /** Will be called when the entity is being validated, usually prior to the `saving` event */
62
+ validation?: (row: entityType, ref: EntityRef<entityType>) => Promise<any> | any;
63
+ /** The name of the table in the database that holds the data for this entity.
64
+ * If no name is set, the `key` will be used instead.
65
+ * @example
66
+ * dbName:'myProducts'
67
+ */
68
+ dbName?: string;
69
+ /** For entities that are based on SQL expressions instead of a physical table or view*/
70
+ sqlExpression?: string | ((entity: FieldsMetadata<entityType>) => string | Promise<string>);
71
+ /** An arrow function that identifies the `id` column to use for this entity
72
+ * @example
73
+ * //Single column id
74
+ * @Entity<Products>("products", { id:p=>p.productCode })
75
+ * @example
76
+ * //Multiple columns id
77
+ * @Entity<OrderDetails>("orderDetails", { id:od=> [od.orderId, od.productCode] })
78
+ */
79
+ id?: (entity: FieldsMetadata<entityType>) => FieldMetadata | FieldMetadata[];
80
+ entityRefInit?: (ref: EntityRef<entityType>, row: entityType) => void;
81
+ apiRequireId?: Allowed;
82
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,50 @@
1
+ import { SqlCommand } from "../sql-command";
2
+ import { Filter, FilterConsumer } from './filter-interfaces';
3
+ import { FieldMetadata } from "../column-interfaces";
4
+ import { EntityMetadata } from "../remult3/remult3";
5
+ export declare class FilterConsumerBridgeToSqlRequest implements FilterConsumer {
6
+ private r;
7
+ private nameProvider;
8
+ private where;
9
+ _addWhere: boolean;
10
+ promises: Promise<void>[];
11
+ resolveWhere(): Promise<string>;
12
+ constructor(r: SqlCommand, nameProvider: dbNameProvider);
13
+ custom(key: string, customItem: any): void;
14
+ or(orElements: Filter[]): void;
15
+ isNull(col: FieldMetadata): void;
16
+ isNotNull(col: FieldMetadata): void;
17
+ isIn(col: FieldMetadata, val: any[]): void;
18
+ isEqualTo(col: FieldMetadata, val: any): void;
19
+ isDifferentFrom(col: FieldMetadata, val: any): void;
20
+ isGreaterOrEqualTo(col: FieldMetadata, val: any): void;
21
+ isGreaterThan(col: FieldMetadata, val: any): void;
22
+ isLessOrEqualTo(col: FieldMetadata, val: any): void;
23
+ isLessThan(col: FieldMetadata, val: any): void;
24
+ containsCaseInsensitive(col: FieldMetadata, val: any): void;
25
+ private add;
26
+ private addToWhere;
27
+ databaseCustom(databaseCustom: CustomSqlFilterObject): void;
28
+ }
29
+ export declare type CustomSqlFilterBuilderFunction = (builder: CustomSqlFilterBuilder) => void | Promise<any>;
30
+ export interface CustomSqlFilterObject {
31
+ buildSql: CustomSqlFilterBuilderFunction;
32
+ }
33
+ export declare class CustomSqlFilterBuilder {
34
+ private r;
35
+ constructor(r: SqlCommand);
36
+ sql: string;
37
+ addParameterAndReturnSqlToken<valueType>(val: valueType, field?: FieldMetadata<valueType>): string;
38
+ }
39
+ export declare function getDbNameProvider(meta: EntityMetadata): Promise<dbNameProvider>;
40
+ export declare class dbNameProviderImpl {
41
+ map: Map<string, string>;
42
+ nameOf(field: FieldMetadata<any>): string;
43
+ entityName: string;
44
+ isDbReadonly(x: FieldMetadata): boolean;
45
+ }
46
+ export interface dbNameProvider {
47
+ nameOf(field: FieldMetadata<any>): string;
48
+ entityName: string;
49
+ isDbReadonly(x: FieldMetadata): boolean;
50
+ }
@@ -0,0 +1,139 @@
1
+ export class FilterConsumerBridgeToSqlRequest {
2
+ constructor(r, nameProvider) {
3
+ this.r = r;
4
+ this.nameProvider = nameProvider;
5
+ this.where = "";
6
+ this._addWhere = true;
7
+ this.promises = [];
8
+ }
9
+ async resolveWhere() {
10
+ while (this.promises.length > 0) {
11
+ let p = this.promises;
12
+ this.promises = [];
13
+ for (const pr of p) {
14
+ await pr;
15
+ }
16
+ }
17
+ return this.where;
18
+ }
19
+ custom(key, customItem) {
20
+ throw new Error("Custom filter should be translated before it gets here");
21
+ }
22
+ or(orElements) {
23
+ let statement = '';
24
+ this.promises.push((async () => {
25
+ for (const element of orElements) {
26
+ let f = new FilterConsumerBridgeToSqlRequest(this.r, this.nameProvider);
27
+ f._addWhere = false;
28
+ element.__applyToConsumer(f);
29
+ let where = await f.resolveWhere();
30
+ if (!where)
31
+ return; //since if any member of or is empty, then the entire or is irrelevant
32
+ if (where.length > 0) {
33
+ if (statement.length > 0) {
34
+ statement += " or ";
35
+ }
36
+ if (orElements.length > 1) {
37
+ statement += "(" + where + ")";
38
+ }
39
+ else
40
+ statement += where;
41
+ }
42
+ }
43
+ this.addToWhere("(" + statement + ")");
44
+ })());
45
+ }
46
+ isNull(col) {
47
+ this.promises.push((async () => this.addToWhere(this.nameProvider.nameOf(col) + ' is null'))());
48
+ }
49
+ isNotNull(col) {
50
+ this.promises.push((async () => this.addToWhere(this.nameProvider.nameOf(col) + ' is not null'))());
51
+ }
52
+ isIn(col, val) {
53
+ this.promises.push((async () => {
54
+ if (val && val.length > 0)
55
+ this.addToWhere(this.nameProvider.nameOf(col) + " in (" + val.map(x => this.r.addParameterAndReturnSqlToken(col.valueConverter.toDb(x))).join(",") + ")");
56
+ else
57
+ this.addToWhere('1 = 0 /*isIn with no values*/');
58
+ })());
59
+ }
60
+ isEqualTo(col, val) {
61
+ this.add(col, val, "=");
62
+ }
63
+ isDifferentFrom(col, val) {
64
+ this.add(col, val, "<>");
65
+ }
66
+ isGreaterOrEqualTo(col, val) {
67
+ this.add(col, val, ">=");
68
+ }
69
+ isGreaterThan(col, val) {
70
+ this.add(col, val, ">");
71
+ }
72
+ isLessOrEqualTo(col, val) {
73
+ this.add(col, val, "<=");
74
+ }
75
+ isLessThan(col, val) {
76
+ this.add(col, val, "<");
77
+ }
78
+ containsCaseInsensitive(col, val) {
79
+ this.promises.push((async () => {
80
+ this.addToWhere('lower (' + this.nameProvider.nameOf(col) + ") like lower ('%" + val.replace(/'/g, '\'\'') + "%')");
81
+ })());
82
+ }
83
+ add(col, val, operator) {
84
+ this.promises.push((async () => {
85
+ let x = this.nameProvider.nameOf(col) + ' ' + operator + ' ' + this.r.addParameterAndReturnSqlToken(col.valueConverter.toDb(val));
86
+ this.addToWhere(x);
87
+ })());
88
+ }
89
+ addToWhere(x) {
90
+ if (this.where.length == 0) {
91
+ if (this._addWhere)
92
+ this.where += ' where ';
93
+ }
94
+ else
95
+ this.where += ' and ';
96
+ this.where += x;
97
+ }
98
+ databaseCustom(databaseCustom) {
99
+ this.promises.push((async () => {
100
+ if (databaseCustom?.buildSql) {
101
+ let item = new CustomSqlFilterBuilder(this.r);
102
+ await databaseCustom.buildSql(item);
103
+ if (item.sql) {
104
+ this.addToWhere("(" + item.sql + ")");
105
+ }
106
+ }
107
+ })());
108
+ }
109
+ }
110
+ export class CustomSqlFilterBuilder {
111
+ constructor(r) {
112
+ this.r = r;
113
+ this.sql = '';
114
+ }
115
+ addParameterAndReturnSqlToken(val, field) {
116
+ if (field)
117
+ val = field.valueConverter.toDb(val);
118
+ return this.r.addParameterAndReturnSqlToken(val);
119
+ }
120
+ }
121
+ export async function getDbNameProvider(meta) {
122
+ var result = new dbNameProviderImpl();
123
+ for (const f of meta.fields) {
124
+ result.map.set(f.key, await f.getDbName());
125
+ }
126
+ result.entityName = await meta.getDbName();
127
+ return result;
128
+ }
129
+ export class dbNameProviderImpl {
130
+ constructor() {
131
+ this.map = new Map();
132
+ }
133
+ nameOf(field) {
134
+ return this.map.get(field.key);
135
+ }
136
+ isDbReadonly(x) {
137
+ return (x.dbReadOnly || x.isServerExpression || this.nameOf(x) != x.options.dbName);
138
+ }
139
+ }