orange-orm 4.10.0-beta.0 → 5.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +167 -24
- package/dist/index.browser.mjs +107 -8
- package/dist/index.mjs +107 -9
- package/package.json +1 -1
- package/src/client/createPatch.js +2 -0
- package/src/client/index.js +66 -2
- package/src/client/stringify.js +5 -3
- package/src/map.d.ts +46 -4
- package/src/map2.d.ts +11 -16
- package/src/nodeSqlite/newDatabase.js +0 -1
- package/src/table/column/utils.js +3 -2
- package/src/table/column.js +32 -2
- package/src/table/relatedTable/where.js +2 -2
- package/src/table/where.js +2 -2
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ Watch the [tutorial video on YouTube](https://youtu.be/1IwwjPr2lMs)
|
|
|
51
51
|

|
|
52
52
|
|
|
53
53
|
<sub>📄 map.ts</sub>
|
|
54
|
-
```
|
|
54
|
+
```ts
|
|
55
55
|
import orange from 'orange-orm';
|
|
56
56
|
|
|
57
57
|
const map = orange.map(x => ({
|
|
@@ -88,7 +88,7 @@ const map = orange.map(x => ({
|
|
|
88
88
|
street: column('street').string(),
|
|
89
89
|
postalCode: column('postalCode').string(),
|
|
90
90
|
postalPlace: column('postalPlace').string(),
|
|
91
|
-
countryCode: column('countryCode').string(),
|
|
91
|
+
countryCode: column('countryCode').string().enum(['NO', 'SE', 'DK', 'FI', 'IS', 'DE', 'FR', 'NL', 'ES', 'IT']),
|
|
92
92
|
}))
|
|
93
93
|
|
|
94
94
|
})).map(x => ({
|
|
@@ -106,7 +106,7 @@ export default map;
|
|
|
106
106
|
```
|
|
107
107
|
<sub>📄 update.ts</sub>
|
|
108
108
|
|
|
109
|
-
```
|
|
109
|
+
```ts
|
|
110
110
|
import map from './map';
|
|
111
111
|
const db = map.sqlite('demo.db');
|
|
112
112
|
|
|
@@ -127,7 +127,7 @@ async function updateRow() {
|
|
|
127
127
|
```
|
|
128
128
|
<sub>📄 filter.ts</sub>
|
|
129
129
|
|
|
130
|
-
```
|
|
130
|
+
```ts
|
|
131
131
|
import map from './map';
|
|
132
132
|
const db = map.sqlite('demo.db');
|
|
133
133
|
|
|
@@ -157,7 +157,8 @@ Each column within your database table is designated by using the <strong><i>col
|
|
|
157
157
|
Relationships between tables can also be outlined. By using methods like <strong><i>hasOne</i></strong>, <strong><i>hasMany</i></strong>, and <strong><i>references</i></strong>, you can establish connections that reflect the relationships in your data schema. In the example below, an 'order' is linked to a 'customer' reference, a 'deliveryAddress', and multiple 'lines'. The hasMany and hasOne relations represents ownership - the tables 'deliveryAddress' and 'orderLine' are owned by the 'order' table, and therefore, they contain the 'orderId' column referring to their parent table, which is 'order'. The similar relationship exists between orderLine and package - hence the packages are owned by the orderLine. Conversely, the customer table is independent and can exist without any knowledge of the 'order' table. Therefore we say that the order table <i>references</i> the customer table - necessitating the existence of a 'customerId' column in the 'order' table.</p>
|
|
158
158
|
|
|
159
159
|
<sub>📄 map.ts</sub>
|
|
160
|
-
|
|
160
|
+
|
|
161
|
+
```ts
|
|
161
162
|
import orange from 'orange-orm';
|
|
162
163
|
|
|
163
164
|
const map = orange.map(x => ({
|
|
@@ -193,7 +194,7 @@ const map = orange.map(x => ({
|
|
|
193
194
|
street: column('street').string(),
|
|
194
195
|
postalCode: column('postalCode').string(),
|
|
195
196
|
postalPlace: column('postalPlace').string(),
|
|
196
|
-
countryCode: column('countryCode').string(),
|
|
197
|
+
countryCode: column('countryCode').string().enum(['NO', 'SE', 'DK', 'FI', 'IS', 'DE', 'FR', 'NL', 'ES', 'IT']),
|
|
197
198
|
}))
|
|
198
199
|
|
|
199
200
|
})).map(x => ({
|
|
@@ -218,7 +219,8 @@ Then, we define a SQL string. This string outlines the structure of our SQLite d
|
|
|
218
219
|
Because of a peculiarity in SQLite, which only allows one statement execution at a time, we split this SQL string into separate statements. We do this using the split() method, which breaks up the string at every semicolon.
|
|
219
220
|
|
|
220
221
|
<sub>📄 init.ts</sub>
|
|
221
|
-
|
|
222
|
+
|
|
223
|
+
```ts
|
|
222
224
|
import map from './map';
|
|
223
225
|
const db = map.sqlite('demo.db');
|
|
224
226
|
|
|
@@ -337,7 +339,7 @@ await db.transaction(async (db) => {
|
|
|
337
339
|
__From the browser__
|
|
338
340
|
You can securely use Orange from the browser by utilizing the Express plugin, which serves to safeguard sensitive database credentials from exposure at the client level. This technique bypasses the need to transmit raw SQL queries directly from the client to the server. Instead, it logs method calls initiated by the client, which are later replayed and authenticated on the server. This not only reinforces security by preventing the disclosure of raw SQL queries on the client side but also facilitates a smoother operation. Essentially, this method mirrors a traditional REST API, augmented with advanced TypeScript tooling for enhanced functionality. You can read more about it in the section called [In the browser](#user-content-in-the-browser)
|
|
339
341
|
<sub>📄 server.ts</sub>
|
|
340
|
-
```
|
|
342
|
+
```ts
|
|
341
343
|
import map from './map';
|
|
342
344
|
import { json } from 'body-parser';
|
|
343
345
|
import express from 'express';
|
|
@@ -354,7 +356,7 @@ express().disable('x-powered-by')
|
|
|
354
356
|
```
|
|
355
357
|
|
|
356
358
|
<sub>📄 browser.ts</sub>
|
|
357
|
-
```
|
|
359
|
+
```ts
|
|
358
360
|
import map from './map';
|
|
359
361
|
|
|
360
362
|
const db = map.http('http://localhost:3000/orange');
|
|
@@ -432,7 +434,7 @@ database_id = "<your-guid-for-the-database>"
|
|
|
432
434
|
```
|
|
433
435
|
|
|
434
436
|
<sub>📄 src/index.ts</sub>
|
|
435
|
-
```
|
|
437
|
+
```ts
|
|
436
438
|
import map from './map';
|
|
437
439
|
|
|
438
440
|
export interface Env {
|
|
@@ -1173,7 +1175,8 @@ async function deleteRows() {
|
|
|
1173
1175
|
Raw sql queries, raw sql filters and transactions are disabled at the http client due to security reasons. If you would like Orange to support other web frameworks, like nestJs, fastify, etc, please let me know.</p>
|
|
1174
1176
|
|
|
1175
1177
|
<sub>📄 server.ts</sub>
|
|
1176
|
-
|
|
1178
|
+
|
|
1179
|
+
```ts
|
|
1177
1180
|
import map from './map';
|
|
1178
1181
|
import { json } from 'body-parser';
|
|
1179
1182
|
import express from 'express';
|
|
@@ -1190,7 +1193,7 @@ express().disable('x-powered-by')
|
|
|
1190
1193
|
```
|
|
1191
1194
|
|
|
1192
1195
|
<sub>📄 browser.ts</sub>
|
|
1193
|
-
```
|
|
1196
|
+
```ts
|
|
1194
1197
|
import map from './map';
|
|
1195
1198
|
|
|
1196
1199
|
const db = map.http('http://localhost:3000/orange');
|
|
@@ -1221,7 +1224,7 @@ One notable side effect compared to the previous example, is that only the order
|
|
|
1221
1224
|
|
|
1222
1225
|
<sub>📄 server.ts</sub>
|
|
1223
1226
|
|
|
1224
|
-
```
|
|
1227
|
+
```ts
|
|
1225
1228
|
import map from './map';
|
|
1226
1229
|
import { json } from 'body-parser';
|
|
1227
1230
|
import express from 'express';
|
|
@@ -1256,7 +1259,7 @@ function validateToken(req, res, next) {
|
|
|
1256
1259
|
|
|
1257
1260
|
<sub>📄 browser.ts</sub>
|
|
1258
1261
|
|
|
1259
|
-
```
|
|
1262
|
+
```ts
|
|
1260
1263
|
import map from './map';
|
|
1261
1264
|
|
|
1262
1265
|
const db = map.http('http://localhost:3000/orange');
|
|
@@ -1300,7 +1303,7 @@ async function updateRows() {
|
|
|
1300
1303
|
|
|
1301
1304
|
```
|
|
1302
1305
|
|
|
1303
|
-
__Row Level
|
|
1306
|
+
__Row Level Security__
|
|
1304
1307
|
You can enforce tenant isolation at the database level by combining Postgres RLS with Express hooks. The example below mirrors the “Interceptors and base filter” style by putting the tenant id in a (fake) token on the client, then extracting it on the server and setting it inside the transaction. This is convenient for a demo because we can seed data and prove rows are filtered. In a real application you must validate signatures and derive tenant id from a trusted identity source, not from arbitrary client input.
|
|
1305
1308
|
|
|
1306
1309
|
<sub>📄 setup.sql</sub>
|
|
@@ -1328,7 +1331,7 @@ insert into tenant_data (tenant_id, value) values
|
|
|
1328
1331
|
|
|
1329
1332
|
<sub>📄 server.ts</sub>
|
|
1330
1333
|
|
|
1331
|
-
```
|
|
1334
|
+
```ts
|
|
1332
1335
|
import map from './map';
|
|
1333
1336
|
import { json } from 'body-parser';
|
|
1334
1337
|
import express from 'express';
|
|
@@ -1343,6 +1346,7 @@ express().disable('x-powered-by')
|
|
|
1343
1346
|
.use('/orange', db.express({
|
|
1344
1347
|
hooks: {
|
|
1345
1348
|
transaction: {
|
|
1349
|
+
//beforeBegin: async (db, req) => ...,
|
|
1346
1350
|
afterBegin: async (db, req) => {
|
|
1347
1351
|
const tenantId = Number.parseInt(String(req.user?.tenantId ?? ''), 10);
|
|
1348
1352
|
if (!Number.isFinite(tenantId)) throw new Error('Missing tenant id');
|
|
@@ -1351,7 +1355,12 @@ express().disable('x-powered-by')
|
|
|
1351
1355
|
sql: 'select set_config(\'app.tenant_id\', ?, true)',
|
|
1352
1356
|
parameters: [String(tenantId)]
|
|
1353
1357
|
});
|
|
1354
|
-
}
|
|
1358
|
+
},
|
|
1359
|
+
//beforeCommit: async (db, req) => ...,
|
|
1360
|
+
//afterCommit: async (db, req) => ...,
|
|
1361
|
+
// afterRollback: async (db, req, error) => {
|
|
1362
|
+
// console.dir(error);
|
|
1363
|
+
// }
|
|
1355
1364
|
}
|
|
1356
1365
|
}
|
|
1357
1366
|
}))
|
|
@@ -1380,7 +1389,7 @@ function decodeFakeJwt(token) {
|
|
|
1380
1389
|
|
|
1381
1390
|
<sub>📄 browser.ts</sub>
|
|
1382
1391
|
|
|
1383
|
-
```
|
|
1392
|
+
```ts
|
|
1384
1393
|
import map from './map';
|
|
1385
1394
|
|
|
1386
1395
|
const db = map.http('http://localhost:3000/orange');
|
|
@@ -1793,7 +1802,8 @@ async function execute() {
|
|
|
1793
1802
|
- **`json`** and **`jsonOf<T>`** are represented as an object or array in javascript and maps to JSON, JSONB, NVARCHAR(max) or TEXT (sqlite) in sql.
|
|
1794
1803
|
|
|
1795
1804
|
<sub>📄 map.ts</sub>
|
|
1796
|
-
|
|
1805
|
+
|
|
1806
|
+
```ts
|
|
1797
1807
|
import orange from 'orange-orm';
|
|
1798
1808
|
|
|
1799
1809
|
interface Pet {
|
|
@@ -1816,7 +1826,8 @@ const map = orange.map(x => ({
|
|
|
1816
1826
|
}));
|
|
1817
1827
|
```
|
|
1818
1828
|
<sub>📄 map.js</sub>
|
|
1819
|
-
|
|
1829
|
+
|
|
1830
|
+
```js
|
|
1820
1831
|
import orange from 'orange-orm';
|
|
1821
1832
|
|
|
1822
1833
|
/**
|
|
@@ -1843,6 +1854,138 @@ const map = orange.map(x => ({
|
|
|
1843
1854
|
```
|
|
1844
1855
|
</details>
|
|
1845
1856
|
|
|
1857
|
+
<details id="enums"><summary><strong>Enums</strong></summary>
|
|
1858
|
+
<p>Enums can be defined using object literals, arrays, or TypeScript enums. The <strong><i>enum(...)</i></strong> method uses literal types when possible, so prefer patterns that keep literals (inline objects, <code>as const</code>, or <code>Object.freeze</code> in JS).</p>
|
|
1859
|
+
|
|
1860
|
+
<sub>📄 map.ts (TypeScript enum)</sub>
|
|
1861
|
+
|
|
1862
|
+
```ts
|
|
1863
|
+
enum CountryCode {
|
|
1864
|
+
NORWAY = 'NO',
|
|
1865
|
+
SWEDEN = 'SE',
|
|
1866
|
+
DENMARK = 'DK',
|
|
1867
|
+
FINLAND = 'FI',
|
|
1868
|
+
ICELAND = 'IS',
|
|
1869
|
+
GERMANY = 'DE',
|
|
1870
|
+
FRANCE = 'FR',
|
|
1871
|
+
NETHERLANDS = 'NL',
|
|
1872
|
+
SPAIN = 'ES',
|
|
1873
|
+
ITALY = 'IT',
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
const map = orange.map(x => ({
|
|
1877
|
+
deliveryAddress: x.table('deliveryAddress').map(({ column }) => ({
|
|
1878
|
+
id: column('id').numeric().primary(),
|
|
1879
|
+
name: column('name').string(),
|
|
1880
|
+
street: column('street').string(),
|
|
1881
|
+
postalCode: column('postalCode').string(),
|
|
1882
|
+
postalPlace: column('postalPlace').string(),
|
|
1883
|
+
countryCode: column('countryCode').string().enum(CountryCode),
|
|
1884
|
+
}))
|
|
1885
|
+
}));
|
|
1886
|
+
```
|
|
1887
|
+
|
|
1888
|
+
|
|
1889
|
+
<sub>📄 map.ts (as const)</sub>
|
|
1890
|
+
|
|
1891
|
+
```ts
|
|
1892
|
+
const Countries = {
|
|
1893
|
+
NORWAY: 'NO',
|
|
1894
|
+
SWEDEN: 'SE',
|
|
1895
|
+
DENMARK: 'DK',
|
|
1896
|
+
FINLAND: 'FI',
|
|
1897
|
+
ICELAND: 'IS',
|
|
1898
|
+
GERMANY: 'DE',
|
|
1899
|
+
FRANCE: 'FR',
|
|
1900
|
+
NETHERLANDS: 'NL',
|
|
1901
|
+
SPAIN: 'ES',
|
|
1902
|
+
ITALY: 'IT',
|
|
1903
|
+
} as const;
|
|
1904
|
+
|
|
1905
|
+
const map = orange.map(x => ({
|
|
1906
|
+
deliveryAddress: x.table('deliveryAddress').map(({ column }) => ({
|
|
1907
|
+
id: column('id').numeric().primary(),
|
|
1908
|
+
name: column('name').string(),
|
|
1909
|
+
street: column('street').string(),
|
|
1910
|
+
postalCode: column('postalCode').string(),
|
|
1911
|
+
postalPlace: column('postalPlace').string(),
|
|
1912
|
+
countryCode: column('countryCode').string().enum(Countries),
|
|
1913
|
+
}))
|
|
1914
|
+
}));
|
|
1915
|
+
```
|
|
1916
|
+
|
|
1917
|
+
<sub>📄 map.ts (array)</sub>
|
|
1918
|
+
|
|
1919
|
+
```ts
|
|
1920
|
+
const map = orange.map(x => ({
|
|
1921
|
+
deliveryAddress: x.table('deliveryAddress').map(({ column }) => ({
|
|
1922
|
+
id: column('id').numeric().primary(),
|
|
1923
|
+
name: column('name').string(),
|
|
1924
|
+
street: column('street').string(),
|
|
1925
|
+
postalCode: column('postalCode').string(),
|
|
1926
|
+
postalPlace: column('postalPlace').string(),
|
|
1927
|
+
countryCode: column('countryCode').string().enum(
|
|
1928
|
+
['NO', 'SE', 'DK', 'FI', 'IS', 'DE', 'FR', 'NL', 'ES', 'IT']
|
|
1929
|
+
),
|
|
1930
|
+
}))
|
|
1931
|
+
}));
|
|
1932
|
+
```
|
|
1933
|
+
|
|
1934
|
+
<sub>📄 map.ts (literal object)</sub>
|
|
1935
|
+
|
|
1936
|
+
```ts
|
|
1937
|
+
const map = orange.map(x => ({
|
|
1938
|
+
deliveryAddress: x.table('deliveryAddress').map(({ column }) => ({
|
|
1939
|
+
id: column('id').numeric().primary(),
|
|
1940
|
+
name: column('name').string(),
|
|
1941
|
+
street: column('street').string(),
|
|
1942
|
+
postalCode: column('postalCode').string(),
|
|
1943
|
+
postalPlace: column('postalPlace').string(),
|
|
1944
|
+
countryCode: column('countryCode').string().enum({
|
|
1945
|
+
NORWAY: 'NO',
|
|
1946
|
+
SWEDEN: 'SE',
|
|
1947
|
+
DENMARK: 'DK',
|
|
1948
|
+
FINLAND: 'FI',
|
|
1949
|
+
ICELAND: 'IS',
|
|
1950
|
+
GERMANY: 'DE',
|
|
1951
|
+
FRANCE: 'FR',
|
|
1952
|
+
NETHERLANDS: 'NL',
|
|
1953
|
+
SPAIN: 'ES',
|
|
1954
|
+
ITALY: 'IT',
|
|
1955
|
+
}),
|
|
1956
|
+
}))
|
|
1957
|
+
}));
|
|
1958
|
+
```
|
|
1959
|
+
|
|
1960
|
+
<sub>📄 map.js (Object.freeze)</sub>
|
|
1961
|
+
|
|
1962
|
+
```js
|
|
1963
|
+
const Countries = Object.freeze({
|
|
1964
|
+
NORWAY: 'NO',
|
|
1965
|
+
SWEDEN: 'SE',
|
|
1966
|
+
DENMARK: 'DK',
|
|
1967
|
+
FINLAND: 'FI',
|
|
1968
|
+
ICELAND: 'IS',
|
|
1969
|
+
GERMANY: 'DE',
|
|
1970
|
+
FRANCE: 'FR',
|
|
1971
|
+
NETHERLANDS: 'NL',
|
|
1972
|
+
SPAIN: 'ES',
|
|
1973
|
+
ITALY: 'IT',
|
|
1974
|
+
});
|
|
1975
|
+
|
|
1976
|
+
const map = orange.map(x => ({
|
|
1977
|
+
deliveryAddress: x.table('deliveryAddress').map(({ column }) => ({
|
|
1978
|
+
id: column('id').numeric().primary(),
|
|
1979
|
+
name: column('name').string(),
|
|
1980
|
+
street: column('street').string(),
|
|
1981
|
+
postalCode: column('postalCode').string(),
|
|
1982
|
+
postalPlace: column('postalPlace').string(),
|
|
1983
|
+
countryCode: column('countryCode').string().enum(Countries),
|
|
1984
|
+
}))
|
|
1985
|
+
}));
|
|
1986
|
+
```
|
|
1987
|
+
</details>
|
|
1988
|
+
|
|
1846
1989
|
<details id="default-values"><summary><strong>Default values</strong></summary>
|
|
1847
1990
|
<p>Utilizing default values can be especially useful for automatically populating these fields when the underlying database doesn't offer native support for default value generation.
|
|
1848
1991
|
|
|
@@ -1869,7 +2012,7 @@ export default map;
|
|
|
1869
2012
|
<p>In the previous sections you have already seen the <strong><i>notNull()</i></strong> validator being used on some columns. This will not only generate correct typescript mapping, but also throw an error if value is set to null or undefined. However, sometimes we do not want the notNull-validator to be run on inserts. Typically, when we have an autoincremental key or server generated uuid, it does not make sense to check for null on insert. This is where <strong><i>notNullExceptInsert()</strong></i> comes to rescue. You can also create your own custom validator as shown below. The last kind of validator, is the <a href="https://ajv.js.org/json-schema.html">ajv JSON schema validator</a>. This can be used on json columns as well as any other column type.</p>
|
|
1870
2013
|
|
|
1871
2014
|
<sub>📄 map.ts</sub>
|
|
1872
|
-
```
|
|
2015
|
+
```ts
|
|
1873
2016
|
import orange from 'orange-orm';
|
|
1874
2017
|
|
|
1875
2018
|
interface Pet {
|
|
@@ -1900,7 +2043,7 @@ const map = orange.map(x => ({
|
|
|
1900
2043
|
export default map;
|
|
1901
2044
|
```
|
|
1902
2045
|
<sub>📄 map.js</sub>
|
|
1903
|
-
```
|
|
2046
|
+
```js
|
|
1904
2047
|
import orange from 'orange-orm';
|
|
1905
2048
|
|
|
1906
2049
|
/**
|
|
@@ -2110,7 +2253,7 @@ async function getCount() {
|
|
|
2110
2253
|
|
|
2111
2254
|
<sub>📄 map.ts</sub>
|
|
2112
2255
|
|
|
2113
|
-
```
|
|
2256
|
+
```ts
|
|
2114
2257
|
import orange from 'orange-orm';
|
|
2115
2258
|
|
|
2116
2259
|
const map = orange.map(x => ({
|
|
@@ -2126,7 +2269,7 @@ export default map;
|
|
|
2126
2269
|
```
|
|
2127
2270
|
<sub>📄 sensitive.ts</sub>
|
|
2128
2271
|
|
|
2129
|
-
```
|
|
2272
|
+
```ts
|
|
2130
2273
|
import map from './map';
|
|
2131
2274
|
const db = map.sqlite('demo.db');
|
|
2132
2275
|
|
package/dist/index.browser.mjs
CHANGED
|
@@ -790,8 +790,10 @@ function requireStringify () {
|
|
|
790
790
|
}
|
|
791
791
|
|
|
792
792
|
function replacer(key, value) {
|
|
793
|
-
//
|
|
794
|
-
if (value
|
|
793
|
+
// @ts-ignore
|
|
794
|
+
if (typeof value === 'bigint')
|
|
795
|
+
return value.toString();
|
|
796
|
+
else if (value instanceof Date && !isNaN(value))
|
|
795
797
|
return dateToISOString(value);
|
|
796
798
|
else
|
|
797
799
|
return value;
|
|
@@ -901,6 +903,8 @@ function requireCreatePatch () {
|
|
|
901
903
|
}
|
|
902
904
|
return copy;
|
|
903
905
|
}
|
|
906
|
+
else if (typeof object === 'bigint')
|
|
907
|
+
return object.toString();
|
|
904
908
|
else if (isValidDate(object))
|
|
905
909
|
return dateToIsoString(object);
|
|
906
910
|
else if (object === Object(object)) {
|
|
@@ -1134,8 +1138,9 @@ function requireUtils () {
|
|
|
1134
1138
|
}
|
|
1135
1139
|
params.push(sql, filter.parameters);
|
|
1136
1140
|
}
|
|
1137
|
-
else if (isObjectFilter(filter, optionalTable))
|
|
1141
|
+
else if (isObjectFilter(filter, optionalTable)) {
|
|
1138
1142
|
return newObjectFilter(context, filter, optionalTable);
|
|
1143
|
+
}
|
|
1139
1144
|
else
|
|
1140
1145
|
params = [filter];
|
|
1141
1146
|
} else {
|
|
@@ -3091,6 +3096,14 @@ function requireClient () {
|
|
|
3091
3096
|
|
|
3092
3097
|
async function getMany(_, strategy) {
|
|
3093
3098
|
let metaPromise = getMeta();
|
|
3099
|
+
if (looksLikeFetchStrategy(_) && (strategy === undefined || !looksLikeFetchStrategy(strategy))) {
|
|
3100
|
+
let meta = await metaPromise;
|
|
3101
|
+
if (!isPrimaryKeyObject(meta, _)) {
|
|
3102
|
+
let _strategy = _;
|
|
3103
|
+
_ = strategy;
|
|
3104
|
+
strategy = _strategy;
|
|
3105
|
+
}
|
|
3106
|
+
}
|
|
3094
3107
|
strategy = extractFetchingStrategy({}, strategy);
|
|
3095
3108
|
let args = [_, strategy].concat(Array.prototype.slice.call(arguments).slice(2));
|
|
3096
3109
|
let rows = await getManyCore.apply(null, args);
|
|
@@ -3118,13 +3131,69 @@ function requireClient () {
|
|
|
3118
3131
|
return adapter.post(body);
|
|
3119
3132
|
}
|
|
3120
3133
|
|
|
3134
|
+
function isRawFilter(value) {
|
|
3135
|
+
return value && typeof value === 'object'
|
|
3136
|
+
&& (typeof value.sql === 'string' || typeof value.sql === 'function');
|
|
3137
|
+
}
|
|
3138
|
+
|
|
3139
|
+
function looksLikeFetchStrategy(value) {
|
|
3140
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
3141
|
+
return false;
|
|
3142
|
+
if (isRawFilter(value))
|
|
3143
|
+
return false;
|
|
3144
|
+
if (Object.keys(value).length === 0)
|
|
3145
|
+
return true;
|
|
3146
|
+
if ('where' in value || 'orderBy' in value || 'limit' in value || 'offset' in value)
|
|
3147
|
+
return true;
|
|
3148
|
+
for (let key in value) {
|
|
3149
|
+
const v = value[key];
|
|
3150
|
+
if (typeof v === 'boolean')
|
|
3151
|
+
return true;
|
|
3152
|
+
if (v && typeof v === 'object' && !Array.isArray(v))
|
|
3153
|
+
return true;
|
|
3154
|
+
}
|
|
3155
|
+
return false;
|
|
3156
|
+
}
|
|
3157
|
+
|
|
3158
|
+
function isPrimaryKeyObject(meta, value) {
|
|
3159
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
3160
|
+
return false;
|
|
3161
|
+
if (isRawFilter(value))
|
|
3162
|
+
return false;
|
|
3163
|
+
const keyNames = meta?.keys?.map(key => key.name);
|
|
3164
|
+
if (!keyNames || keyNames.length === 0)
|
|
3165
|
+
return false;
|
|
3166
|
+
const keys = Object.keys(value);
|
|
3167
|
+
if (keys.length === 0)
|
|
3168
|
+
return false;
|
|
3169
|
+
for (let i = 0; i < keys.length; i++) {
|
|
3170
|
+
const key = keys[i];
|
|
3171
|
+
if (!keyNames.includes(key))
|
|
3172
|
+
return false;
|
|
3173
|
+
const val = value[key];
|
|
3174
|
+
if (val && typeof val === 'object' && !(val instanceof Date))
|
|
3175
|
+
return false;
|
|
3176
|
+
}
|
|
3177
|
+
return true;
|
|
3178
|
+
}
|
|
3179
|
+
|
|
3180
|
+
function normalizeGetOneArgs(meta, filter, strategy) {
|
|
3181
|
+
if (looksLikeFetchStrategy(filter) && (strategy === undefined || !looksLikeFetchStrategy(strategy))) {
|
|
3182
|
+
if (!isPrimaryKeyObject(meta, filter))
|
|
3183
|
+
return { filter: strategy, strategy: filter };
|
|
3184
|
+
}
|
|
3185
|
+
return { filter, strategy };
|
|
3186
|
+
}
|
|
3187
|
+
|
|
3121
3188
|
async function getOne(filter, strategy) {
|
|
3122
3189
|
let metaPromise = getMeta();
|
|
3123
|
-
|
|
3190
|
+
let meta = await metaPromise;
|
|
3191
|
+
let normalized = normalizeGetOneArgs(meta, filter, strategy);
|
|
3192
|
+
filter = normalized.filter;
|
|
3193
|
+
strategy = extractFetchingStrategy({}, normalized.strategy);
|
|
3124
3194
|
let _strategy = { ...strategy, ...{ limit: 1 } };
|
|
3125
3195
|
let args = [filter, _strategy].concat(Array.prototype.slice.call(arguments).slice(2));
|
|
3126
3196
|
let rows = await getManyCore.apply(null, args);
|
|
3127
|
-
await metaPromise;
|
|
3128
3197
|
if (rows.length === 0)
|
|
3129
3198
|
return;
|
|
3130
3199
|
return proxify(rows[0], strategy, true);
|
|
@@ -5817,6 +5886,37 @@ function requireColumn () {
|
|
|
5817
5886
|
return c;
|
|
5818
5887
|
};
|
|
5819
5888
|
|
|
5889
|
+
c.enum = function(values) {
|
|
5890
|
+
let list = values;
|
|
5891
|
+
if (Array.isArray(values))
|
|
5892
|
+
list = values;
|
|
5893
|
+
else if (values && typeof values === 'object') {
|
|
5894
|
+
const keys = Object.keys(values);
|
|
5895
|
+
const nonNumericKeys = keys.filter((key) => !/^-?\d+$/.test(key));
|
|
5896
|
+
list = (nonNumericKeys.length ? nonNumericKeys : keys).map((key) => values[key]);
|
|
5897
|
+
}
|
|
5898
|
+
else
|
|
5899
|
+
throw new Error('enum values must be an array');
|
|
5900
|
+
const allowed = new Set(list);
|
|
5901
|
+
column.enum = list;
|
|
5902
|
+
function validate(value) {
|
|
5903
|
+
if (value === undefined || value === null)
|
|
5904
|
+
return;
|
|
5905
|
+
if (!allowed.has(value)) {
|
|
5906
|
+
const formatted = list.map((v) => JSON.stringify(v)).join(', ');
|
|
5907
|
+
throw new Error(`Column ${column.alias} must be one of: ${formatted}`);
|
|
5908
|
+
}
|
|
5909
|
+
}
|
|
5910
|
+
return c.validate(validate);
|
|
5911
|
+
};
|
|
5912
|
+
|
|
5913
|
+
c.enum2 = function(...values) {
|
|
5914
|
+
const list = values.length === 1 && Array.isArray(values[0])
|
|
5915
|
+
? values[0]
|
|
5916
|
+
: values;
|
|
5917
|
+
return c.enum(list);
|
|
5918
|
+
};
|
|
5919
|
+
|
|
5820
5920
|
c.default = function(value) {
|
|
5821
5921
|
column.default = value;
|
|
5822
5922
|
return c;
|
|
@@ -5832,7 +5932,6 @@ function requireColumn () {
|
|
|
5832
5932
|
var oldAlias = column.alias;
|
|
5833
5933
|
table._aliases.delete(oldAlias);
|
|
5834
5934
|
table._aliases.add(alias);
|
|
5835
|
-
delete table[oldAlias];
|
|
5836
5935
|
table[alias] = column;
|
|
5837
5936
|
column.alias = alias;
|
|
5838
5937
|
return c;
|
|
@@ -9682,7 +9781,7 @@ function requireWhere$1 () {
|
|
|
9682
9781
|
|
|
9683
9782
|
try {
|
|
9684
9783
|
let arg = typeof fn === 'function' ? fn(table) : fn;
|
|
9685
|
-
let anyFilter = negotiateRawSqlFilter(context, arg);
|
|
9784
|
+
let anyFilter = negotiateRawSqlFilter(context, arg, table, true);
|
|
9686
9785
|
delete table._rootAlias;
|
|
9687
9786
|
return anyFilter;
|
|
9688
9787
|
}
|
|
@@ -12339,7 +12438,7 @@ function requireWhere () {
|
|
|
12339
12438
|
|
|
12340
12439
|
function where(context, fn) {
|
|
12341
12440
|
let arg = typeof fn === 'function' ? fn(table) : fn;
|
|
12342
|
-
return negotiateRawSqlFilter(context, arg);
|
|
12441
|
+
return negotiateRawSqlFilter(context, arg, table, true);
|
|
12343
12442
|
}
|
|
12344
12443
|
return where;
|
|
12345
12444
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -791,8 +791,10 @@ function requireStringify () {
|
|
|
791
791
|
}
|
|
792
792
|
|
|
793
793
|
function replacer(key, value) {
|
|
794
|
-
//
|
|
795
|
-
if (value
|
|
794
|
+
// @ts-ignore
|
|
795
|
+
if (typeof value === 'bigint')
|
|
796
|
+
return value.toString();
|
|
797
|
+
else if (value instanceof Date && !isNaN(value))
|
|
796
798
|
return dateToISOString(value);
|
|
797
799
|
else
|
|
798
800
|
return value;
|
|
@@ -902,6 +904,8 @@ function requireCreatePatch () {
|
|
|
902
904
|
}
|
|
903
905
|
return copy;
|
|
904
906
|
}
|
|
907
|
+
else if (typeof object === 'bigint')
|
|
908
|
+
return object.toString();
|
|
905
909
|
else if (isValidDate(object))
|
|
906
910
|
return dateToIsoString(object);
|
|
907
911
|
else if (object === Object(object)) {
|
|
@@ -1135,8 +1139,9 @@ function requireUtils () {
|
|
|
1135
1139
|
}
|
|
1136
1140
|
params.push(sql, filter.parameters);
|
|
1137
1141
|
}
|
|
1138
|
-
else if (isObjectFilter(filter, optionalTable))
|
|
1142
|
+
else if (isObjectFilter(filter, optionalTable)) {
|
|
1139
1143
|
return newObjectFilter(context, filter, optionalTable);
|
|
1144
|
+
}
|
|
1140
1145
|
else
|
|
1141
1146
|
params = [filter];
|
|
1142
1147
|
} else {
|
|
@@ -3092,6 +3097,14 @@ function requireClient () {
|
|
|
3092
3097
|
|
|
3093
3098
|
async function getMany(_, strategy) {
|
|
3094
3099
|
let metaPromise = getMeta();
|
|
3100
|
+
if (looksLikeFetchStrategy(_) && (strategy === undefined || !looksLikeFetchStrategy(strategy))) {
|
|
3101
|
+
let meta = await metaPromise;
|
|
3102
|
+
if (!isPrimaryKeyObject(meta, _)) {
|
|
3103
|
+
let _strategy = _;
|
|
3104
|
+
_ = strategy;
|
|
3105
|
+
strategy = _strategy;
|
|
3106
|
+
}
|
|
3107
|
+
}
|
|
3095
3108
|
strategy = extractFetchingStrategy({}, strategy);
|
|
3096
3109
|
let args = [_, strategy].concat(Array.prototype.slice.call(arguments).slice(2));
|
|
3097
3110
|
let rows = await getManyCore.apply(null, args);
|
|
@@ -3119,13 +3132,69 @@ function requireClient () {
|
|
|
3119
3132
|
return adapter.post(body);
|
|
3120
3133
|
}
|
|
3121
3134
|
|
|
3135
|
+
function isRawFilter(value) {
|
|
3136
|
+
return value && typeof value === 'object'
|
|
3137
|
+
&& (typeof value.sql === 'string' || typeof value.sql === 'function');
|
|
3138
|
+
}
|
|
3139
|
+
|
|
3140
|
+
function looksLikeFetchStrategy(value) {
|
|
3141
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
3142
|
+
return false;
|
|
3143
|
+
if (isRawFilter(value))
|
|
3144
|
+
return false;
|
|
3145
|
+
if (Object.keys(value).length === 0)
|
|
3146
|
+
return true;
|
|
3147
|
+
if ('where' in value || 'orderBy' in value || 'limit' in value || 'offset' in value)
|
|
3148
|
+
return true;
|
|
3149
|
+
for (let key in value) {
|
|
3150
|
+
const v = value[key];
|
|
3151
|
+
if (typeof v === 'boolean')
|
|
3152
|
+
return true;
|
|
3153
|
+
if (v && typeof v === 'object' && !Array.isArray(v))
|
|
3154
|
+
return true;
|
|
3155
|
+
}
|
|
3156
|
+
return false;
|
|
3157
|
+
}
|
|
3158
|
+
|
|
3159
|
+
function isPrimaryKeyObject(meta, value) {
|
|
3160
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
3161
|
+
return false;
|
|
3162
|
+
if (isRawFilter(value))
|
|
3163
|
+
return false;
|
|
3164
|
+
const keyNames = meta?.keys?.map(key => key.name);
|
|
3165
|
+
if (!keyNames || keyNames.length === 0)
|
|
3166
|
+
return false;
|
|
3167
|
+
const keys = Object.keys(value);
|
|
3168
|
+
if (keys.length === 0)
|
|
3169
|
+
return false;
|
|
3170
|
+
for (let i = 0; i < keys.length; i++) {
|
|
3171
|
+
const key = keys[i];
|
|
3172
|
+
if (!keyNames.includes(key))
|
|
3173
|
+
return false;
|
|
3174
|
+
const val = value[key];
|
|
3175
|
+
if (val && typeof val === 'object' && !(val instanceof Date))
|
|
3176
|
+
return false;
|
|
3177
|
+
}
|
|
3178
|
+
return true;
|
|
3179
|
+
}
|
|
3180
|
+
|
|
3181
|
+
function normalizeGetOneArgs(meta, filter, strategy) {
|
|
3182
|
+
if (looksLikeFetchStrategy(filter) && (strategy === undefined || !looksLikeFetchStrategy(strategy))) {
|
|
3183
|
+
if (!isPrimaryKeyObject(meta, filter))
|
|
3184
|
+
return { filter: strategy, strategy: filter };
|
|
3185
|
+
}
|
|
3186
|
+
return { filter, strategy };
|
|
3187
|
+
}
|
|
3188
|
+
|
|
3122
3189
|
async function getOne(filter, strategy) {
|
|
3123
3190
|
let metaPromise = getMeta();
|
|
3124
|
-
|
|
3191
|
+
let meta = await metaPromise;
|
|
3192
|
+
let normalized = normalizeGetOneArgs(meta, filter, strategy);
|
|
3193
|
+
filter = normalized.filter;
|
|
3194
|
+
strategy = extractFetchingStrategy({}, normalized.strategy);
|
|
3125
3195
|
let _strategy = { ...strategy, ...{ limit: 1 } };
|
|
3126
3196
|
let args = [filter, _strategy].concat(Array.prototype.slice.call(arguments).slice(2));
|
|
3127
3197
|
let rows = await getManyCore.apply(null, args);
|
|
3128
|
-
await metaPromise;
|
|
3129
3198
|
if (rows.length === 0)
|
|
3130
3199
|
return;
|
|
3131
3200
|
return proxify(rows[0], strategy, true);
|
|
@@ -5818,6 +5887,37 @@ function requireColumn () {
|
|
|
5818
5887
|
return c;
|
|
5819
5888
|
};
|
|
5820
5889
|
|
|
5890
|
+
c.enum = function(values) {
|
|
5891
|
+
let list = values;
|
|
5892
|
+
if (Array.isArray(values))
|
|
5893
|
+
list = values;
|
|
5894
|
+
else if (values && typeof values === 'object') {
|
|
5895
|
+
const keys = Object.keys(values);
|
|
5896
|
+
const nonNumericKeys = keys.filter((key) => !/^-?\d+$/.test(key));
|
|
5897
|
+
list = (nonNumericKeys.length ? nonNumericKeys : keys).map((key) => values[key]);
|
|
5898
|
+
}
|
|
5899
|
+
else
|
|
5900
|
+
throw new Error('enum values must be an array');
|
|
5901
|
+
const allowed = new Set(list);
|
|
5902
|
+
column.enum = list;
|
|
5903
|
+
function validate(value) {
|
|
5904
|
+
if (value === undefined || value === null)
|
|
5905
|
+
return;
|
|
5906
|
+
if (!allowed.has(value)) {
|
|
5907
|
+
const formatted = list.map((v) => JSON.stringify(v)).join(', ');
|
|
5908
|
+
throw new Error(`Column ${column.alias} must be one of: ${formatted}`);
|
|
5909
|
+
}
|
|
5910
|
+
}
|
|
5911
|
+
return c.validate(validate);
|
|
5912
|
+
};
|
|
5913
|
+
|
|
5914
|
+
c.enum2 = function(...values) {
|
|
5915
|
+
const list = values.length === 1 && Array.isArray(values[0])
|
|
5916
|
+
? values[0]
|
|
5917
|
+
: values;
|
|
5918
|
+
return c.enum(list);
|
|
5919
|
+
};
|
|
5920
|
+
|
|
5821
5921
|
c.default = function(value) {
|
|
5822
5922
|
column.default = value;
|
|
5823
5923
|
return c;
|
|
@@ -5833,7 +5933,6 @@ function requireColumn () {
|
|
|
5833
5933
|
var oldAlias = column.alias;
|
|
5834
5934
|
table._aliases.delete(oldAlias);
|
|
5835
5935
|
table._aliases.add(alias);
|
|
5836
|
-
delete table[oldAlias];
|
|
5837
5936
|
table[alias] = column;
|
|
5838
5937
|
column.alias = alias;
|
|
5839
5938
|
return c;
|
|
@@ -9683,7 +9782,7 @@ function requireWhere$1 () {
|
|
|
9683
9782
|
|
|
9684
9783
|
try {
|
|
9685
9784
|
let arg = typeof fn === 'function' ? fn(table) : fn;
|
|
9686
|
-
let anyFilter = negotiateRawSqlFilter(context, arg);
|
|
9785
|
+
let anyFilter = negotiateRawSqlFilter(context, arg, table, true);
|
|
9687
9786
|
delete table._rootAlias;
|
|
9688
9787
|
return anyFilter;
|
|
9689
9788
|
}
|
|
@@ -12340,7 +12439,7 @@ function requireWhere () {
|
|
|
12340
12439
|
|
|
12341
12440
|
function where(context, fn) {
|
|
12342
12441
|
let arg = typeof fn === 'function' ? fn(table) : fn;
|
|
12343
|
-
return negotiateRawSqlFilter(context, arg);
|
|
12442
|
+
return negotiateRawSqlFilter(context, arg, table, true);
|
|
12344
12443
|
}
|
|
12345
12444
|
return where;
|
|
12346
12445
|
}
|
|
@@ -17753,7 +17852,6 @@ function requireNewDatabase$7 () {
|
|
|
17753
17852
|
};
|
|
17754
17853
|
|
|
17755
17854
|
c.createTransaction = function(options) {
|
|
17756
|
-
console.dir('create transaction');
|
|
17757
17855
|
let domain = createDomain();
|
|
17758
17856
|
let transaction = newTransaction(domain, pool);
|
|
17759
17857
|
let p = domain.run(() => new Promise(transaction).then(begin));
|
package/package.json
CHANGED
|
@@ -90,6 +90,8 @@ module.exports = function createPatch(original, dto, options) {
|
|
|
90
90
|
}
|
|
91
91
|
return copy;
|
|
92
92
|
}
|
|
93
|
+
else if (typeof object === 'bigint')
|
|
94
|
+
return object.toString();
|
|
93
95
|
else if (isValidDate(object))
|
|
94
96
|
return dateToIsoString(object);
|
|
95
97
|
else if (object === Object(object)) {
|
package/src/client/index.js
CHANGED
|
@@ -242,6 +242,14 @@ function rdbClient(options = {}) {
|
|
|
242
242
|
|
|
243
243
|
async function getMany(_, strategy) {
|
|
244
244
|
let metaPromise = getMeta();
|
|
245
|
+
if (looksLikeFetchStrategy(_) && (strategy === undefined || !looksLikeFetchStrategy(strategy))) {
|
|
246
|
+
let meta = await metaPromise;
|
|
247
|
+
if (!isPrimaryKeyObject(meta, _)) {
|
|
248
|
+
let _strategy = _;
|
|
249
|
+
_ = strategy;
|
|
250
|
+
strategy = _strategy;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
245
253
|
strategy = extractFetchingStrategy({}, strategy);
|
|
246
254
|
let args = [_, strategy].concat(Array.prototype.slice.call(arguments).slice(2));
|
|
247
255
|
let rows = await getManyCore.apply(null, args);
|
|
@@ -269,13 +277,69 @@ function rdbClient(options = {}) {
|
|
|
269
277
|
return adapter.post(body);
|
|
270
278
|
}
|
|
271
279
|
|
|
280
|
+
function isRawFilter(value) {
|
|
281
|
+
return value && typeof value === 'object'
|
|
282
|
+
&& (typeof value.sql === 'string' || typeof value.sql === 'function');
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function looksLikeFetchStrategy(value) {
|
|
286
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
287
|
+
return false;
|
|
288
|
+
if (isRawFilter(value))
|
|
289
|
+
return false;
|
|
290
|
+
if (Object.keys(value).length === 0)
|
|
291
|
+
return true;
|
|
292
|
+
if ('where' in value || 'orderBy' in value || 'limit' in value || 'offset' in value)
|
|
293
|
+
return true;
|
|
294
|
+
for (let key in value) {
|
|
295
|
+
const v = value[key];
|
|
296
|
+
if (typeof v === 'boolean')
|
|
297
|
+
return true;
|
|
298
|
+
if (v && typeof v === 'object' && !Array.isArray(v))
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function isPrimaryKeyObject(meta, value) {
|
|
305
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
306
|
+
return false;
|
|
307
|
+
if (isRawFilter(value))
|
|
308
|
+
return false;
|
|
309
|
+
const keyNames = meta?.keys?.map(key => key.name);
|
|
310
|
+
if (!keyNames || keyNames.length === 0)
|
|
311
|
+
return false;
|
|
312
|
+
const keys = Object.keys(value);
|
|
313
|
+
if (keys.length === 0)
|
|
314
|
+
return false;
|
|
315
|
+
for (let i = 0; i < keys.length; i++) {
|
|
316
|
+
const key = keys[i];
|
|
317
|
+
if (!keyNames.includes(key))
|
|
318
|
+
return false;
|
|
319
|
+
const val = value[key];
|
|
320
|
+
if (val && typeof val === 'object' && !(val instanceof Date))
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
return true;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function normalizeGetOneArgs(meta, filter, strategy) {
|
|
327
|
+
if (looksLikeFetchStrategy(filter) && (strategy === undefined || !looksLikeFetchStrategy(strategy))) {
|
|
328
|
+
if (!isPrimaryKeyObject(meta, filter))
|
|
329
|
+
return { filter: strategy, strategy: filter };
|
|
330
|
+
}
|
|
331
|
+
return { filter, strategy };
|
|
332
|
+
}
|
|
333
|
+
|
|
272
334
|
async function getOne(filter, strategy) {
|
|
273
335
|
let metaPromise = getMeta();
|
|
274
|
-
|
|
336
|
+
let meta = await metaPromise;
|
|
337
|
+
let normalized = normalizeGetOneArgs(meta, filter, strategy);
|
|
338
|
+
filter = normalized.filter;
|
|
339
|
+
strategy = extractFetchingStrategy({}, normalized.strategy);
|
|
275
340
|
let _strategy = { ...strategy, ...{ limit: 1 } };
|
|
276
341
|
let args = [filter, _strategy].concat(Array.prototype.slice.call(arguments).slice(2));
|
|
277
342
|
let rows = await getManyCore.apply(null, args);
|
|
278
|
-
await metaPromise;
|
|
279
343
|
if (rows.length === 0)
|
|
280
344
|
return;
|
|
281
345
|
return proxify(rows[0], strategy, true);
|
package/src/client/stringify.js
CHANGED
|
@@ -5,11 +5,13 @@ function stringify(value) {
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
function replacer(key, value) {
|
|
8
|
-
//
|
|
9
|
-
if (value
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
if (typeof value === 'bigint')
|
|
10
|
+
return value.toString();
|
|
11
|
+
else if (value instanceof Date && !isNaN(value))
|
|
10
12
|
return dateToISOString(value);
|
|
11
13
|
else
|
|
12
14
|
return value;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
module.exports = stringify;
|
|
17
|
+
module.exports = stringify;
|
package/src/map.d.ts
CHANGED
|
@@ -96,7 +96,9 @@ type ReturnArrayOrObj<W, V1, V2> =
|
|
|
96
96
|
V1;
|
|
97
97
|
|
|
98
98
|
|
|
99
|
-
type ColumnToType<T> = T extends
|
|
99
|
+
type ColumnToType<T> = T extends EnumOf<infer E>
|
|
100
|
+
? E
|
|
101
|
+
: T extends UuidColumnSymbol
|
|
100
102
|
? string
|
|
101
103
|
: T extends StringColumnSymbol
|
|
102
104
|
? string
|
|
@@ -625,6 +627,10 @@ type NotNullExceptInsert = {
|
|
|
625
627
|
[' notNullExceptInsert']: boolean;
|
|
626
628
|
};
|
|
627
629
|
|
|
630
|
+
type EnumOf<T> = {
|
|
631
|
+
[' enum']: T;
|
|
632
|
+
};
|
|
633
|
+
|
|
628
634
|
type JsonOf<T> = {
|
|
629
635
|
[' isjsonOf']: boolean;
|
|
630
636
|
type: T;
|
|
@@ -734,6 +740,11 @@ type DateWithTimeZoneValidator<M> = M extends NotNull
|
|
|
734
740
|
};
|
|
735
741
|
|
|
736
742
|
type StringColumnTypeDef<M> = StringValidator<M> & {
|
|
743
|
+
enum<const V extends readonly string[]>(values: V): StringColumnTypeDef<M & EnumOf<V[number]>> & EnumOf<V[number]>;
|
|
744
|
+
enum<const V extends Record<string, string>>(values: V): StringColumnTypeDef<M & EnumOf<V[keyof V]>> & EnumOf<V[keyof V]>;
|
|
745
|
+
enum<TEnum>(values: Record<string, TEnum>): StringColumnTypeDef<M & EnumOf<TEnum>> & EnumOf<TEnum>;
|
|
746
|
+
enum<E extends string>(values: readonly E[]): StringColumnTypeDef<M & EnumOf<E>> & EnumOf<E>;
|
|
747
|
+
enum<E, V extends Record<string, E>>(values: V): StringColumnTypeDef<M & EnumOf<V[keyof V]>> & EnumOf<V[keyof V]>;
|
|
737
748
|
primary(): StringColumnTypeDef<M & IsPrimary> & IsPrimary;
|
|
738
749
|
notNull(): StringColumnTypeDef<M & NotNull> & NotNull;
|
|
739
750
|
notNullExceptInsert(): StringColumnTypeDef<M & NotNull & NotNullExceptInsert> & NotNull & NotNullExceptInsert;
|
|
@@ -745,6 +756,10 @@ type StringColumnTypeDef<M> = StringValidator<M> & {
|
|
|
745
756
|
M;
|
|
746
757
|
|
|
747
758
|
type NumericColumnTypeDef<M> = NumericValidator<M> & {
|
|
759
|
+
enum<const V extends Record<string, number>>(values: V): NumericColumnTypeDef<M & EnumOf<V[keyof V]>> & EnumOf<V[keyof V]>;
|
|
760
|
+
enum<TEnum>(values: Record<string, TEnum>): NumericColumnTypeDef<M & EnumOf<TEnum>> & EnumOf<TEnum>;
|
|
761
|
+
enum<E extends number>(values: readonly E[]): NumericColumnTypeDef<M & EnumOf<E>> & EnumOf<E>;
|
|
762
|
+
enum<E, V extends Record<string, E>>(values: V): NumericColumnTypeDef<M & EnumOf<V[keyof V]>> & EnumOf<V[keyof V]>;
|
|
748
763
|
primary(): NumericColumnTypeDef<M & IsPrimary> & IsPrimary;
|
|
749
764
|
notNull(): NumericColumnTypeDef<M & NotNull> & NotNull;
|
|
750
765
|
notNullExceptInsert(): NumericColumnTypeDef<M & NotNull & NotNullExceptInsert> & NotNull & NotNullExceptInsert;
|
|
@@ -756,6 +771,10 @@ type NumericColumnTypeDef<M> = NumericValidator<M> & {
|
|
|
756
771
|
M;
|
|
757
772
|
|
|
758
773
|
type BigIntColumnTypeDef<M> = BigIntValidator<M> & {
|
|
774
|
+
enum<const V extends Record<string, bigint>>(values: V): BigIntColumnTypeDef<M & EnumOf<V[keyof V]>> & EnumOf<V[keyof V]>;
|
|
775
|
+
enum<TEnum>(values: Record<string, TEnum>): BigIntColumnTypeDef<M & EnumOf<TEnum>> & EnumOf<TEnum>;
|
|
776
|
+
enum<E extends bigint>(values: readonly E[]): BigIntColumnTypeDef<M & EnumOf<E>> & EnumOf<E>;
|
|
777
|
+
enum<E, V extends Record<string, E>>(values: V): BigIntColumnTypeDef<M & EnumOf<V[keyof V]>> & EnumOf<V[keyof V]>;
|
|
759
778
|
primary(): BigIntColumnTypeDef<M & IsPrimary> & IsPrimary;
|
|
760
779
|
notNull(): BigIntColumnTypeDef<M & NotNull> & NotNull;
|
|
761
780
|
notNullExceptInsert(): BigIntColumnTypeDef<M & NotNull & NotNullExceptInsert> & NotNull & NotNullExceptInsert;
|
|
@@ -767,6 +786,10 @@ type BigIntColumnTypeDef<M> = BigIntValidator<M> & {
|
|
|
767
786
|
M;
|
|
768
787
|
|
|
769
788
|
type UuidColumnTypeDef<M> = UuidValidator<M> & {
|
|
789
|
+
enum<const V extends Record<string, string>>(values: V): UuidColumnTypeDef<M & EnumOf<V[keyof V]>> & EnumOf<V[keyof V]>;
|
|
790
|
+
enum<TEnum>(values: Record<string, TEnum>): UuidColumnTypeDef<M & EnumOf<TEnum>> & EnumOf<TEnum>;
|
|
791
|
+
enum<E extends string>(values: readonly E[]): UuidColumnTypeDef<M & EnumOf<E>> & EnumOf<E>;
|
|
792
|
+
enum<E, V extends Record<string, E>>(values: V): UuidColumnTypeDef<M & EnumOf<V[keyof V]>> & EnumOf<V[keyof V]>;
|
|
770
793
|
primary(): UuidColumnTypeDef<M & IsPrimary> & IsPrimary;
|
|
771
794
|
notNull(): UuidColumnTypeDef<M & NotNull> & NotNull;
|
|
772
795
|
notNullExceptInsert(): UuidColumnTypeDef<M & NotNull & NotNullExceptInsert> & NotNull & NotNullExceptInsert;
|
|
@@ -789,6 +812,10 @@ type JSONColumnTypeDef<M> = JSONValidator<M> & {
|
|
|
789
812
|
M;
|
|
790
813
|
|
|
791
814
|
type BinaryColumnTypeDef<M> = BinaryValidator<M> & {
|
|
815
|
+
enum<const V extends Record<string, string>>(values: V): BinaryColumnTypeDef<M & EnumOf<V[keyof V]>> & EnumOf<V[keyof V]>;
|
|
816
|
+
enum<TEnum>(values: Record<string, TEnum>): BinaryColumnTypeDef<M & EnumOf<TEnum>> & EnumOf<TEnum>;
|
|
817
|
+
enum<E extends string>(values: readonly E[]): BinaryColumnTypeDef<M & EnumOf<E>> & EnumOf<E>;
|
|
818
|
+
enum<E, V extends Record<string, E>>(values: V): BinaryColumnTypeDef<M & EnumOf<V[keyof V]>> & EnumOf<V[keyof V]>;
|
|
792
819
|
primary(): BinaryColumnTypeDef<M & IsPrimary> & IsPrimary;
|
|
793
820
|
notNull(): BinaryColumnTypeDef<M & NotNull> & NotNull;
|
|
794
821
|
notNullExceptInsert(): BinaryColumnTypeDef<M & NotNull & NotNullExceptInsert> & NotNull & NotNullExceptInsert;
|
|
@@ -800,6 +827,10 @@ type BinaryColumnTypeDef<M> = BinaryValidator<M> & {
|
|
|
800
827
|
M;
|
|
801
828
|
|
|
802
829
|
type BooleanColumnTypeDef<M> = BooleanValidator<M> & {
|
|
830
|
+
enum<const V extends Record<string, boolean>>(values: V): BooleanColumnTypeDef<M & EnumOf<V[keyof V]>> & EnumOf<V[keyof V]>;
|
|
831
|
+
enum<TEnum>(values: Record<string, TEnum>): BooleanColumnTypeDef<M & EnumOf<TEnum>> & EnumOf<TEnum>;
|
|
832
|
+
enum<E extends boolean>(values: readonly E[]): BooleanColumnTypeDef<M & EnumOf<E>> & EnumOf<E>;
|
|
833
|
+
enum<E, V extends Record<string, E>>(values: V): BooleanColumnTypeDef<M & EnumOf<V[keyof V]>> & EnumOf<V[keyof V]>;
|
|
803
834
|
primary(): BooleanColumnTypeDef<M & IsPrimary> & IsPrimary;
|
|
804
835
|
notNull(): BooleanColumnTypeDef<M & NotNull> & NotNull;
|
|
805
836
|
notNullExceptInsert(): BooleanColumnTypeDef<M & NotNull & NotNullExceptInsert> & NotNull & NotNullExceptInsert;
|
|
@@ -811,6 +842,10 @@ type BooleanColumnTypeDef<M> = BooleanValidator<M> & {
|
|
|
811
842
|
M;
|
|
812
843
|
|
|
813
844
|
type DateColumnTypeDef<M> = DateValidator<M> & {
|
|
845
|
+
enum<const V extends Record<string, string | Date>>(values: V): DateColumnTypeDef<M & EnumOf<V[keyof V]>> & EnumOf<V[keyof V]>;
|
|
846
|
+
enum<TEnum>(values: Record<string, TEnum>): DateColumnTypeDef<M & EnumOf<TEnum>> & EnumOf<TEnum>;
|
|
847
|
+
enum<E extends string | Date>(values: readonly E[]): DateColumnTypeDef<M & EnumOf<E>> & EnumOf<E>;
|
|
848
|
+
enum<E, V extends Record<string, E>>(values: V): DateColumnTypeDef<M & EnumOf<V[keyof V]>> & EnumOf<V[keyof V]>;
|
|
814
849
|
primary(): DateColumnTypeDef<M & IsPrimary> & IsPrimary;
|
|
815
850
|
notNull(): DateColumnTypeDef<M & NotNull> & NotNull;
|
|
816
851
|
notNullExceptInsert(): DateColumnTypeDef<M & NotNull & NotNullExceptInsert> & NotNull & NotNullExceptInsert;
|
|
@@ -822,6 +857,10 @@ type DateColumnTypeDef<M> = DateValidator<M> & {
|
|
|
822
857
|
M;
|
|
823
858
|
|
|
824
859
|
type DateWithTimeZoneColumnTypeDef<M> = DateValidator<M> & {
|
|
860
|
+
enum<const V extends Record<string, string | Date>>(values: V): DateWithTimeZoneColumnTypeDef<M & EnumOf<V[keyof V]>> & EnumOf<V[keyof V]>;
|
|
861
|
+
enum<TEnum>(values: Record<string, TEnum>): DateWithTimeZoneColumnTypeDef<M & EnumOf<TEnum>> & EnumOf<TEnum>;
|
|
862
|
+
enum<E extends string | Date>(values: readonly E[]): DateWithTimeZoneColumnTypeDef<M & EnumOf<E>> & EnumOf<E>;
|
|
863
|
+
enum<E, V extends Record<string, E>>(values: V): DateWithTimeZoneColumnTypeDef<M & EnumOf<V[keyof V]>> & EnumOf<V[keyof V]>;
|
|
825
864
|
primary(): DateWithTimeZoneColumnTypeDef<M & IsPrimary> & IsPrimary;
|
|
826
865
|
notNull(): DateWithTimeZoneColumnTypeDef<M & NotNull> & NotNull;
|
|
827
866
|
notNullExceptInsert(): DateWithTimeZoneColumnTypeDef<M & NotNull & NotNullExceptInsert> & NotNull & NotNullExceptInsert;
|
|
@@ -1000,7 +1039,9 @@ type ExtractPrimaryKeyNames<T> =
|
|
|
1000
1039
|
type RelationTarget<T> =
|
|
1001
1040
|
T extends { __tableAlias: infer S } ? Extract<S, string> : string;
|
|
1002
1041
|
|
|
1003
|
-
type
|
|
1042
|
+
type EnumSchema<T> = T extends EnumOf<infer E> ? { ' enum': readonly E[] } : {};
|
|
1043
|
+
|
|
1044
|
+
type ColumnToSchemaType<T> = (
|
|
1004
1045
|
T extends JsonOf<infer U>
|
|
1005
1046
|
? { ' type': 'json'; ' tsType': U }
|
|
1006
1047
|
& (T extends NotNullExceptInsert ? { ' notNull': true; ' notNullExceptInsert': true }
|
|
@@ -1046,7 +1087,8 @@ type ColumnToSchemaType<T> =
|
|
|
1046
1087
|
& (T extends NotNullExceptInsert ? { ' notNull': true; ' notNullExceptInsert': true }
|
|
1047
1088
|
: T extends NotNull ? { ' notNull': true }
|
|
1048
1089
|
: {}) :
|
|
1049
|
-
never
|
|
1090
|
+
never
|
|
1091
|
+
) & EnumSchema<T>;
|
|
1050
1092
|
|
|
1051
1093
|
export type MappedDbDef<T> = {
|
|
1052
1094
|
map<V extends AllowedDbMap<V>>(
|
|
@@ -1059,4 +1101,4 @@ export type MappedDbDef<T> = {
|
|
|
1059
1101
|
* Usage: type Schema = ReturnType<typeof db.toSchema>
|
|
1060
1102
|
*/
|
|
1061
1103
|
toSchema: <U = T>() => SchemaFromMappedDb<U>;
|
|
1062
|
-
} & T & DbConnectable<T>;
|
|
1104
|
+
} & T & DbConnectable<T>;
|
package/src/map2.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export type ORMColumnType = 'string' | 'bigint' | 'uuid' | 'date' | 'numeric' |
|
|
|
10
10
|
// Base column definition with space-prefixed required properties
|
|
11
11
|
export type ORMColumnDefinition = {
|
|
12
12
|
' type': ORMColumnType;
|
|
13
|
+
' enum'?: readonly (string | number | boolean | Date)[] | Record<string, string | number | boolean | Date>;
|
|
13
14
|
' notNull'?: boolean;
|
|
14
15
|
' notNullExceptInsert'?: boolean;
|
|
15
16
|
};
|
|
@@ -24,7 +25,7 @@ export type ORMJsonColumnDefinition<T = any> = {
|
|
|
24
25
|
|
|
25
26
|
type NormalizeColumn<T> =
|
|
26
27
|
T extends ORMColumnType
|
|
27
|
-
? { ' type': T; ' notNull'?: boolean; ' notNullExceptInsert'?: boolean }
|
|
28
|
+
? { ' type': T; ' enum'?: readonly (string | number | boolean | Date)[] | Record<string, string | number | boolean | Date>; ' notNull'?: boolean; ' notNullExceptInsert'?: boolean }
|
|
28
29
|
: T extends { ' type': ORMColumnType }
|
|
29
30
|
? { ' notNull'?: boolean; ' notNullExceptInsert'?: boolean } & T
|
|
30
31
|
: T extends { ' type': 'json'; ' tsType': any }
|
|
@@ -41,6 +42,8 @@ type IsRequiredInsert<CT> =
|
|
|
41
42
|
: false; // Otherwise, it's optional
|
|
42
43
|
|
|
43
44
|
type ColumnTypeToTS<CT> =
|
|
45
|
+
NormalizeColumn<CT> extends { ' enum': readonly (infer E)[] } ? E :
|
|
46
|
+
NormalizeColumn<CT> extends { ' enum': Record<string, infer E> } ? E :
|
|
44
47
|
NormalizeColumn<CT>[' type'] extends 'numeric' ? number :
|
|
45
48
|
NormalizeColumn<CT>[' type'] extends 'boolean' ? boolean :
|
|
46
49
|
NormalizeColumn<CT>[' type'] extends 'json'
|
|
@@ -674,41 +677,33 @@ type AggregateCustomSelectorProperties<M extends Record<string, TableDefinition<
|
|
|
674
677
|
|
|
675
678
|
export type TableClient<M extends Record<string, TableDefinition<M>>, K extends keyof M> = {
|
|
676
679
|
// Array methods - return arrays with array-level active record methods, but individual items are plain
|
|
677
|
-
|
|
678
|
-
getAll<strategy extends FetchStrategy<M, K>>(strategy: strategy): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, strategy>>>, M, K>>;
|
|
679
|
-
getMany(filter?: RawFilter | Array<PrimaryKeyObject<M, K>>): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, {}>>>, M, K>>;
|
|
680
|
-
getMany<strategy extends FetchStrategy<M, K>>(filter?: RawFilter | Array<PrimaryKeyObject<M, K>>, strategy?: strategy): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, strategy>>>, M, K>>;
|
|
680
|
+
getMany<strategy extends FetchStrategy<M, K>>(strategy?: strategy): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, strategy>>>, M, K>>;
|
|
681
681
|
|
|
682
682
|
// Aggregate methods - return plain objects (no active record methods)
|
|
683
683
|
aggregate<strategy extends AggregateStrategy<M, K>>(strategy: strategy): Promise<Array<DeepExpand<AggregateCustomSelectorProperties<M, K, strategy>>>>;
|
|
684
684
|
|
|
685
685
|
// Single item methods - return individual objects with individual active record methods
|
|
686
|
-
getOne<strategy extends FetchStrategy<M, K
|
|
687
|
-
filter?: RawFilter | Array<PrimaryKeyObject<M, K>>
|
|
688
|
-
): Promise<WithActiveRecord<DeepExpand<Selection<M, K, strategy>>, M, K>>;
|
|
689
|
-
|
|
690
|
-
getOne<strategy extends FetchStrategy<M, K>>(
|
|
691
|
-
filter?: RawFilter | Array<PrimaryKeyObject<M, K>>,
|
|
686
|
+
getOne<strategy extends FetchStrategy<M, K> = {}>(
|
|
692
687
|
strategy?: strategy
|
|
693
|
-
): Promise<WithActiveRecord<DeepExpand<Selection<M, K, strategy>>, M, K
|
|
688
|
+
): Promise<WithActiveRecord<DeepExpand<Selection<M, K, strategy>>, M, K> | undefined>;
|
|
694
689
|
|
|
695
690
|
getById<strategy extends FetchStrategy<M, K>>(
|
|
696
691
|
...args: [...PrimaryKeyArgs<M, K>, strategy: strategy]
|
|
697
|
-
): Promise<WithActiveRecord<DeepExpand<Selection<M, K, strategy>>, M, K
|
|
692
|
+
): Promise<WithActiveRecord<DeepExpand<Selection<M, K, strategy>>, M, K> | undefined>;
|
|
698
693
|
|
|
699
694
|
getById(
|
|
700
695
|
...args: [...PrimaryKeyArgs<M, K>]
|
|
701
|
-
): Promise<WithActiveRecord<DeepExpand<Selection<M, K, {}>>, M, K
|
|
696
|
+
): Promise<WithActiveRecord<DeepExpand<Selection<M, K, {}>>, M, K> | undefined>;
|
|
702
697
|
|
|
703
698
|
// UPDATED: Bulk update methods with relations support
|
|
704
699
|
update(
|
|
705
700
|
row: UpdateRowWithRelations<M, K>,
|
|
706
|
-
opts: { where: (row: RootTableRefs<M, K>) => RawFilter }
|
|
701
|
+
opts: { where: (row: RootTableRefs<M, K>) => RawFilter | Array<PrimaryKeyObject<M, K>> }
|
|
707
702
|
): Promise<void>;
|
|
708
703
|
|
|
709
704
|
update<strategy extends FetchStrategy<M, K>>(
|
|
710
705
|
row: UpdateRowWithRelations<M, K>,
|
|
711
|
-
opts: { where: (row: RootTableRefs<M, K>) => RawFilter },
|
|
706
|
+
opts: { where: (row: RootTableRefs<M, K>) => RawFilter | Array<PrimaryKeyObject<M, K>> },
|
|
712
707
|
strategy: strategy
|
|
713
708
|
): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, strategy>>>, M, K>>;
|
|
714
709
|
|
|
@@ -48,7 +48,6 @@ function newDatabase(connectionString, poolOptions) {
|
|
|
48
48
|
};
|
|
49
49
|
|
|
50
50
|
c.createTransaction = function(options) {
|
|
51
|
-
console.dir('create transaction');
|
|
52
51
|
let domain = createDomain();
|
|
53
52
|
let transaction = newTransaction(domain, pool);
|
|
54
53
|
let p = domain.run(() => new Promise(transaction).then(begin));
|
|
@@ -80,8 +80,9 @@ function negotiateRawSqlFilter(context, filter, optionalTable, emptyArrayMeansFa
|
|
|
80
80
|
}
|
|
81
81
|
params.push(sql, filter.parameters);
|
|
82
82
|
}
|
|
83
|
-
else if (isObjectFilter(filter, optionalTable))
|
|
83
|
+
else if (isObjectFilter(filter, optionalTable)) {
|
|
84
84
|
return newObjectFilter(context, filter, optionalTable);
|
|
85
|
+
}
|
|
85
86
|
else
|
|
86
87
|
params = [filter];
|
|
87
88
|
} else {
|
|
@@ -110,4 +111,4 @@ function newObjectFilter(context, object, table) {
|
|
|
110
111
|
}
|
|
111
112
|
|
|
112
113
|
|
|
113
|
-
module.exports = { negotiateRawSqlFilter, newBoolean};
|
|
114
|
+
module.exports = { negotiateRawSqlFilter, newBoolean};
|
package/src/table/column.js
CHANGED
|
@@ -54,6 +54,37 @@ function defineColumn(column, table) {
|
|
|
54
54
|
return c;
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
+
c.enum = function(values) {
|
|
58
|
+
let list = values;
|
|
59
|
+
if (Array.isArray(values))
|
|
60
|
+
list = values;
|
|
61
|
+
else if (values && typeof values === 'object') {
|
|
62
|
+
const keys = Object.keys(values);
|
|
63
|
+
const nonNumericKeys = keys.filter((key) => !/^-?\d+$/.test(key));
|
|
64
|
+
list = (nonNumericKeys.length ? nonNumericKeys : keys).map((key) => values[key]);
|
|
65
|
+
}
|
|
66
|
+
else
|
|
67
|
+
throw new Error('enum values must be an array');
|
|
68
|
+
const allowed = new Set(list);
|
|
69
|
+
column.enum = list;
|
|
70
|
+
function validate(value) {
|
|
71
|
+
if (value === undefined || value === null)
|
|
72
|
+
return;
|
|
73
|
+
if (!allowed.has(value)) {
|
|
74
|
+
const formatted = list.map((v) => JSON.stringify(v)).join(', ');
|
|
75
|
+
throw new Error(`Column ${column.alias} must be one of: ${formatted}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return c.validate(validate);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
c.enum2 = function(...values) {
|
|
82
|
+
const list = values.length === 1 && Array.isArray(values[0])
|
|
83
|
+
? values[0]
|
|
84
|
+
: values;
|
|
85
|
+
return c.enum(list);
|
|
86
|
+
};
|
|
87
|
+
|
|
57
88
|
c.default = function(value) {
|
|
58
89
|
column.default = value;
|
|
59
90
|
return c;
|
|
@@ -69,7 +100,6 @@ function defineColumn(column, table) {
|
|
|
69
100
|
var oldAlias = column.alias;
|
|
70
101
|
table._aliases.delete(oldAlias);
|
|
71
102
|
table._aliases.add(alias);
|
|
72
|
-
delete table[oldAlias];
|
|
73
103
|
table[alias] = column;
|
|
74
104
|
column.alias = alias;
|
|
75
105
|
return c;
|
|
@@ -160,4 +190,4 @@ function inspect(obj) {
|
|
|
160
190
|
}
|
|
161
191
|
|
|
162
192
|
|
|
163
|
-
module.exports = defineColumn;
|
|
193
|
+
module.exports = defineColumn;
|
|
@@ -11,7 +11,7 @@ function newWhere(_relations, _depth) {
|
|
|
11
11
|
|
|
12
12
|
try {
|
|
13
13
|
let arg = typeof fn === 'function' ? fn(table) : fn;
|
|
14
|
-
let anyFilter = negotiateRawSqlFilter(context, arg);
|
|
14
|
+
let anyFilter = negotiateRawSqlFilter(context, arg, table, true);
|
|
15
15
|
delete table._rootAlias;
|
|
16
16
|
return anyFilter;
|
|
17
17
|
}
|
|
@@ -40,4 +40,4 @@ function newWhere(_relations, _depth) {
|
|
|
40
40
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
module.exports = newWhere;
|
|
43
|
+
module.exports = newWhere;
|
package/src/table/where.js
CHANGED
|
@@ -4,9 +4,9 @@ function newWhere(table) {
|
|
|
4
4
|
|
|
5
5
|
function where(context, fn) {
|
|
6
6
|
let arg = typeof fn === 'function' ? fn(table) : fn;
|
|
7
|
-
return negotiateRawSqlFilter(context, arg);
|
|
7
|
+
return negotiateRawSqlFilter(context, arg, table, true);
|
|
8
8
|
}
|
|
9
9
|
return where;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
module.exports = newWhere;
|
|
12
|
+
module.exports = newWhere;
|