@opra/sqb 1.26.3 → 1.27.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
@@ -1,3 +1,26 @@
1
1
  # @opra/sqb
2
2
 
3
- OPRA SQB package.
3
+ [![NPM Version][npm-image]][npm-url]
4
+ [![NPM Downloads][downloads-image]][downloads-url]
5
+ [![CI Tests][ci-test-image]][ci-test-url]
6
+ [![Test Coverage][coveralls-image]][coveralls-url]
7
+
8
+
9
+ ## Support
10
+ You can report bugs and discuss features on the [GitHub issues](https://github.com/panates/opra/issues) page.
11
+
12
+ ## Node Compatibility
13
+ - node >= 20.x
14
+
15
+
16
+ ## License
17
+ Available under [MIT](LICENSE) license.
18
+
19
+ [npm-image]: https://img.shields.io/npm/v/@opra/sqb
20
+ [npm-url]: https://npmjs.org/package/@opra/sqb
21
+ [downloads-image]: https://img.shields.io/npm/dm/@opra/sqb.svg
22
+ [downloads-url]: https://npmjs.org/package/@opra/sqb
23
+ [ci-test-image]: https://github.com/panates/opra/actions/workflows/test.yml/badge.svg
24
+ [ci-test-url]: https://github.com/panates/opra/actions/workflows/test.yml
25
+ [coveralls-image]: https://coveralls.io/repos/github/panates/opra/badge.svg?branch=main
26
+ [coveralls-url]: https://coveralls.io/github/panates/opra?branch=main
@@ -1,10 +1,9 @@
1
1
  import '@opra/core';
2
2
  import type { SQBAdapter } from '../sqb-adapter.js';
3
3
  /**
4
- * Prepare the SQB filter based on the provided filters and options.
4
+ * Prepares the SQB filter based on the provided filters and options.
5
5
  *
6
- * @param {SQBAdapter.FilterInput|SQBAdapter.FilterInput[]} filters - The filter(s) to be applied.
7
- *
8
- * @returns {Expression} - The prepared SQB Expression.
6
+ * @param filters - The filter(s) to be applied. Can be a single filter or an array of filters.
7
+ * @returns The prepared SQB Expression, or `undefined` if no filters are provided.
9
8
  */
10
9
  export default function prepareFilter(filters: SQBAdapter.FilterInput | SQBAdapter.FilterInput[]): any;
@@ -1,13 +1,12 @@
1
1
  import '@opra/core';
2
2
  import { OpraFilter } from '@opra/common';
3
- import * as sqb from '@sqb/builder';
3
+ import { Operators, sql } from '@sqb/builder';
4
4
  import { vg } from 'valgen';
5
5
  /**
6
- * Prepare the SQB filter based on the provided filters and options.
6
+ * Prepares the SQB filter based on the provided filters and options.
7
7
  *
8
- * @param {SQBAdapter.FilterInput|SQBAdapter.FilterInput[]} filters - The filter(s) to be applied.
9
- *
10
- * @returns {Expression} - The prepared SQB Expression.
8
+ * @param filters - The filter(s) to be applied. Can be a single filter or an array of filters.
9
+ * @returns The prepared SQB Expression, or `undefined` if no filters are provided.
11
10
  */
12
11
  export default function prepareFilter(filters) {
13
12
  const filtersArray = Array.isArray(filters) ? filters : [filters];
@@ -27,7 +26,7 @@ export default function prepareFilter(filters) {
27
26
  if (ast)
28
27
  arr.push(ast);
29
28
  }
30
- return arr.length > 1 ? sqb.And(...arr) : arr[0];
29
+ return arr.length > 1 ? sql.And(...arr) : arr[0];
31
30
  }
32
31
  const _isDate = vg.isDate({ trim: 'day' });
33
32
  const _isDateTime = vg.isDate();
@@ -44,12 +43,12 @@ function prepareFilterAst(ast) {
44
43
  return ast.items.map(prepareFilterAst);
45
44
  }
46
45
  if (ast instanceof OpraFilter.NegativeExpression) {
47
- return sqb.Not(prepareFilterAst(ast.expression));
46
+ return sql.Not(prepareFilterAst(ast.expression));
48
47
  }
49
48
  if (ast instanceof OpraFilter.LogicalExpression) {
50
49
  if (ast.op === 'or')
51
- return sqb.Or(...ast.items.map(prepareFilterAst));
52
- return sqb.And(...ast.items.map(prepareFilterAst));
50
+ return sql.Or(...ast.items.map(prepareFilterAst));
51
+ return sql.And(...ast.items.map(prepareFilterAst));
53
52
  }
54
53
  if (ast instanceof OpraFilter.ParenthesizedExpression) {
55
54
  return prepareFilterAst(ast.expression);
@@ -68,33 +67,19 @@ function prepareFilterAst(ast) {
68
67
  return x;
69
68
  }
70
69
  switch (ast.op) {
71
- case '=':
72
- return sqb.Eq(left, right);
73
- case '!=':
74
- return sqb.Ne(left, right);
75
- case '>':
76
- return sqb.Gt(left, right);
77
- case '>=':
78
- return sqb.Gte(left, right);
79
- case '<':
80
- return sqb.Lt(left, right);
81
- case '<=':
82
- return sqb.Lte(left, right);
83
- case 'in':
84
- return sqb.In(left, right);
85
- case '!in':
86
- return sqb.Nin(left, right);
87
70
  case 'like':
88
- return sqb.Like(left, String(right).replace(/\*/g, '%'));
71
+ return sql.Like(left, String(right).replace(/\*/g, '%'));
89
72
  case 'ilike':
90
- return sqb.Ilike(left, String(right).replace(/\*/g, '%'));
73
+ return sql.ILike(left, String(right).replace(/\*/g, '%'));
91
74
  case '!like':
92
- return sqb.NotLike(left, String(right).replace(/\*/g, '%'));
75
+ return sql.NotLike(left, String(right).replace(/\*/g, '%'));
93
76
  case '!ilike':
94
- return sqb.NotILike(left, String(right).replace(/\*/g, '%'));
95
- default:
96
- throw new Error(`ComparisonExpression operator (${ast.op}) not implemented yet`);
77
+ return sql.NotILike(left, String(right).replace(/\*/g, '%'));
97
78
  }
79
+ const fn = Operators[ast.op];
80
+ if (fn)
81
+ return fn(left, right);
82
+ throw new Error(`ComparisonExpression operator (${ast.op}) not implemented yet`);
98
83
  }
99
84
  if (ast instanceof OpraFilter.QualifiedIdentifier ||
100
85
  ast instanceof OpraFilter.Literal) {
@@ -13,7 +13,7 @@ DataTypeFactory._prepareComplexTypeArgs = async function (context, owner, initAr
13
13
  const sqbField = sqbMeta && EntityMetadata.getField(sqbMeta, fieldName);
14
14
  if (!sqbField)
15
15
  continue;
16
- /** Copy type information from sqb metadata to opra */
16
+ /* Copy type information from sqb metadata to opra */
17
17
  if (!fieldSchema.type || fieldSchema.type === Object) {
18
18
  if (isAssociationField(sqbField)) {
19
19
  if (!fieldSchema.type) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opra/sqb",
3
- "version": "1.26.3",
3
+ "version": "1.27.0",
4
4
  "description": "Opra SQB adapter package",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
@@ -10,8 +10,8 @@
10
10
  "valgen": "^6.0.3"
11
11
  },
12
12
  "peerDependencies": {
13
- "@opra/core": "^1.26.3",
14
- "@opra/http": "^1.26.3",
13
+ "@opra/core": "^1.27.0",
14
+ "@opra/http": "^1.27.0",
15
15
  "@sqb/builder": ">4.0.0 <5",
16
16
  "@sqb/connect": ">4.0.0 <5"
17
17
  },
package/sqb-adapter.d.ts CHANGED
@@ -2,20 +2,60 @@ import type { OpraFilter } from '@opra/common';
2
2
  import type { ExecutionContext } from '@opra/core';
3
3
  import { type Repository } from '@sqb/connect';
4
4
  import _prepareFilter from './adapter-utils/prepare-filter.js';
5
+ /**
6
+ * SQBAdapter namespace provides types and utility functions for integrating SQB with Opra.
7
+ */
5
8
  export declare namespace SQBAdapter {
9
+ /**
10
+ * Represents a single identifier type.
11
+ */
6
12
  type Id = string | number | boolean | Date;
13
+ /**
14
+ * Represents a single identifier or a composite key.
15
+ */
7
16
  type IdOrIds = Id | Record<string, Id>;
17
+ /**
18
+ * Represents the input for a filter, which can be an Opra filter expression,
19
+ * a SQB filter object, a string, or undefined.
20
+ */
8
21
  type FilterInput = OpraFilter.Expression | Repository.FindManyOptions['filter'] | string | undefined;
9
22
  /**
10
- * @deprecated Use prepareFilter instead
23
+ * Parses the given filter input into a SQB filter expression.
24
+ * @deprecated Use {@link prepareFilter} instead.
11
25
  */
12
26
  const parseFilter: typeof _prepareFilter;
27
+ /**
28
+ * Prepares the given filter input into a SQB filter expression.
29
+ */
13
30
  const prepareFilter: typeof _prepareFilter;
31
+ /**
32
+ * Represents a request that has been transformed for SQB operations.
33
+ */
14
34
  interface TransformedRequest {
35
+ /**
36
+ * The operation method name.
37
+ */
15
38
  method: 'create' | 'delete' | 'deleteMany' | 'get' | 'replace' | 'findMany' | 'update' | 'updateMany';
39
+ /**
40
+ * The primary key for the operation, if applicable.
41
+ */
16
42
  key?: any;
43
+ /**
44
+ * The data object for create or update operations.
45
+ */
17
46
  data?: any;
47
+ /**
48
+ * Additional options for the SQB operation.
49
+ */
18
50
  options: any;
19
51
  }
52
+ /**
53
+ * Parses an execution context and transforms it into a SQB-compatible request.
54
+ *
55
+ * @param context - The execution context to parse.
56
+ * @returns A promise that resolves to the transformed request.
57
+ * @throws {TypeError} If the context transport is not 'http'.
58
+ * @throws {Error} If the operation is not compatible with SQB Adapter.
59
+ */
20
60
  function parseRequest(context: ExecutionContext): Promise<TransformedRequest>;
21
61
  }
package/sqb-adapter.js CHANGED
@@ -1,12 +1,27 @@
1
1
  import { EntityMetadata } from '@sqb/connect';
2
2
  import _prepareFilter from './adapter-utils/prepare-filter.js';
3
+ /**
4
+ * SQBAdapter namespace provides types and utility functions for integrating SQB with Opra.
5
+ */
3
6
  export var SQBAdapter;
4
7
  (function (SQBAdapter) {
5
8
  /**
6
- * @deprecated Use prepareFilter instead
9
+ * Parses the given filter input into a SQB filter expression.
10
+ * @deprecated Use {@link prepareFilter} instead.
7
11
  */
8
12
  SQBAdapter.parseFilter = _prepareFilter;
13
+ /**
14
+ * Prepares the given filter input into a SQB filter expression.
15
+ */
9
16
  SQBAdapter.prepareFilter = _prepareFilter;
17
+ /**
18
+ * Parses an execution context and transforms it into a SQB-compatible request.
19
+ *
20
+ * @param context - The execution context to parse.
21
+ * @returns A promise that resolves to the transformed request.
22
+ * @throws {TypeError} If the context transport is not 'http'.
23
+ * @throws {Error} If the operation is not compatible with SQB Adapter.
24
+ */
10
25
  async function parseRequest(context) {
11
26
  if (context.transport !== 'http') {
12
27
  throw new TypeError('SQBAdapter can parse only HttpContext');
@@ -37,7 +52,7 @@ export var SQBAdapter;
37
52
  controller.parameters.find(p => p.keyParam);
38
53
  const key = keyParam && ctx.pathParams[String(keyParam.name)];
39
54
  const options = {
40
- filter: SQBAdapter.parseFilter(ctx.queryParams.filter),
55
+ filter: SQBAdapter.prepareFilter(ctx.queryParams.filter),
41
56
  };
42
57
  return {
43
58
  method: 'delete',
@@ -47,14 +62,14 @@ export var SQBAdapter;
47
62
  }
48
63
  case 'Entity.DeleteMany': {
49
64
  const options = {
50
- filter: SQBAdapter.parseFilter(ctx.queryParams.filter),
65
+ filter: SQBAdapter.prepareFilter(ctx.queryParams.filter),
51
66
  };
52
67
  return { method: 'deleteMany', options };
53
68
  }
54
69
  case 'Entity.FindMany': {
55
70
  const options = {
56
71
  count: ctx.queryParams.count,
57
- filter: SQBAdapter.parseFilter(ctx.queryParams.filter),
72
+ filter: SQBAdapter.prepareFilter(ctx.queryParams.filter),
58
73
  projection: ctx.queryParams.projection ||
59
74
  __oprDef.compositionOptions.defaultProjection,
60
75
  limit: ctx.queryParams.limit || __oprDef.compositionOptions.defaultLimit,
@@ -96,7 +111,7 @@ export var SQBAdapter;
96
111
  const key = keyParam && ctx.pathParams[String(keyParam.name)];
97
112
  const options = {
98
113
  projection: ctx.queryParams.projection,
99
- filter: SQBAdapter.parseFilter(ctx.queryParams.filter),
114
+ filter: SQBAdapter.prepareFilter(ctx.queryParams.filter),
100
115
  };
101
116
  return {
102
117
  method: 'update',
@@ -108,7 +123,7 @@ export var SQBAdapter;
108
123
  case 'Entity.UpdateMany': {
109
124
  const data = await ctx.getBody();
110
125
  const options = {
111
- filter: SQBAdapter.parseFilter(ctx.queryParams.filter),
126
+ filter: SQBAdapter.prepareFilter(ctx.queryParams.filter),
112
127
  };
113
128
  return {
114
129
  method: 'updateMany',