orange-orm 5.1.0 → 5.2.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 +87 -1
- package/bin/build.js +1 -0
- package/dist/index.browser.mjs +385 -28
- package/dist/index.mjs +385 -28
- package/other.db +0 -0
- package/package.json +1 -1
- package/src/client/index.js +24 -3
- package/src/getManyDto/query/newSingleQuery.js +4 -3
- package/src/hostExpress/executePath.js +64 -11
- package/src/hostLocal.js +1 -1
- package/src/map2.d.ts +34 -25
- package/src/table/column/encodeFilterArg.js +3 -1
- package/src/table/column/newColumn.js +17 -0
- package/src/table/column/string/containsCore.js +7 -3
- package/src/table/column/string/endsWithCore.js +6 -2
- package/src/table/column/string/newLikeColumnArg.js +38 -0
- package/src/table/column/string/startsWithCore.js +6 -2
- package/src/table/groupBy/newQuery.js +12 -3
- package/src/table/groupBy.js +3 -3
- package/src/table/newRelatedTable.js +5 -1
- package/src/table/relatedTable/count.js +139 -0
- package/src/table/relatedTable/newFilterArg.js +20 -0
- package/src/table/relatedTable/relatedColumn.js +11 -1
- package/src/table.js +4 -0
package/README.md
CHANGED
|
@@ -634,6 +634,8 @@ The following operators are supported:
|
|
|
634
634
|
- max
|
|
635
635
|
- avg
|
|
636
636
|
|
|
637
|
+
For distinct rows across selected fields, you can use `table.distinct(...)`.
|
|
638
|
+
|
|
637
639
|
You can also elevate associated data to a parent level for easier access. In the example below, <i>balance</i> of the customer is elevated to the root level.
|
|
638
640
|
|
|
639
641
|
```javascript
|
|
@@ -651,6 +653,19 @@ async function getRows() {
|
|
|
651
653
|
}
|
|
652
654
|
```
|
|
653
655
|
|
|
656
|
+
```javascript
|
|
657
|
+
import map from './map';
|
|
658
|
+
const db = map.sqlite('demo.db');
|
|
659
|
+
|
|
660
|
+
getDistinct();
|
|
661
|
+
|
|
662
|
+
async function getDistinct() {
|
|
663
|
+
const rows = await db.orderLine.distinct({
|
|
664
|
+
orderId: x => x.orderId
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
```
|
|
668
|
+
|
|
654
669
|
__Many rows filtered__
|
|
655
670
|
|
|
656
671
|
```javascript
|
|
@@ -1150,7 +1165,7 @@ async function deleteRows() {
|
|
|
1150
1165
|
</details>
|
|
1151
1166
|
|
|
1152
1167
|
<details id="in-the-browser"><summary><strong>In the browser</strong></summary>
|
|
1153
|
-
<p>You can use <strong><i>Orange</i></strong> in the browser by using the adapter for Express. Instead of sending raw SQL queries from the client to the server, this approach records the method calls in the client. These method calls are then replayed at the server, ensuring a higher level of security by not exposing raw SQL on the client side.
|
|
1168
|
+
<p>You can use <strong><i>Orange</i></strong> in the browser by using the adapter for Express or Hono. Instead of sending raw SQL queries from the client to the server, this approach records the method calls in the client. These method calls are then replayed at the server, ensuring a higher level of security by not exposing raw SQL on the client side.
|
|
1154
1169
|
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>
|
|
1155
1170
|
|
|
1156
1171
|
<sub>📄 server.ts</sub>
|
|
@@ -1197,6 +1212,32 @@ async function updateRows() {
|
|
|
1197
1212
|
|
|
1198
1213
|
```
|
|
1199
1214
|
|
|
1215
|
+
__Hono adapter__
|
|
1216
|
+
|
|
1217
|
+
You can host the same HTTP endpoint with Hono by replacing `db.express()` with `db.hono()`. The browser client setup stays the same (`map.http(...)`), so you can reuse the `browser.ts` example above.
|
|
1218
|
+
|
|
1219
|
+
<sub>📄 server.ts</sub>
|
|
1220
|
+
|
|
1221
|
+
```ts
|
|
1222
|
+
import map from './map';
|
|
1223
|
+
import { Hono } from 'hono';
|
|
1224
|
+
import { cors } from 'hono/cors';
|
|
1225
|
+
import { serve } from '@hono/node-server';
|
|
1226
|
+
|
|
1227
|
+
const db = map.sqlite('demo.db');
|
|
1228
|
+
const app = new Hono();
|
|
1229
|
+
|
|
1230
|
+
app.use('/orange', cors());
|
|
1231
|
+
app.use('/orange/*', cors());
|
|
1232
|
+
// for demonstrational purposes, authentication middleware is not shown here.
|
|
1233
|
+
app.all('/orange', db.hono());
|
|
1234
|
+
app.all('/orange/*', db.hono());
|
|
1235
|
+
|
|
1236
|
+
serve({ fetch: app.fetch, port: 3000 });
|
|
1237
|
+
```
|
|
1238
|
+
|
|
1239
|
+
`baseFilter` and transaction hooks are also supported in `db.hono({...})`, using Hono-style request/response objects.
|
|
1240
|
+
|
|
1200
1241
|
__Interceptors and base filter__
|
|
1201
1242
|
|
|
1202
1243
|
In the next setup, axios interceptors are employed on the client side to add an Authorization header of requests. Meanwhile, on the server side, an Express middleware (validateToken) is utilized to ensure the presence of the Authorization header, while a base filter is applied on the order table to filter incoming requests based on the customerId extracted from this header. This combined approach enhances security by ensuring that users can only access data relevant to their authorization level and that every request is accompanied by a token. In real-world applications, it's advisable to use a more comprehensive token system and expand error handling to manage a wider range of potential issues.
|
|
@@ -1563,6 +1604,33 @@ async function getRows() {
|
|
|
1563
1604
|
});
|
|
1564
1605
|
}
|
|
1565
1606
|
```
|
|
1607
|
+
__Column-to-column filters__
|
|
1608
|
+
You can compare one column to another column instead of comparing to a constant value.
|
|
1609
|
+
This works both on the same table and across relations.
|
|
1610
|
+
|
|
1611
|
+
```javascript
|
|
1612
|
+
import map from './map';
|
|
1613
|
+
const db = map.sqlite('demo.db');
|
|
1614
|
+
|
|
1615
|
+
getRows();
|
|
1616
|
+
|
|
1617
|
+
async function getRows() {
|
|
1618
|
+
// equality between related columns
|
|
1619
|
+
const sameName = await db.order.getMany({
|
|
1620
|
+
where: x => x.deliveryAddress.name.eq(x.customer.name)
|
|
1621
|
+
});
|
|
1622
|
+
|
|
1623
|
+
// string pattern match against another column
|
|
1624
|
+
const containsName = await db.order.getMany({
|
|
1625
|
+
where: x => x.deliveryAddress.name.contains(x.customer.name)
|
|
1626
|
+
});
|
|
1627
|
+
|
|
1628
|
+
// column as one of the bounds in between
|
|
1629
|
+
const withColumnBound = await db.customer.getMany({
|
|
1630
|
+
where: x => x.balance.between(x.id, 180)
|
|
1631
|
+
});
|
|
1632
|
+
}
|
|
1633
|
+
```
|
|
1566
1634
|
__In__
|
|
1567
1635
|
```javascript
|
|
1568
1636
|
import map from './map';
|
|
@@ -2247,6 +2315,24 @@ async function getAggregates() {
|
|
|
2247
2315
|
}
|
|
2248
2316
|
```
|
|
2249
2317
|
|
|
2318
|
+
__Distinct__
|
|
2319
|
+
Use `distinct` when you want unique combinations of selected fields.
|
|
2320
|
+
When only plain columns are selected, this uses SQL `DISTINCT`.
|
|
2321
|
+
If aggregate expressions are included, it falls back to `GROUP BY`.
|
|
2322
|
+
|
|
2323
|
+
```javascript
|
|
2324
|
+
import map from './map';
|
|
2325
|
+
const db = map.sqlite('demo.db');
|
|
2326
|
+
|
|
2327
|
+
getDistinctRows();
|
|
2328
|
+
|
|
2329
|
+
async function getDistinctRows() {
|
|
2330
|
+
const rows = await db.orderLine.distinct({
|
|
2331
|
+
orderId: x => x.orderId
|
|
2332
|
+
});
|
|
2333
|
+
}
|
|
2334
|
+
```
|
|
2335
|
+
|
|
2250
2336
|
__Count__
|
|
2251
2337
|
For convenience, you can use the <i>count</i> directly on the table instead of using the aggregated query syntax.
|
|
2252
2338
|
```javascript
|
package/bin/build.js
CHANGED
|
@@ -114,6 +114,7 @@ function findClosestPackageJson(startDir) {
|
|
|
114
114
|
function findClosestNodeModules(startPath) {
|
|
115
115
|
const startDir = fs.statSync(startPath).isDirectory() ? startPath : path.dirname(startPath);
|
|
116
116
|
let currentDir = startDir;
|
|
117
|
+
// eslint-disable-next-line no-constant-condition
|
|
117
118
|
while (true) {
|
|
118
119
|
const nodeModulesPath = path.join(currentDir, 'node_modules');
|
|
119
120
|
if (fs.existsSync(nodeModulesPath))
|