orange-orm 5.0.0-beta.1 β†’ 5.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -51,7 +51,7 @@ Watch the [tutorial video on YouTube](https://youtu.be/1IwwjPr2lMs)
51
51
  ![Relations diagram](./docs/diagram.svg)
52
52
 
53
53
  <sub>πŸ“„ map.ts</sub>
54
- ```ts
54
+ ```javascript
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().enum(['NO', 'SE', 'DK', 'FI', 'IS', 'DE', 'FR', 'NL', 'ES', 'IT']),
91
+ countryCode: column('countryCode').string(),
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
- ```ts
109
+ ```javascript
110
110
  import map from './map';
111
111
  const db = map.sqlite('demo.db');
112
112
 
@@ -127,14 +127,14 @@ async function updateRow() {
127
127
  ```
128
128
  <sub>πŸ“„ filter.ts</sub>
129
129
 
130
- ```ts
130
+ ```javascript
131
131
  import map from './map';
132
132
  const db = map.sqlite('demo.db');
133
133
 
134
134
  getRows();
135
135
 
136
136
  async function getRows() {
137
- const orders = await db.order.getMany({
137
+ const orders = await db.order.getAll({
138
138
  where: x => x.lines.any(line => line.product.contains('broomstick'))
139
139
  .and(x.customer.name.startsWith('Harry')),
140
140
  lines: {
@@ -157,8 +157,7 @@ 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
-
161
- ```ts
160
+ ```javascript
162
161
  import orange from 'orange-orm';
163
162
 
164
163
  const map = orange.map(x => ({
@@ -194,7 +193,7 @@ const map = orange.map(x => ({
194
193
  street: column('street').string(),
195
194
  postalCode: column('postalCode').string(),
196
195
  postalPlace: column('postalPlace').string(),
197
- countryCode: column('countryCode').string().enum(['NO', 'SE', 'DK', 'FI', 'IS', 'DE', 'FR', 'NL', 'ES', 'IT']),
196
+ countryCode: column('countryCode').string(),
198
197
  }))
199
198
 
200
199
  })).map(x => ({
@@ -219,8 +218,7 @@ Then, we define a SQL string. This string outlines the structure of our SQLite d
219
218
  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.
220
219
 
221
220
  <sub>πŸ“„ init.ts</sub>
222
-
223
- ```ts
221
+ ```javascript
224
222
  import map from './map';
225
223
  const db = map.sqlite('demo.db');
226
224
 
@@ -312,13 +310,34 @@ __Why close ?__
312
310
  In serverless environments (e.g. AWS Lambda, Vercel, Cloudflare Workers) execution contexts are frequently frozen and resumed. Explicitly closing the client or pool ensures that file handles are released promptly and prevents β€œdatabase locked” errors between invocations.
313
311
 
314
312
  __SQLite user-defined functions__
315
- You can register custom SQLite functions using `db.function(name, fn)`.
316
- For full behavior, runtime caveats, and examples, see [SQLite user-defined functions](#sqlite-user-defined-functions).
313
+ You can register custom SQLite functions on the connection using `db.function(name, fn)`.
314
+
315
+ ```javascript
316
+ import map from './map';
317
+ const db = map.sqlite('demo.db');
318
+
319
+ db.function('add_prefix', (text, prefix) => `${prefix}${text}`);
320
+
321
+ const rows = await db.query(
322
+ "select id, name, add_prefix(name, '[VIP] ') as prefixedName from customer"
323
+ );
324
+ ```
325
+
326
+ If you need the function inside a transaction, register it within the transaction callback to ensure it is available on that connection.
327
+
328
+ ```javascript
329
+ await db.transaction(async (db) => {
330
+ db.function('add_prefix', (text, prefix) => `${prefix}${text}`);
331
+ return db.query(
332
+ "select id, name, add_prefix(name, '[VIP] ') as prefixedName from customer"
333
+ );
334
+ });
335
+ ```
317
336
 
318
337
  __From the browser__
319
338
  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)
320
339
  <sub>πŸ“„ server.ts</sub>
321
- ```ts
340
+ ```javascript
322
341
  import map from './map';
323
342
  import { json } from 'body-parser';
324
343
  import express from 'express';
@@ -335,7 +354,7 @@ express().disable('x-powered-by')
335
354
  ```
336
355
 
337
356
  <sub>πŸ“„ browser.ts</sub>
338
- ```ts
357
+ ```javascript
339
358
  import map from './map';
340
359
 
341
360
  const db = map.http('http://localhost:3000/orange');
@@ -413,7 +432,7 @@ database_id = "<your-guid-for-the-database>"
413
432
  ```
414
433
 
415
434
  <sub>πŸ“„ src/index.ts</sub>
416
- ```ts
435
+ ```javascript
417
436
  import map from './map';
418
437
 
419
438
  export interface Env {
@@ -424,7 +443,7 @@ export interface Env {
424
443
  export default {
425
444
  async fetch(request, env): Promise<Response> {
426
445
  const db = map.d1(env.DB);
427
- const customers = await db.customer.getMany();
446
+ const customers = await db.customer.getAll();
428
447
  return Response.json(customers);
429
448
  },
430
449
  } satisfies ExportedHandler<Env>;
@@ -592,7 +611,7 @@ const db = map.sqlite('demo.db');
592
611
  getRows();
593
612
 
594
613
  async function getRows() {
595
- const orders = await db.order.getMany({
614
+ const orders = await db.order.getAll({
596
615
  customer: true,
597
616
  deliveryAddress: true,
598
617
  lines: {
@@ -611,7 +630,7 @@ const db = map.sqlite('demo.db');
611
630
  getRows();
612
631
 
613
632
  async function getRows() {
614
- const orders = await db.order.getMany({
633
+ const orders = await db.order.getAll({
615
634
  offset: 1,
616
635
  orderBy: ['orderDate desc', 'id'],
617
636
  limit: 10,
@@ -643,7 +662,7 @@ const db = map.sqlite('demo.db');
643
662
  getRows();
644
663
 
645
664
  async function getRows() {
646
- const orders = await db.order.getMany({
665
+ const orders = await db.order.getAll({
647
666
  numberOfLines: x => x.count(x => x.lines.id),
648
667
  totalAmount: x => x.sum(x => lines.amount),
649
668
  balance: x => x.customer.balance
@@ -660,7 +679,7 @@ const db = map.sqlite('demo.db');
660
679
  getRows();
661
680
 
662
681
  async function getRows() {
663
- const orders = await db.order.getMany({
682
+ const orders = await db.order.getAll({
664
683
  where: x => x.lines.any(line => line.product.contains('i'))
665
684
  .and(x.customer.balance.greaterThan(180)),
666
685
  customer: true,
@@ -669,13 +688,14 @@ async function getRows() {
669
688
  });
670
689
  }
671
690
  ```
672
- You can also use the alternative syntax for the `where` filter. This way, the filter can be constructed independently from the fetching strategy and passed in via the `where` clause.
691
+ You can also use the alternative syntax for the `where-filter`. This way, the filter can be constructed independently from the fetching strategy. Keep in mind that you must use the `getMany` method instead of the `getAll` method.
692
+ It is also possible to combine `where-filter` with the independent filter when using the `getMany` method.
673
693
  ```javascript
674
694
  async function getRows() {
675
695
  const filter = db.order.lines.any(line => line.product.contains('i'))
676
696
  .and(db.order.customer.balance.greaterThan(180));
677
- const orders = await db.order.getMany({
678
- where: filter,
697
+ const orders = await db.order.getMany(filter, {
698
+ //where: x => ... can be combined as well
679
699
  customer: true,
680
700
  deliveryAddress: true,
681
701
  lines: true
@@ -790,7 +810,7 @@ const db = map.sqlite('demo.db');
790
810
  update();
791
811
 
792
812
  async function update() {
793
- let orders = await db.order.getMany({
813
+ let orders = await db.order.getAll({
794
814
  orderBy: 'id',
795
815
  lines: true,
796
816
  deliveryAddress: true,
@@ -1023,7 +1043,7 @@ const db = map.sqlite('demo.db');
1023
1043
  updateInsertDelete();
1024
1044
 
1025
1045
  async function updateInsertDelete() {
1026
- const orders = await db.order.getMany({
1046
+ const orders = await db.order.getAll({
1027
1047
  customer: true,
1028
1048
  deliveryAddress: true,
1029
1049
  lines: true
@@ -1070,7 +1090,7 @@ const db = map.sqlite('demo.db');
1070
1090
  deleteRows();
1071
1091
 
1072
1092
  async function deleteRows() {
1073
- let orders = await db.order.getMany({
1093
+ let orders = await db.order.getAll({
1074
1094
  where: x => x.customer.name.eq('George')
1075
1095
  });
1076
1096
 
@@ -1086,7 +1106,7 @@ const db = map.sqlite('demo.db');
1086
1106
  deleteRows();
1087
1107
 
1088
1108
  async function deleteRows() {
1089
- let orders = await db.order.getMany({
1109
+ let orders = await db.order.getAll({
1090
1110
  where: x => x.deliveryAddress.name.eq('George'),
1091
1111
  customer: true,
1092
1112
  deliveryAddress: true,
@@ -1154,7 +1174,7 @@ Raw sql queries, raw sql filters and transactions are disabled at the http clien
1154
1174
 
1155
1175
  <sub>πŸ“„ server.ts</sub>
1156
1176
 
1157
- ```ts
1177
+ ```javascript
1158
1178
  import map from './map';
1159
1179
  import { json } from 'body-parser';
1160
1180
  import express from 'express';
@@ -1171,7 +1191,7 @@ express().disable('x-powered-by')
1171
1191
  ```
1172
1192
 
1173
1193
  <sub>πŸ“„ browser.ts</sub>
1174
- ```ts
1194
+ ```javascript
1175
1195
  import map from './map';
1176
1196
 
1177
1197
  const db = map.http('http://localhost:3000/orange');
@@ -1202,7 +1222,7 @@ One notable side effect compared to the previous example, is that only the order
1202
1222
 
1203
1223
  <sub>πŸ“„ server.ts</sub>
1204
1224
 
1205
- ```ts
1225
+ ```javascript
1206
1226
  import map from './map';
1207
1227
  import { json } from 'body-parser';
1208
1228
  import express from 'express';
@@ -1237,7 +1257,7 @@ function validateToken(req, res, next) {
1237
1257
 
1238
1258
  <sub>πŸ“„ browser.ts</sub>
1239
1259
 
1240
- ```ts
1260
+ ```javascript
1241
1261
  import map from './map';
1242
1262
 
1243
1263
  const db = map.http('http://localhost:3000/orange');
@@ -1281,8 +1301,9 @@ async function updateRows() {
1281
1301
 
1282
1302
  ```
1283
1303
 
1284
- __Row Level Security__
1304
+ __Row Level Security (Postgres)__
1285
1305
  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.
1306
+ Available transaction hooks are `beforeBegin`, `afterBegin`, `beforeCommit`, `afterCommit`, and `afterRollback`.
1286
1307
 
1287
1308
  <sub>πŸ“„ setup.sql</sub>
1288
1309
 
@@ -1309,7 +1330,7 @@ insert into tenant_data (tenant_id, value) values
1309
1330
 
1310
1331
  <sub>πŸ“„ server.ts</sub>
1311
1332
 
1312
- ```ts
1333
+ ```javascript
1313
1334
  import map from './map';
1314
1335
  import { json } from 'body-parser';
1315
1336
  import express from 'express';
@@ -1324,7 +1345,6 @@ express().disable('x-powered-by')
1324
1345
  .use('/orange', db.express({
1325
1346
  hooks: {
1326
1347
  transaction: {
1327
- //beforeBegin: async (db, req) => ...,
1328
1348
  afterBegin: async (db, req) => {
1329
1349
  const tenantId = Number.parseInt(String(req.user?.tenantId ?? ''), 10);
1330
1350
  if (!Number.isFinite(tenantId)) throw new Error('Missing tenant id');
@@ -1333,12 +1353,7 @@ express().disable('x-powered-by')
1333
1353
  sql: 'select set_config(\'app.tenant_id\', ?, true)',
1334
1354
  parameters: [String(tenantId)]
1335
1355
  });
1336
- },
1337
- //beforeCommit: async (db, req) => ...,
1338
- //afterCommit: async (db, req) => ...,
1339
- // afterRollback: async (db, req, error) => {
1340
- // console.dir(error);
1341
- // }
1356
+ }
1342
1357
  }
1343
1358
  }
1344
1359
  }))
@@ -1367,7 +1382,7 @@ function decodeFakeJwt(token) {
1367
1382
 
1368
1383
  <sub>πŸ“„ browser.ts</sub>
1369
1384
 
1370
- ```ts
1385
+ ```javascript
1371
1386
  import map from './map';
1372
1387
 
1373
1388
  const db = map.http('http://localhost:3000/orange');
@@ -1397,7 +1412,7 @@ const db = map.sqlite('demo.db');
1397
1412
  getRows();
1398
1413
 
1399
1414
  async function getRows() {
1400
- const rows = await db.order.getMany({
1415
+ const rows = await db.order.getAll({
1401
1416
  deliveryAddress: true
1402
1417
  });
1403
1418
  }
@@ -1413,7 +1428,7 @@ const db = map.sqlite('demo.db');
1413
1428
  getRows();
1414
1429
 
1415
1430
  async function getRows() {
1416
- const rows = await db.order.getMany({
1431
+ const rows = await db.order.getAll({
1417
1432
  orderDate: false,
1418
1433
  deliveryAddress: {
1419
1434
  countryCode: true,
@@ -1437,7 +1452,7 @@ const db = map.sqlite('demo.db');
1437
1452
  getRows();
1438
1453
 
1439
1454
  async function getRows() {
1440
- const rows = await db.customer.getMany({
1455
+ const rows = await db.customer.getAll({
1441
1456
  where x => x.name.equal('Harry')
1442
1457
  });
1443
1458
  }
@@ -1450,7 +1465,7 @@ const db = map.sqlite('demo.db');
1450
1465
  getRows();
1451
1466
 
1452
1467
  async function getRows() {
1453
- const rows = await db.customer.getMany({
1468
+ const rows = await db.customer.getAll({
1454
1469
  where x => x.name.notEqual('Harry')
1455
1470
  });
1456
1471
  }
@@ -1463,7 +1478,7 @@ const db = map.sqlite('demo.db');
1463
1478
  getRows();
1464
1479
 
1465
1480
  async function getRows() {
1466
- const rows = await db.customer.getMany({
1481
+ const rows = await db.customer.getAll({
1467
1482
  where: x => x.name.contains('arr')
1468
1483
  });
1469
1484
  }
@@ -1478,7 +1493,7 @@ getRows();
1478
1493
  async function getRows() {
1479
1494
  const filter = db.customer.name.startsWith('Harr');
1480
1495
 
1481
- const rows = await db.customer.getMany({
1496
+ const rows = await db.customer.getAll({
1482
1497
  where: x => x.name.startsWith('Harr')
1483
1498
  });
1484
1499
  }
@@ -1491,7 +1506,7 @@ const db = map.sqlite('demo.db');
1491
1506
  getRows();
1492
1507
 
1493
1508
  async function getRows() {
1494
- const rows = await db.customer.getMany({
1509
+ const rows = await db.customer.getAll({
1495
1510
  where: x => x.name.endsWith('arry')
1496
1511
  });
1497
1512
  }
@@ -1504,7 +1519,7 @@ const db = map.sqlite('demo.db');
1504
1519
  getRows();
1505
1520
 
1506
1521
  async function getRows() {
1507
- const rows = await db.order.getMany({
1522
+ const rows = await db.order.getAll({
1508
1523
  where: x => x.orderDate.greaterThan('2023-07-14T12:00:00')
1509
1524
  });
1510
1525
  }
@@ -1517,7 +1532,7 @@ const db = map.sqlite('demo.db');
1517
1532
  getRows();
1518
1533
 
1519
1534
  async function getRows() {
1520
- const rows = await db.order.getMany({
1535
+ const rows = await db.order.getAll({
1521
1536
  where: x => x.orderDate.greaterThanOrEqual('2023-07-14T12:00:00')
1522
1537
  });
1523
1538
  }
@@ -1530,7 +1545,7 @@ const db = map.sqlite('demo.db');
1530
1545
  getRows();
1531
1546
 
1532
1547
  async function getRows() {
1533
- const rows = await db.order.getMany({
1548
+ const rows = await db.order.getAll({
1534
1549
  where: x => x.orderDate.lessThan('2023-07-14T12:00:00')
1535
1550
  });
1536
1551
  }
@@ -1543,7 +1558,7 @@ const db = map.sqlite('demo.db');
1543
1558
  getRows();
1544
1559
 
1545
1560
  async function getRows() {
1546
- const rows = await db.order.getMany({
1561
+ const rows = await db.order.getAll({
1547
1562
  where: x => x.orderDate.lessThanOrEqual('2023-07-14T12:00:00')
1548
1563
  });
1549
1564
  }
@@ -1556,7 +1571,7 @@ const db = map.sqlite('demo.db');
1556
1571
  getRows();
1557
1572
 
1558
1573
  async function getRows() {
1559
- const rows = await db.order.getMany({
1574
+ const rows = await db.order.getAll({
1560
1575
  where: x => x.orderDate.between('2023-07-14T12:00:00', '2024-07-14T12:00:00')
1561
1576
  });
1562
1577
  }
@@ -1569,7 +1584,7 @@ const db = map.sqlite('demo.db');
1569
1584
  getRows();
1570
1585
 
1571
1586
  async function getRows() {
1572
- const rows = await db.order.getMany({
1587
+ const rows = await db.order.getAll({
1573
1588
  where: x => x.customer.name.in('George', 'Harry')
1574
1589
  });
1575
1590
 
@@ -1591,11 +1606,11 @@ async function getRows() {
1591
1606
  parameters: ['%arry']
1592
1607
  };
1593
1608
 
1594
- const rowsWithRaw = await db.customer.getMany({
1609
+ const rowsWithRaw = await db.customer.getAll({
1595
1610
  where: () => rawFilter
1596
1611
  });
1597
1612
 
1598
- const rowsWithCombined = await db.customer.getMany({
1613
+ const rowsWithCombined = await db.customer.getAll({
1599
1614
  where: x => x.balance.greaterThan(100).and(rawFilter)
1600
1615
  });
1601
1616
  }
@@ -1613,7 +1628,7 @@ const db = map.sqlite('demo.db');
1613
1628
  getRows();
1614
1629
 
1615
1630
  async function getRows() {
1616
- const orders = await db.order.getMany({
1631
+ const orders = await db.order.getAll({
1617
1632
  lines: {
1618
1633
  where: x => x.product.contains('broomstick')
1619
1634
  },
@@ -1635,7 +1650,7 @@ const db = map.sqlite('demo.db');
1635
1650
  getRows();
1636
1651
 
1637
1652
  async function getRows() {
1638
- const rows = await db.order.getMany({
1653
+ const rows = await db.order.getAll({
1639
1654
  where: x => x.customer.name.equal('Harry')
1640
1655
  .and(x.orderDate.greaterThan('2023-07-14T12:00:00'))
1641
1656
  });
@@ -1650,7 +1665,7 @@ getRows();
1650
1665
 
1651
1666
  async function getRows() {
1652
1667
 
1653
- const rows = await db.order.getMany({
1668
+ const rows = await db.order.getAll({
1654
1669
  where: y => y.customer( x => x.name.equal('George')
1655
1670
  .or(x.name.equal('Harry')))
1656
1671
  });
@@ -1665,7 +1680,7 @@ getRows();
1665
1680
 
1666
1681
  async function getRows() {
1667
1682
  //Neither George nor Harry
1668
- const rows = await db.order.getMany({
1683
+ const rows = await db.order.getAll({
1669
1684
  where: y => y.customer(x => x.name.equal('George')
1670
1685
  .or(x.name.equal('Harry')))
1671
1686
  .not()
@@ -1680,7 +1695,7 @@ const db = map.sqlite('demo.db');
1680
1695
  getRows();
1681
1696
 
1682
1697
  async function getRows() {
1683
- const rows = await db.order.getMany({
1698
+ const rows = await db.order.getAll({
1684
1699
  where: x => x.deliveryAddress.exists()
1685
1700
  });
1686
1701
  }
@@ -1701,7 +1716,7 @@ const db = map.sqlite('demo.db');
1701
1716
  getRows();
1702
1717
 
1703
1718
  async function getRows() {
1704
- const rows = await db.order.getMany({
1719
+ const rows = await db.order.getAll({
1705
1720
  where: y => y.lines.any(x => x.product.contains('guitar'))
1706
1721
  //equivalent syntax:
1707
1722
  //where: x => x.lines.product.contains('guitar')
@@ -1717,7 +1732,7 @@ const db = map.sqlite('demo.db');
1717
1732
  getRows();
1718
1733
 
1719
1734
  async function getRows() {
1720
- const rows = await db.order.getMany({
1735
+ const rows = await db.order.getAll({
1721
1736
  where: y => y.lines.all(x => x.product.contains('a'))
1722
1737
  });
1723
1738
  }
@@ -1731,7 +1746,7 @@ const db = map.sqlite('demo.db');
1731
1746
  getRows();
1732
1747
 
1733
1748
  async function getRows() {
1734
- const rows = await db.order.getMany({
1749
+ const rows = await db.order.getAll({
1735
1750
  where: y => y.lines.none(x => x.product.equal('Magic wand'))
1736
1751
  });
1737
1752
  }
@@ -1780,8 +1795,7 @@ async function execute() {
1780
1795
  - **`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.
1781
1796
 
1782
1797
  <sub>πŸ“„ map.ts</sub>
1783
-
1784
- ```ts
1798
+ ```javascript
1785
1799
  import orange from 'orange-orm';
1786
1800
 
1787
1801
  interface Pet {
@@ -1804,8 +1818,7 @@ const map = orange.map(x => ({
1804
1818
  }));
1805
1819
  ```
1806
1820
  <sub>πŸ“„ map.js</sub>
1807
-
1808
- ```js
1821
+ ```javascript
1809
1822
  import orange from 'orange-orm';
1810
1823
 
1811
1824
  /**
@@ -1832,138 +1845,6 @@ const map = orange.map(x => ({
1832
1845
  ```
1833
1846
  </details>
1834
1847
 
1835
- <details id="enums"><summary><strong>Enums</strong></summary>
1836
- <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>
1837
-
1838
- <sub>πŸ“„ map.ts (TypeScript enum)</sub>
1839
-
1840
- ```ts
1841
- enum CountryCode {
1842
- NORWAY = 'NO',
1843
- SWEDEN = 'SE',
1844
- DENMARK = 'DK',
1845
- FINLAND = 'FI',
1846
- ICELAND = 'IS',
1847
- GERMANY = 'DE',
1848
- FRANCE = 'FR',
1849
- NETHERLANDS = 'NL',
1850
- SPAIN = 'ES',
1851
- ITALY = 'IT',
1852
- }
1853
-
1854
- const map = orange.map(x => ({
1855
- deliveryAddress: x.table('deliveryAddress').map(({ column }) => ({
1856
- id: column('id').numeric().primary(),
1857
- name: column('name').string(),
1858
- street: column('street').string(),
1859
- postalCode: column('postalCode').string(),
1860
- postalPlace: column('postalPlace').string(),
1861
- countryCode: column('countryCode').string().enum(CountryCode),
1862
- }))
1863
- }));
1864
- ```
1865
-
1866
-
1867
- <sub>πŸ“„ map.ts (as const)</sub>
1868
-
1869
- ```ts
1870
- const Countries = {
1871
- NORWAY: 'NO',
1872
- SWEDEN: 'SE',
1873
- DENMARK: 'DK',
1874
- FINLAND: 'FI',
1875
- ICELAND: 'IS',
1876
- GERMANY: 'DE',
1877
- FRANCE: 'FR',
1878
- NETHERLANDS: 'NL',
1879
- SPAIN: 'ES',
1880
- ITALY: 'IT',
1881
- } as const;
1882
-
1883
- const map = orange.map(x => ({
1884
- deliveryAddress: x.table('deliveryAddress').map(({ column }) => ({
1885
- id: column('id').numeric().primary(),
1886
- name: column('name').string(),
1887
- street: column('street').string(),
1888
- postalCode: column('postalCode').string(),
1889
- postalPlace: column('postalPlace').string(),
1890
- countryCode: column('countryCode').string().enum(Countries),
1891
- }))
1892
- }));
1893
- ```
1894
-
1895
- <sub>πŸ“„ map.ts (array)</sub>
1896
-
1897
- ```ts
1898
- const map = orange.map(x => ({
1899
- deliveryAddress: x.table('deliveryAddress').map(({ column }) => ({
1900
- id: column('id').numeric().primary(),
1901
- name: column('name').string(),
1902
- street: column('street').string(),
1903
- postalCode: column('postalCode').string(),
1904
- postalPlace: column('postalPlace').string(),
1905
- countryCode: column('countryCode').string().enum(
1906
- ['NO', 'SE', 'DK', 'FI', 'IS', 'DE', 'FR', 'NL', 'ES', 'IT']
1907
- ),
1908
- }))
1909
- }));
1910
- ```
1911
-
1912
- <sub>πŸ“„ map.ts (literal object)</sub>
1913
-
1914
- ```ts
1915
- const map = orange.map(x => ({
1916
- deliveryAddress: x.table('deliveryAddress').map(({ column }) => ({
1917
- id: column('id').numeric().primary(),
1918
- name: column('name').string(),
1919
- street: column('street').string(),
1920
- postalCode: column('postalCode').string(),
1921
- postalPlace: column('postalPlace').string(),
1922
- countryCode: column('countryCode').string().enum({
1923
- NORWAY: 'NO',
1924
- SWEDEN: 'SE',
1925
- DENMARK: 'DK',
1926
- FINLAND: 'FI',
1927
- ICELAND: 'IS',
1928
- GERMANY: 'DE',
1929
- FRANCE: 'FR',
1930
- NETHERLANDS: 'NL',
1931
- SPAIN: 'ES',
1932
- ITALY: 'IT',
1933
- }),
1934
- }))
1935
- }));
1936
- ```
1937
-
1938
- <sub>πŸ“„ map.js (Object.freeze)</sub>
1939
-
1940
- ```js
1941
- const Countries = Object.freeze({
1942
- NORWAY: 'NO',
1943
- SWEDEN: 'SE',
1944
- DENMARK: 'DK',
1945
- FINLAND: 'FI',
1946
- ICELAND: 'IS',
1947
- GERMANY: 'DE',
1948
- FRANCE: 'FR',
1949
- NETHERLANDS: 'NL',
1950
- SPAIN: 'ES',
1951
- ITALY: 'IT',
1952
- });
1953
-
1954
- const map = orange.map(x => ({
1955
- deliveryAddress: x.table('deliveryAddress').map(({ column }) => ({
1956
- id: column('id').numeric().primary(),
1957
- name: column('name').string(),
1958
- street: column('street').string(),
1959
- postalCode: column('postalCode').string(),
1960
- postalPlace: column('postalPlace').string(),
1961
- countryCode: column('countryCode').string().enum(Countries),
1962
- }))
1963
- }));
1964
- ```
1965
- </details>
1966
-
1967
1848
  <details id="default-values"><summary><strong>Default values</strong></summary>
1968
1849
  <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.
1969
1850
 
@@ -1990,7 +1871,7 @@ export default map;
1990
1871
  <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>
1991
1872
 
1992
1873
  <sub>πŸ“„ map.ts</sub>
1993
- ```ts
1874
+ ```javascript
1994
1875
  import orange from 'orange-orm';
1995
1876
 
1996
1877
  interface Pet {
@@ -2021,7 +1902,7 @@ const map = orange.map(x => ({
2021
1902
  export default map;
2022
1903
  ```
2023
1904
  <sub>πŸ“„ map.js</sub>
2024
- ```js
1905
+ ```javascript
2025
1906
  import orange from 'orange-orm';
2026
1907
 
2027
1908
  /**
@@ -2159,43 +2040,6 @@ async function getRows() {
2159
2040
  ```
2160
2041
  </details>
2161
2042
 
2162
- <details id="sqlite-user-defined-functions"><summary><strong>SQLite user-defined functions</strong></summary>
2163
-
2164
- You can register custom SQLite functions on the connection using `db.function(name, fn)`.
2165
-
2166
- The `fn` argument is your user-defined callback:
2167
- - It is invoked by SQLite every time the SQL function is called.
2168
- - Callback arguments are positional and match the SQL call (for example, `my_fn(a, b)` maps to `(a, b)`).
2169
- - Return a SQLite-compatible scalar value (for example text, number, or `null`).
2170
- - Throwing inside the callback fails the SQL statement.
2171
-
2172
- `db.function(...)` is sync-only in Node and Deno, but can be async or sync in Bun.
2173
-
2174
- ```javascript
2175
- import map from './map';
2176
- const db = map.sqlite('demo.db');
2177
-
2178
- await db.function('add_prefix', (text, prefix) => `${prefix}${text}`);
2179
-
2180
- const rows = await db.query(
2181
- "select id, name, add_prefix(name, '[VIP] ') as prefixedName from customer"
2182
- );
2183
- ```
2184
-
2185
- If you need the function inside a transaction, register it within the transaction callback to ensure it is available on that connection.
2186
-
2187
- ```javascript
2188
- await db.transaction(async (db) => {
2189
- await db.function('add_prefix', (text, prefix) => `${prefix}${text}`);
2190
- return db.query(
2191
- "select id, name, add_prefix(name, '[VIP] ') as prefixedName from customer"
2192
- );
2193
- });
2194
- ```
2195
-
2196
- `db.function(...)` is available on direct SQLite connections (for example `map.sqlite(...)`) and not through `map.http(...)`.
2197
- </details>
2198
-
2199
2043
  <details id="aggregates"><summary><strong>Aggregate functions</strong></summary>
2200
2044
 
2201
2045
  You can count records and aggregate numerical columns. This can either be done across rows or separately for each row.
@@ -2217,7 +2061,7 @@ const db = map.sqlite('demo.db');
2217
2061
  getRows();
2218
2062
 
2219
2063
  async function getRows() {
2220
- const orders = await db.order.getMany({
2064
+ const orders = await db.order.getAll({
2221
2065
  numberOfLines: x => x.count(x => x.lines.id),
2222
2066
  totalAmount: x => x.sum(x => lines.amount),
2223
2067
  balance: x => x.customer.balance
@@ -2268,7 +2112,7 @@ async function getCount() {
2268
2112
 
2269
2113
  <sub>πŸ“„ map.ts</sub>
2270
2114
 
2271
- ```ts
2115
+ ```javascript
2272
2116
  import orange from 'orange-orm';
2273
2117
 
2274
2118
  const map = orange.map(x => ({
@@ -2284,7 +2128,7 @@ export default map;
2284
2128
  ```
2285
2129
  <sub>πŸ“„ sensitive.ts</sub>
2286
2130
 
2287
- ```ts
2131
+ ```javascript
2288
2132
  import map from './map';
2289
2133
  const db = map.sqlite('demo.db');
2290
2134
 
@@ -5886,37 +5886,6 @@ function requireColumn () {
5886
5886
  return c;
5887
5887
  };
5888
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
-
5920
5889
  c.default = function(value) {
5921
5890
  column.default = value;
5922
5891
  return c;
@@ -5932,6 +5901,7 @@ function requireColumn () {
5932
5901
  var oldAlias = column.alias;
5933
5902
  table._aliases.delete(oldAlias);
5934
5903
  table._aliases.add(alias);
5904
+ delete table[oldAlias];
5935
5905
  table[alias] = column;
5936
5906
  column.alias = alias;
5937
5907
  return c;
package/dist/index.mjs CHANGED
@@ -5887,37 +5887,6 @@ function requireColumn () {
5887
5887
  return c;
5888
5888
  };
5889
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
-
5921
5890
  c.default = function(value) {
5922
5891
  column.default = value;
5923
5892
  return c;
@@ -5933,6 +5902,7 @@ function requireColumn () {
5933
5902
  var oldAlias = column.alias;
5934
5903
  table._aliases.delete(oldAlias);
5935
5904
  table._aliases.add(alias);
5905
+ delete table[oldAlias];
5936
5906
  table[alias] = column;
5937
5907
  column.alias = alias;
5938
5908
  return c;
@@ -19655,7 +19625,7 @@ function requireOutputInsertedSql () {
19655
19625
 
19656
19626
  function formatColumn(column) {
19657
19627
  if (column.formatOut)
19658
- return column.formatOut(context, 'INSERTED');
19628
+ return `${column.formatOut(context, 'INSERTED')} AS [${column._dbName}]`;
19659
19629
  else
19660
19630
  return `INSERTED.[${column._dbName}]`;
19661
19631
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orange-orm",
3
- "version": "5.0.0-beta.1",
3
+ "version": "5.0.0-beta.2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/src/map.d.ts CHANGED
@@ -96,9 +96,7 @@ type ReturnArrayOrObj<W, V1, V2> =
96
96
  V1;
97
97
 
98
98
 
99
- type ColumnToType<T> = T extends EnumOf<infer E>
100
- ? E
101
- : T extends UuidColumnSymbol
99
+ type ColumnToType<T> = T extends UuidColumnSymbol
102
100
  ? string
103
101
  : T extends StringColumnSymbol
104
102
  ? string
@@ -627,10 +625,6 @@ type NotNullExceptInsert = {
627
625
  [' notNullExceptInsert']: boolean;
628
626
  };
629
627
 
630
- type EnumOf<T> = {
631
- [' enum']: T;
632
- };
633
-
634
628
  type JsonOf<T> = {
635
629
  [' isjsonOf']: boolean;
636
630
  type: T;
@@ -740,11 +734,6 @@ type DateWithTimeZoneValidator<M> = M extends NotNull
740
734
  };
741
735
 
742
736
  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]>;
748
737
  primary(): StringColumnTypeDef<M & IsPrimary> & IsPrimary;
749
738
  notNull(): StringColumnTypeDef<M & NotNull> & NotNull;
750
739
  notNullExceptInsert(): StringColumnTypeDef<M & NotNull & NotNullExceptInsert> & NotNull & NotNullExceptInsert;
@@ -756,10 +745,6 @@ type StringColumnTypeDef<M> = StringValidator<M> & {
756
745
  M;
757
746
 
758
747
  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]>;
763
748
  primary(): NumericColumnTypeDef<M & IsPrimary> & IsPrimary;
764
749
  notNull(): NumericColumnTypeDef<M & NotNull> & NotNull;
765
750
  notNullExceptInsert(): NumericColumnTypeDef<M & NotNull & NotNullExceptInsert> & NotNull & NotNullExceptInsert;
@@ -771,10 +756,6 @@ type NumericColumnTypeDef<M> = NumericValidator<M> & {
771
756
  M;
772
757
 
773
758
  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]>;
778
759
  primary(): BigIntColumnTypeDef<M & IsPrimary> & IsPrimary;
779
760
  notNull(): BigIntColumnTypeDef<M & NotNull> & NotNull;
780
761
  notNullExceptInsert(): BigIntColumnTypeDef<M & NotNull & NotNullExceptInsert> & NotNull & NotNullExceptInsert;
@@ -786,10 +767,6 @@ type BigIntColumnTypeDef<M> = BigIntValidator<M> & {
786
767
  M;
787
768
 
788
769
  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]>;
793
770
  primary(): UuidColumnTypeDef<M & IsPrimary> & IsPrimary;
794
771
  notNull(): UuidColumnTypeDef<M & NotNull> & NotNull;
795
772
  notNullExceptInsert(): UuidColumnTypeDef<M & NotNull & NotNullExceptInsert> & NotNull & NotNullExceptInsert;
@@ -812,10 +789,6 @@ type JSONColumnTypeDef<M> = JSONValidator<M> & {
812
789
  M;
813
790
 
814
791
  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]>;
819
792
  primary(): BinaryColumnTypeDef<M & IsPrimary> & IsPrimary;
820
793
  notNull(): BinaryColumnTypeDef<M & NotNull> & NotNull;
821
794
  notNullExceptInsert(): BinaryColumnTypeDef<M & NotNull & NotNullExceptInsert> & NotNull & NotNullExceptInsert;
@@ -827,10 +800,6 @@ type BinaryColumnTypeDef<M> = BinaryValidator<M> & {
827
800
  M;
828
801
 
829
802
  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]>;
834
803
  primary(): BooleanColumnTypeDef<M & IsPrimary> & IsPrimary;
835
804
  notNull(): BooleanColumnTypeDef<M & NotNull> & NotNull;
836
805
  notNullExceptInsert(): BooleanColumnTypeDef<M & NotNull & NotNullExceptInsert> & NotNull & NotNullExceptInsert;
@@ -842,10 +811,6 @@ type BooleanColumnTypeDef<M> = BooleanValidator<M> & {
842
811
  M;
843
812
 
844
813
  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]>;
849
814
  primary(): DateColumnTypeDef<M & IsPrimary> & IsPrimary;
850
815
  notNull(): DateColumnTypeDef<M & NotNull> & NotNull;
851
816
  notNullExceptInsert(): DateColumnTypeDef<M & NotNull & NotNullExceptInsert> & NotNull & NotNullExceptInsert;
@@ -857,10 +822,6 @@ type DateColumnTypeDef<M> = DateValidator<M> & {
857
822
  M;
858
823
 
859
824
  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]>;
864
825
  primary(): DateWithTimeZoneColumnTypeDef<M & IsPrimary> & IsPrimary;
865
826
  notNull(): DateWithTimeZoneColumnTypeDef<M & NotNull> & NotNull;
866
827
  notNullExceptInsert(): DateWithTimeZoneColumnTypeDef<M & NotNull & NotNullExceptInsert> & NotNull & NotNullExceptInsert;
@@ -1039,9 +1000,7 @@ type ExtractPrimaryKeyNames<T> =
1039
1000
  type RelationTarget<T> =
1040
1001
  T extends { __tableAlias: infer S } ? Extract<S, string> : string;
1041
1002
 
1042
- type EnumSchema<T> = T extends EnumOf<infer E> ? { ' enum': readonly E[] } : {};
1043
-
1044
- type ColumnToSchemaType<T> = (
1003
+ type ColumnToSchemaType<T> =
1045
1004
  T extends JsonOf<infer U>
1046
1005
  ? { ' type': 'json'; ' tsType': U }
1047
1006
  & (T extends NotNullExceptInsert ? { ' notNull': true; ' notNullExceptInsert': true }
@@ -1087,8 +1046,7 @@ type ColumnToSchemaType<T> = (
1087
1046
  & (T extends NotNullExceptInsert ? { ' notNull': true; ' notNullExceptInsert': true }
1088
1047
  : T extends NotNull ? { ' notNull': true }
1089
1048
  : {}) :
1090
- never
1091
- ) & EnumSchema<T>;
1049
+ never;
1092
1050
 
1093
1051
  export type MappedDbDef<T> = {
1094
1052
  map<V extends AllowedDbMap<V>>(
@@ -1101,4 +1059,4 @@ export type MappedDbDef<T> = {
1101
1059
  * Usage: type Schema = ReturnType<typeof db.toSchema>
1102
1060
  */
1103
1061
  toSchema: <U = T>() => SchemaFromMappedDb<U>;
1104
- } & T & DbConnectable<T>;
1062
+ } & T & DbConnectable<T>;
package/src/map2.d.ts CHANGED
@@ -10,7 +10,6 @@ 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>;
14
13
  ' notNull'?: boolean;
15
14
  ' notNullExceptInsert'?: boolean;
16
15
  };
@@ -25,7 +24,7 @@ export type ORMJsonColumnDefinition<T = any> = {
25
24
 
26
25
  type NormalizeColumn<T> =
27
26
  T extends ORMColumnType
28
- ? { ' type': T; ' enum'?: readonly (string | number | boolean | Date)[] | Record<string, string | number | boolean | Date>; ' notNull'?: boolean; ' notNullExceptInsert'?: boolean }
27
+ ? { ' type': T; ' notNull'?: boolean; ' notNullExceptInsert'?: boolean }
29
28
  : T extends { ' type': ORMColumnType }
30
29
  ? { ' notNull'?: boolean; ' notNullExceptInsert'?: boolean } & T
31
30
  : T extends { ' type': 'json'; ' tsType': any }
@@ -42,8 +41,6 @@ type IsRequiredInsert<CT> =
42
41
  : false; // Otherwise, it's optional
43
42
 
44
43
  type ColumnTypeToTS<CT> =
45
- NormalizeColumn<CT> extends { ' enum': readonly (infer E)[] } ? E :
46
- NormalizeColumn<CT> extends { ' enum': Record<string, infer E> } ? E :
47
44
  NormalizeColumn<CT>[' type'] extends 'numeric' ? number :
48
45
  NormalizeColumn<CT>[' type'] extends 'boolean' ? boolean :
49
46
  NormalizeColumn<CT>[' type'] extends 'json'
@@ -166,7 +163,7 @@ type BaseFetchStrategy<M extends Record<string, TableDefinition<M>>, K extends k
166
163
  orderBy?: OrderBy<M, K>;
167
164
  limit?: number;
168
165
  offset?: number;
169
- where?: WhereClause<M, K>;
166
+ where?: WhereFunc<M, K>;
170
167
  };
171
168
 
172
169
  export type PrimaryKeyObject<M extends Record<string, TableDefinition<M>>, K extends keyof M> =
@@ -344,25 +341,18 @@ export type AggregateStrategy<M extends Record<string, TableDefinition<M>>, K ex
344
341
  BaseAggregateStrategy<M, K>
345
342
  | CustomAggregateSelectors<M, K>;
346
343
 
347
- type WhereFilter<M extends Record<string, TableDefinition<M>>, K extends keyof M> =
348
- RawFilter | Array<PrimaryKeyObject<M, K>>;
349
-
350
- type WhereFunc<M extends Record<string, TableDefinition<M>>, K extends keyof M> =
351
- (row: RootTableRefs<M, K>) => WhereFilter<M, K>;
352
-
353
- type WhereClause<M extends Record<string, TableDefinition<M>>, K extends keyof M> =
354
- WhereFilter<M, K> | WhereFunc<M, K> | (() => WhereFilter<M, K>);
344
+ type WhereFunc<M extends Record<string, TableDefinition<M>>, K extends keyof M> = (row: RootTableRefs<M, K>) => RawFilter | Array<PrimaryKeyObject<M, K>>;
355
345
 
356
346
  type BaseAggregateStrategy<M extends Record<string, TableDefinition<M>>, K extends keyof M> = {
357
347
  limit?: number;
358
348
  offset?: number;
359
- where?: WhereClause<M, K>;
349
+ where?: WhereFunc<M, K>;
360
350
  };
361
351
 
362
352
  type CustomAggregateSelectors<M extends Record<string, TableDefinition<M>>, K extends keyof M> = {
363
353
  [key: string]: (row: RootSelectionRefs<M, K>) => ValidSelectorReturnTypes<M, K>;
364
354
  } & {
365
- where?: WhereClause<M, K>;
355
+ where?: WhereFunc<M, K>;
366
356
  } & {
367
357
  // Explicitly prevent limit/offset in selectors
368
358
  limit?: never;
@@ -684,13 +674,13 @@ type AggregateCustomSelectorProperties<M extends Record<string, TableDefinition<
684
674
 
685
675
  export type TableClient<M extends Record<string, TableDefinition<M>>, K extends keyof M> = {
686
676
  // Array methods - return arrays with array-level active record methods, but individual items are plain
687
- getMany<strategy extends FetchStrategy<M, K>>(strategy?: strategy): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, strategy>>>, M, K>>;
677
+ getMany<strategy extends FetchStrategy<M, K> = {}>(strategy: strategy): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, strategy>>>, M, K>>;
688
678
 
689
679
  // Aggregate methods - return plain objects (no active record methods)
690
680
  aggregate<strategy extends AggregateStrategy<M, K>>(strategy: strategy): Promise<Array<DeepExpand<AggregateCustomSelectorProperties<M, K, strategy>>>>;
691
681
 
692
682
  // Single item methods - return individual objects with individual active record methods
693
- getOne<strategy extends FetchStrategy<M, K>>(
683
+ getOne<strategy extends FetchStrategy<M, K> = {}>(
694
684
  strategy?: strategy
695
685
  ): Promise<WithActiveRecord<DeepExpand<Selection<M, K, strategy>>, M, K> | undefined>;
696
686
 
@@ -705,12 +695,12 @@ export type TableClient<M extends Record<string, TableDefinition<M>>, K extends
705
695
  // UPDATED: Bulk update methods with relations support
706
696
  update(
707
697
  row: UpdateRowWithRelations<M, K>,
708
- opts: { where: WhereClause<M, K> }
698
+ opts: { where: (row: RootTableRefs<M, K>) => RawFilter | Array<PrimaryKeyObject<M, K>> }
709
699
  ): Promise<void>;
710
700
 
711
701
  update<strategy extends FetchStrategy<M, K>>(
712
702
  row: UpdateRowWithRelations<M, K>,
713
- opts: { where: WhereClause<M, K> },
703
+ opts: { where: (row: RootTableRefs<M, K>) => RawFilter | Array<PrimaryKeyObject<M, K>> },
714
704
  strategy: strategy
715
705
  ): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, strategy>>>, M, K>>;
716
706
 
@@ -54,37 +54,6 @@ 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
-
88
57
  c.default = function(value) {
89
58
  column.default = value;
90
59
  return c;
@@ -100,6 +69,7 @@ function defineColumn(column, table) {
100
69
  var oldAlias = column.alias;
101
70
  table._aliases.delete(oldAlias);
102
71
  table._aliases.add(alias);
72
+ delete table[oldAlias];
103
73
  table[alias] = column;
104
74
  column.alias = alias;
105
75
  return c;
@@ -190,4 +160,4 @@ function inspect(obj) {
190
160
  }
191
161
 
192
162
 
193
- module.exports = defineColumn;
163
+ module.exports = defineColumn;
@@ -9,7 +9,7 @@ function outputInsertedSql(context, table) {
9
9
 
10
10
  function formatColumn(column) {
11
11
  if (column.formatOut)
12
- return column.formatOut(context, 'INSERTED');
12
+ return `${column.formatOut(context, 'INSERTED')} AS [${column._dbName}]`;
13
13
  else
14
14
  return `INSERTED.[${column._dbName}]`;
15
15
  }
@@ -17,4 +17,4 @@ function outputInsertedSql(context, table) {
17
17
 
18
18
 
19
19
 
20
- module.exports = outputInsertedSql;
20
+ module.exports = outputInsertedSql;