orange-orm 5.1.0 → 5.2.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 CHANGED
@@ -1150,7 +1150,7 @@ async function deleteRows() {
1150
1150
  </details>
1151
1151
 
1152
1152
  <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.
1153
+ <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
1154
  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
1155
 
1156
1156
  <sub>📄 server.ts</sub>
@@ -1197,6 +1197,32 @@ async function updateRows() {
1197
1197
 
1198
1198
  ```
1199
1199
 
1200
+ __Hono adapter__
1201
+
1202
+ 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.
1203
+
1204
+ <sub>📄 server.ts</sub>
1205
+
1206
+ ```ts
1207
+ import map from './map';
1208
+ import { Hono } from 'hono';
1209
+ import { cors } from 'hono/cors';
1210
+ import { serve } from '@hono/node-server';
1211
+
1212
+ const db = map.sqlite('demo.db');
1213
+ const app = new Hono();
1214
+
1215
+ app.use('/orange', cors());
1216
+ app.use('/orange/*', cors());
1217
+ // for demonstrational purposes, authentication middleware is not shown here.
1218
+ app.all('/orange', db.hono());
1219
+ app.all('/orange/*', db.hono());
1220
+
1221
+ serve({ fetch: app.fetch, port: 3000 });
1222
+ ```
1223
+
1224
+ `baseFilter` and transaction hooks are also supported in `db.hono({...})`, using Hono-style request/response objects.
1225
+
1200
1226
  __Interceptors and base filter__
1201
1227
 
1202
1228
  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 +1589,33 @@ async function getRows() {
1563
1589
  });
1564
1590
  }
1565
1591
  ```
1592
+ __Column-to-column filters__
1593
+ You can compare one column to another column instead of comparing to a constant value.
1594
+ This works both on the same table and across relations.
1595
+
1596
+ ```javascript
1597
+ import map from './map';
1598
+ const db = map.sqlite('demo.db');
1599
+
1600
+ getRows();
1601
+
1602
+ async function getRows() {
1603
+ // equality between related columns
1604
+ const sameName = await db.order.getMany({
1605
+ where: x => x.deliveryAddress.name.eq(x.customer.name)
1606
+ });
1607
+
1608
+ // string pattern match against another column
1609
+ const containsName = await db.order.getMany({
1610
+ where: x => x.deliveryAddress.name.contains(x.customer.name)
1611
+ });
1612
+
1613
+ // column as one of the bounds in between
1614
+ const withColumnBound = await db.customer.getMany({
1615
+ where: x => x.balance.between(x.id, 180)
1616
+ });
1617
+ }
1618
+ ```
1566
1619
  __In__
1567
1620
  ```javascript
1568
1621
  import map from './map';
@@ -1738,6 +1791,21 @@ async function getRows() {
1738
1791
  });
1739
1792
  }
1740
1793
  ```
1794
+ __Count__
1795
+ Use <i>count</i> on a relation in a filter to compare how many related rows match a condition.
1796
+ ```javascript
1797
+ import map from './map';
1798
+ const db = map.sqlite('demo.db');
1799
+
1800
+ getRows();
1801
+
1802
+ async function getRows() {
1803
+ const rows = await db.order.getMany({
1804
+ where: x => x.lines.count().le(1)
1805
+ .and(x.lines.count(line => line.product.contains('guitar')).eq(1))
1806
+ });
1807
+ }
1808
+ ```
1741
1809
 
1742
1810
  </details>
1743
1811
 
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))