@venizia/ignis-filter 0.1.1
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/LICENSE.md +103 -0
- package/README.md +86 -0
- package/dist/cjs/common/index.d.ts +3 -0
- package/dist/cjs/common/index.d.ts.map +1 -0
- package/dist/cjs/common/index.js +19 -0
- package/dist/cjs/common/index.js.map +1 -0
- package/dist/cjs/common/operators.d.ts +49 -0
- package/dist/cjs/common/operators.d.ts.map +1 -0
- package/dist/cjs/common/operators.js +121 -0
- package/dist/cjs/common/operators.js.map +1 -0
- package/dist/cjs/common/types.d.ts +37 -0
- package/dist/cjs/common/types.d.ts.map +1 -0
- package/dist/cjs/common/types.js +4 -0
- package/dist/cjs/common/types.js.map +1 -0
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +18 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/schemas/builder.d.ts +16 -0
- package/dist/cjs/schemas/builder.d.ts.map +1 -0
- package/dist/cjs/schemas/builder.js +131 -0
- package/dist/cjs/schemas/builder.js.map +1 -0
- package/dist/cjs/schemas/common/types.d.ts +9 -0
- package/dist/cjs/schemas/common/types.d.ts.map +1 -0
- package/dist/cjs/schemas/common/types.js +3 -0
- package/dist/cjs/schemas/common/types.js.map +1 -0
- package/dist/cjs/schemas/index.d.ts +5 -0
- package/dist/cjs/schemas/index.d.ts.map +1 -0
- package/dist/cjs/schemas/index.js +24 -0
- package/dist/cjs/schemas/index.js.map +1 -0
- package/dist/esm/common/index.d.ts +3 -0
- package/dist/esm/common/index.d.ts.map +1 -0
- package/dist/esm/common/index.js +3 -0
- package/dist/esm/common/index.js.map +1 -0
- package/dist/esm/common/operators.d.ts +49 -0
- package/dist/esm/common/operators.d.ts.map +1 -0
- package/dist/esm/common/operators.js +116 -0
- package/dist/esm/common/operators.js.map +1 -0
- package/dist/esm/common/types.d.ts +37 -0
- package/dist/esm/common/types.d.ts.map +1 -0
- package/dist/esm/common/types.js +3 -0
- package/dist/esm/common/types.js.map +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/schemas/builder.d.ts +16 -0
- package/dist/esm/schemas/builder.d.ts.map +1 -0
- package/dist/esm/schemas/builder.js +127 -0
- package/dist/esm/schemas/builder.js.map +1 -0
- package/dist/esm/schemas/common/types.d.ts +9 -0
- package/dist/esm/schemas/common/types.d.ts.map +1 -0
- package/dist/esm/schemas/common/types.js +2 -0
- package/dist/esm/schemas/common/types.js.map +1 -0
- package/dist/esm/schemas/index.d.ts +5 -0
- package/dist/esm/schemas/index.d.ts.map +1 -0
- package/dist/esm/schemas/index.js +6 -0
- package/dist/esm/schemas/index.js.map +1 -0
- package/package.json +93 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Ignis Framework License
|
|
2
|
+
|
|
3
|
+
Ignis is a TypeScript Server Infrastructure framework built on [Hono](https://hono.dev/).
|
|
4
|
+
|
|
5
|
+
## MIT License
|
|
6
|
+
|
|
7
|
+
Copyright (c) 2025 VENIZIA Ltd. Co.
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Packages
|
|
30
|
+
|
|
31
|
+
This monorepo contains the following packages, all licensed under MIT:
|
|
32
|
+
|
|
33
|
+
| Package | Description |
|
|
34
|
+
|---------|-------------|
|
|
35
|
+
| `@venizia/ignis` | Core framework - controllers, services, decorators |
|
|
36
|
+
| `@venizia/ignis-boot` | Application bootstrapping & artifact auto-discovery |
|
|
37
|
+
| `@venizia/ignis-helpers` | Utility helpers - logging, cron, Redis, queues, storage |
|
|
38
|
+
| `@venizia/ignis-inversion` | Dependency Injection & IoC container |
|
|
39
|
+
| `@venizia/dev-configs` | Shared ESLint, Prettier, TypeScript configurations |
|
|
40
|
+
| `@venizia/ignis-docs` | Documentation and MCP Server |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Third-Party Dependencies
|
|
45
|
+
|
|
46
|
+
Ignis uses the following open-source libraries. We are grateful to the authors and contributors of these projects.
|
|
47
|
+
|
|
48
|
+
### Core Dependencies
|
|
49
|
+
|
|
50
|
+
| Library | License | Description |
|
|
51
|
+
|---------|---------|-------------|
|
|
52
|
+
| [Hono](https://github.com/honojs/hono) | MIT | Ultrafast web framework |
|
|
53
|
+
| [Zod](https://github.com/colinhacks/zod) | MIT | TypeScript-first schema validation |
|
|
54
|
+
| [Drizzle ORM](https://github.com/drizzle-team/drizzle-orm) | Apache-2.0 | TypeScript ORM |
|
|
55
|
+
| [Jose](https://github.com/panva/jose) | MIT | JavaScript Object Signing and Encryption |
|
|
56
|
+
|
|
57
|
+
### Helpers Dependencies
|
|
58
|
+
|
|
59
|
+
| Library | License | Description |
|
|
60
|
+
|---------|---------|-------------|
|
|
61
|
+
| [Winston](https://github.com/winstonjs/winston) | MIT | Universal logging library |
|
|
62
|
+
| [BullMQ](https://github.com/taskforcesh/bullmq) | MIT | Message queue and job scheduling |
|
|
63
|
+
| [IORedis](https://github.com/redis/ioredis) | MIT | Redis client for Node.js |
|
|
64
|
+
| [MinIO](https://github.com/minio/minio-js) | Apache-2.0 | S3-compatible object storage client |
|
|
65
|
+
| [Axios](https://github.com/axios/axios) | MIT | HTTP client |
|
|
66
|
+
| [Day.js](https://github.com/iamkun/dayjs) | MIT | Date manipulation library |
|
|
67
|
+
| [Cron](https://github.com/kelektiv/node-cron) | MIT | Cron job scheduler |
|
|
68
|
+
| [Socket.IO](https://github.com/socketio/socket.io) | MIT | Real-time bidirectional communication |
|
|
69
|
+
| [MQTT.js](https://github.com/mqttjs/MQTT.js) | MIT | MQTT client |
|
|
70
|
+
|
|
71
|
+
### Utility Dependencies
|
|
72
|
+
|
|
73
|
+
| Library | License | Description |
|
|
74
|
+
|---------|---------|-------------|
|
|
75
|
+
| [Lodash](https://github.com/lodash/lodash) | MIT | Utility library |
|
|
76
|
+
| [reflect-metadata](https://github.com/rbuckton/reflect-metadata) | Apache-2.0 | Metadata reflection API |
|
|
77
|
+
|
|
78
|
+
### Documentation Dependencies
|
|
79
|
+
|
|
80
|
+
| Library | License | Description |
|
|
81
|
+
|---------|---------|-------------|
|
|
82
|
+
| [VitePress](https://github.com/vuejs/vitepress) | MIT | Static site generator |
|
|
83
|
+
| [Fuse.js](https://github.com/krisk/fuse) | Apache-2.0 | Fuzzy search library |
|
|
84
|
+
| [gray-matter](https://github.com/jonschlinkert/gray-matter) | MIT | Front-matter parser |
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Acknowledgments
|
|
89
|
+
|
|
90
|
+
Ignis Framework is inspired by and built upon the work of many open-source projects:
|
|
91
|
+
|
|
92
|
+
- **[Hono](https://hono.dev/)** by Yusuke Wada - The ultrafast web framework that powers Ignis
|
|
93
|
+
- **[LoopBack 4](https://loopback.io/)** by IBM/StrongLoop - Inspiration for the enterprise architecture patterns
|
|
94
|
+
- **[NestJS](https://nestjs.com/)** by Kamil Mysliwiec - Inspiration for decorator-based controllers
|
|
95
|
+
- **[InversifyJS](https://inversify.io/)** - Inspiration for the IoC container design
|
|
96
|
+
|
|
97
|
+
We thank all the maintainers and contributors of these projects for their excellent work.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Contributing
|
|
102
|
+
|
|
103
|
+
By contributing to Ignis, you agree that your contributions will be licensed under the MIT License.
|
package/README.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# @venizia/ignis-filter
|
|
2
|
+
|
|
3
|
+
The engine-neutral query filter vocabulary shared across IGNIS: the filter shape, the operator set,
|
|
4
|
+
and the sort direction constants.
|
|
5
|
+
|
|
6
|
+
It is **isomorphic by construction**. The package resolves to no node builtin and no server-only
|
|
7
|
+
peer, so the same filter language describes a query against a Postgres repository on the server and
|
|
8
|
+
against a WASM database in a browser worker. A guard test bundles the barrel for `target: 'browser'`
|
|
9
|
+
and fails if anything outside `@venizia/ignis-inversion`, `lodash` and `reflect-metadata` enters the
|
|
10
|
+
graph.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
bun add @venizia/ignis-filter
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Applications on `@venizia/ignis` already get everything here re-exported from the core barrel - there
|
|
19
|
+
is no need to add this package to reach `TFilter` or `QueryOperators`. Install it directly when you
|
|
20
|
+
want the vocabulary **without** the server framework, which is the browser case.
|
|
21
|
+
|
|
22
|
+
## What it carries
|
|
23
|
+
|
|
24
|
+
| Export | Purpose |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `TFilter` | `{ where, order, limit, offset, skip, fields, include }` |
|
|
27
|
+
| `TWhere` | Query conditions, with nested `and` / `or` |
|
|
28
|
+
| `TFields` | Field selection - array of names, or an object keyed by name |
|
|
29
|
+
| `TInclusion` | One relation to include, with an optional nested `scope` |
|
|
30
|
+
| `TLimit`, `TOffset`, `TSkip`, `TOrderBy` | The scalar members of the shape |
|
|
31
|
+
| `QueryOperators` | Comparison, pattern, null, array and logical operators, plus `isValid` |
|
|
32
|
+
| `TQueryOperator` | The operator union, derived from the const class |
|
|
33
|
+
| `Sorts` | `ASC` / `DESC`, plus `isValid` |
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { QueryOperators, Sorts, type TFilter } from '@venizia/ignis-filter';
|
|
37
|
+
|
|
38
|
+
const filter: TFilter = {
|
|
39
|
+
where: { status: 'active', createdAt: { [QueryOperators.GTE]: '2026-01-01' } },
|
|
40
|
+
order: [`createdAt ${Sorts.DESC}`],
|
|
41
|
+
limit: 20,
|
|
42
|
+
};
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Validation - the `/schemas` sub-path
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { FilterSchema, WhereSchema } from '@venizia/ignis-filter/schemas';
|
|
49
|
+
|
|
50
|
+
const parsed = FilterSchema.parse({ where: { status: 'active' }, limit: 20 });
|
|
51
|
+
const where = WhereSchema.parse('{"status":"active"}'); // a JSON string parses too
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
A separate entry point on purpose: importing the vocabulary must not drag `zod` into a bundle that
|
|
55
|
+
only needs `QueryOperators`. Available: `FilterSchema`, `WhereSchema`, `FieldsSchema`,
|
|
56
|
+
`InclusionSchema`, `LimitSchema`, `OffsetSchema`, `SkipSchema`, `OrderBySchema`.
|
|
57
|
+
|
|
58
|
+
> **On a server, import these from `@venizia/ignis-core` instead.** The instances here carry no
|
|
59
|
+
> OpenAPI metadata - they validate identically but document nothing, so a route built on them
|
|
60
|
+
> produces an API reference with no descriptions.
|
|
61
|
+
|
|
62
|
+
Need your own metadata layer? `buildQuerySchemas({ decorate })` takes a decorator applied to every
|
|
63
|
+
node, including nested ones:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { buildQuerySchemas } from '@venizia/ignis-filter/schemas';
|
|
67
|
+
|
|
68
|
+
const { FilterSchema } = buildQuerySchemas({
|
|
69
|
+
decorate: (schema, metadata) => schema.describe(metadata.description ?? ''),
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## What it deliberately does not carry
|
|
74
|
+
|
|
75
|
+
- **Any translation to a query language.** Turning a `TFilter` into SQL is engine-specific - the
|
|
76
|
+
Postgres translator is Drizzle-coupled and lives with its connector. Operator support differs per
|
|
77
|
+
engine, and an unsupported operator throws at translation time rather than being dropped from this
|
|
78
|
+
list.
|
|
79
|
+
- **Types inferred from the schemas.** `TFilter<T>` is generic over the entity, so `TFilter<User>`
|
|
80
|
+
rejects `{ where: { notAField: 1 } }`; `z.infer<typeof FilterSchema>` accepts it, because the
|
|
81
|
+
recursive where-clause is `z.ZodType<any>`. The schema describes what arrives over the wire, the
|
|
82
|
+
type describes what application code builds, and they only overlap in the middle.
|
|
83
|
+
|
|
84
|
+
## License
|
|
85
|
+
|
|
86
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/common/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./operators"), exports);
|
|
18
|
+
__exportStar(require("./types"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/common/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,0CAAwB"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type TConstValue } from '@venizia/ignis-inversion';
|
|
2
|
+
/** Sort direction constants for order by clauses. */
|
|
3
|
+
export declare class Sorts {
|
|
4
|
+
static readonly DESC = "desc";
|
|
5
|
+
static readonly ASC = "asc";
|
|
6
|
+
static readonly SCHEMA_SET: Set<string>;
|
|
7
|
+
static isValid(value: string): boolean;
|
|
8
|
+
}
|
|
9
|
+
/** Query operators for building where conditions (comparison, pattern, null, array, logical). */
|
|
10
|
+
export declare class QueryOperators {
|
|
11
|
+
static readonly EQ = "eq";
|
|
12
|
+
static readonly NE = "ne";
|
|
13
|
+
static readonly NEQ = "neq";
|
|
14
|
+
static readonly GT = "gt";
|
|
15
|
+
static readonly GTE = "gte";
|
|
16
|
+
static readonly LT = "lt";
|
|
17
|
+
static readonly LTE = "lte";
|
|
18
|
+
static readonly LIKE = "like";
|
|
19
|
+
static readonly NOT_LIKE = "nlike";
|
|
20
|
+
static readonly ILIKE = "ilike";
|
|
21
|
+
static readonly NOT_ILIKE = "nilike";
|
|
22
|
+
static readonly IS = "is";
|
|
23
|
+
static readonly IS_NOT = "isn";
|
|
24
|
+
static readonly REGEXP = "regexp";
|
|
25
|
+
static readonly IREGEXP = "iregexp";
|
|
26
|
+
static readonly IN = "in";
|
|
27
|
+
static readonly INQ = "inq";
|
|
28
|
+
static readonly NIN = "nin";
|
|
29
|
+
static readonly EXISTS = "exists";
|
|
30
|
+
static readonly NOT_EXISTS = "notExists";
|
|
31
|
+
static readonly BETWEEN = "between";
|
|
32
|
+
static readonly NOT_BETWEEN = "notBetween";
|
|
33
|
+
static readonly CONTAINS = "contains";
|
|
34
|
+
static readonly CONTAINED_BY = "containedBy";
|
|
35
|
+
static readonly OVERLAPS = "overlaps";
|
|
36
|
+
static readonly NOT = "not";
|
|
37
|
+
static readonly AND = "and";
|
|
38
|
+
static readonly OR = "or";
|
|
39
|
+
static readonly SCHEME_SET: Set<string>;
|
|
40
|
+
static readonly LOGICAL_GROUP_OPERATORS: Set<string>;
|
|
41
|
+
static readonly NUMERIC_COMPARISON_OPERATORS: Set<string>;
|
|
42
|
+
/** Checks if operators contain numeric comparisons (used for JSON path numeric casting). */
|
|
43
|
+
static hasNumericComparison(opts: {
|
|
44
|
+
operators: Record<string, any>;
|
|
45
|
+
}): boolean;
|
|
46
|
+
static isValid(orgType: string): boolean;
|
|
47
|
+
}
|
|
48
|
+
export type TQueryOperator = TConstValue<typeof QueryOperators>;
|
|
49
|
+
//# sourceMappingURL=operators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operators.d.ts","sourceRoot":"","sources":["../../../src/common/operators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAItE,qDAAqD;AACrD,qBAAa,KAAK;IAChB,MAAM,CAAC,QAAQ,CAAC,IAAI,UAAU;IAC9B,MAAM,CAAC,QAAQ,CAAC,GAAG,SAAS;IAC5B,MAAM,CAAC,QAAQ,CAAC,UAAU,cAAoC;IAE9D,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;CAGvC;AAeD,iGAAiG;AACjG,qBAAa,cAAc;IACzB,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ;IAC1B,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ;IAC1B,MAAM,CAAC,QAAQ,CAAC,GAAG,SAAS;IAE5B,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ;IAC1B,MAAM,CAAC,QAAQ,CAAC,GAAG,SAAS;IAE5B,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ;IAC1B,MAAM,CAAC,QAAQ,CAAC,GAAG,SAAS;IAE5B,MAAM,CAAC,QAAQ,CAAC,IAAI,UAAU;IAC9B,MAAM,CAAC,QAAQ,CAAC,QAAQ,WAAW;IACnC,MAAM,CAAC,QAAQ,CAAC,KAAK,WAAW;IAChC,MAAM,CAAC,QAAQ,CAAC,SAAS,YAAY;IAErC,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ;IAC1B,MAAM,CAAC,QAAQ,CAAC,MAAM,SAAS;IAC/B,MAAM,CAAC,QAAQ,CAAC,MAAM,YAAY;IAClC,MAAM,CAAC,QAAQ,CAAC,OAAO,aAAa;IAEpC,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ;IAC1B,MAAM,CAAC,QAAQ,CAAC,GAAG,SAAS;IAC5B,MAAM,CAAC,QAAQ,CAAC,GAAG,SAAS;IAE5B,MAAM,CAAC,QAAQ,CAAC,MAAM,YAAY;IAClC,MAAM,CAAC,QAAQ,CAAC,UAAU,eAAe;IAEzC,MAAM,CAAC,QAAQ,CAAC,OAAO,aAAa;IACpC,MAAM,CAAC,QAAQ,CAAC,WAAW,gBAAgB;IAG3C,MAAM,CAAC,QAAQ,CAAC,QAAQ,cAAc;IACtC,MAAM,CAAC,QAAQ,CAAC,YAAY,iBAAiB;IAC7C,MAAM,CAAC,QAAQ,CAAC,QAAQ,cAAc;IAEtC,MAAM,CAAC,QAAQ,CAAC,GAAG,SAAS;IAC5B,MAAM,CAAC,QAAQ,CAAC,GAAG,SAAS;IAC5B,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ;IAE1B,MAAM,CAAC,QAAQ,CAAC,UAAU,cA6BvB;IAEH,MAAM,CAAC,QAAQ,CAAC,uBAAuB,cAAgC;IAEvE,MAAM,CAAC,QAAQ,CAAC,4BAA4B,cAOzC;IAEH,4FAA4F;IAC5F,MAAM,CAAC,oBAAoB,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KAAE,GAAG,OAAO;IAyB9E,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;CAGzC;AAED,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,OAAO,cAAc,CAAC,CAAC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QueryOperators = exports.Sorts = void 0;
|
|
4
|
+
const ignis_inversion_1 = require("@venizia/ignis-inversion");
|
|
5
|
+
// Neutral filter vocabulary shared by every connector. Support differs per engine - unsupported operators throw at translation time rather than being removed from this list.
|
|
6
|
+
/** Sort direction constants for order by clauses. */
|
|
7
|
+
class Sorts {
|
|
8
|
+
static { this.DESC = 'desc'; }
|
|
9
|
+
static { this.ASC = 'asc'; }
|
|
10
|
+
static { this.SCHEMA_SET = new Set([Sorts.ASC, Sorts.DESC]); }
|
|
11
|
+
static isValid(value) {
|
|
12
|
+
return Sorts.SCHEMA_SET.has(value.toLowerCase());
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.Sorts = Sorts;
|
|
16
|
+
/** Asserts a between-style operand is a two-element tuple and reports whether both bounds are numbers. */
|
|
17
|
+
const validateNumericRange = (opts) => {
|
|
18
|
+
const { op, value } = opts;
|
|
19
|
+
if (!Array.isArray(value) || value.length !== 2) {
|
|
20
|
+
throw (0, ignis_inversion_1.getError)({
|
|
21
|
+
message: `[QueryOperators][hasNumericComparison] Invalid '${op}' value | Expected: [min, max] | Got: ${JSON.stringify(value)}`,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return value.every(v => typeof v === 'number');
|
|
25
|
+
};
|
|
26
|
+
/** Query operators for building where conditions (comparison, pattern, null, array, logical). */
|
|
27
|
+
class QueryOperators {
|
|
28
|
+
static { this.EQ = 'eq'; }
|
|
29
|
+
static { this.NE = 'ne'; }
|
|
30
|
+
static { this.NEQ = 'neq'; }
|
|
31
|
+
static { this.GT = 'gt'; }
|
|
32
|
+
static { this.GTE = 'gte'; }
|
|
33
|
+
static { this.LT = 'lt'; }
|
|
34
|
+
static { this.LTE = 'lte'; }
|
|
35
|
+
static { this.LIKE = 'like'; }
|
|
36
|
+
static { this.NOT_LIKE = 'nlike'; }
|
|
37
|
+
static { this.ILIKE = 'ilike'; }
|
|
38
|
+
static { this.NOT_ILIKE = 'nilike'; }
|
|
39
|
+
static { this.IS = 'is'; }
|
|
40
|
+
static { this.IS_NOT = 'isn'; }
|
|
41
|
+
static { this.REGEXP = 'regexp'; }
|
|
42
|
+
static { this.IREGEXP = 'iregexp'; }
|
|
43
|
+
static { this.IN = 'in'; }
|
|
44
|
+
static { this.INQ = 'inq'; }
|
|
45
|
+
static { this.NIN = 'nin'; }
|
|
46
|
+
static { this.EXISTS = 'exists'; }
|
|
47
|
+
static { this.NOT_EXISTS = 'notExists'; }
|
|
48
|
+
static { this.BETWEEN = 'between'; }
|
|
49
|
+
static { this.NOT_BETWEEN = 'notBetween'; }
|
|
50
|
+
// Array Column Operators (PostgreSQL specific)
|
|
51
|
+
static { this.CONTAINS = 'contains'; } // @> array contains
|
|
52
|
+
static { this.CONTAINED_BY = 'containedBy'; } // <@ array is contained by
|
|
53
|
+
static { this.OVERLAPS = 'overlaps'; } // && array overlaps
|
|
54
|
+
static { this.NOT = 'not'; }
|
|
55
|
+
static { this.AND = 'and'; }
|
|
56
|
+
static { this.OR = 'or'; }
|
|
57
|
+
static { this.SCHEME_SET = new Set([
|
|
58
|
+
this.EQ,
|
|
59
|
+
this.NE,
|
|
60
|
+
this.NEQ,
|
|
61
|
+
this.GT,
|
|
62
|
+
this.GTE,
|
|
63
|
+
this.LT,
|
|
64
|
+
this.LTE,
|
|
65
|
+
this.LIKE,
|
|
66
|
+
this.NOT_LIKE,
|
|
67
|
+
this.ILIKE,
|
|
68
|
+
this.NOT_ILIKE,
|
|
69
|
+
this.IS,
|
|
70
|
+
this.IS_NOT,
|
|
71
|
+
this.REGEXP,
|
|
72
|
+
this.IREGEXP,
|
|
73
|
+
this.IN,
|
|
74
|
+
this.INQ,
|
|
75
|
+
this.NIN,
|
|
76
|
+
this.EXISTS,
|
|
77
|
+
this.NOT_EXISTS,
|
|
78
|
+
this.BETWEEN,
|
|
79
|
+
this.NOT_BETWEEN,
|
|
80
|
+
this.CONTAINS,
|
|
81
|
+
this.CONTAINED_BY,
|
|
82
|
+
this.OVERLAPS,
|
|
83
|
+
this.NOT,
|
|
84
|
+
this.AND,
|
|
85
|
+
this.OR,
|
|
86
|
+
]); }
|
|
87
|
+
static { this.LOGICAL_GROUP_OPERATORS = new Set([this.AND, this.OR]); }
|
|
88
|
+
static { this.NUMERIC_COMPARISON_OPERATORS = new Set([
|
|
89
|
+
this.GT,
|
|
90
|
+
this.GTE,
|
|
91
|
+
this.LT,
|
|
92
|
+
this.LTE,
|
|
93
|
+
this.BETWEEN,
|
|
94
|
+
this.NOT_BETWEEN,
|
|
95
|
+
]); }
|
|
96
|
+
/** Checks if operators contain numeric comparisons (used for JSON path numeric casting). */
|
|
97
|
+
static hasNumericComparison(opts) {
|
|
98
|
+
const { operators } = opts;
|
|
99
|
+
let hasNumeric = false;
|
|
100
|
+
for (const op in operators) {
|
|
101
|
+
if (!this.NUMERIC_COMPARISON_OPERATORS.has(op)) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const value = operators[op];
|
|
105
|
+
if (op === this.BETWEEN || op === this.NOT_BETWEEN) {
|
|
106
|
+
const isNumericRange = validateNumericRange({ op, value });
|
|
107
|
+
hasNumeric = hasNumeric || isNumericRange;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (typeof value === 'number') {
|
|
111
|
+
hasNumeric = true;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return hasNumeric;
|
|
115
|
+
}
|
|
116
|
+
static isValid(orgType) {
|
|
117
|
+
return this.SCHEME_SET.has(orgType);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
exports.QueryOperators = QueryOperators;
|
|
121
|
+
//# sourceMappingURL=operators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operators.js","sourceRoot":"","sources":["../../../src/common/operators.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** The filter shape, free of any runtime import. The zod schemas that validate this shape over HTTP stay in `@venizia/ignis-core` - they parse query strings and pull in the OpenAPI layer, which is a server concern. Do not import a value here; the purity guard fails if this file resolves to anything. */
|
|
2
|
+
/** Fields selection - an array of field names to include, or an object keyed by field name (`true` includes, `false` excludes). */
|
|
3
|
+
export type TFields<T = any> = Partial<{
|
|
4
|
+
[K in keyof T]: boolean;
|
|
5
|
+
}> | Array<keyof T>;
|
|
6
|
+
/** Query conditions for selecting data, with nested `and` / `or`. */
|
|
7
|
+
export type TWhere<T = any> = {
|
|
8
|
+
[key in keyof T]?: any;
|
|
9
|
+
} & {
|
|
10
|
+
and?: TWhere<T>[];
|
|
11
|
+
or?: TWhere<T>[];
|
|
12
|
+
};
|
|
13
|
+
/** Single relation inclusion configuration. */
|
|
14
|
+
export type TInclusion = {
|
|
15
|
+
relation: string;
|
|
16
|
+
scope?: TFilter;
|
|
17
|
+
shouldSkipDefaultFilter?: boolean;
|
|
18
|
+
};
|
|
19
|
+
/** Maximum number of items to return. Defaults to 10 for top-level list queries. */
|
|
20
|
+
export type TLimit = number | undefined;
|
|
21
|
+
/** Number of items to offset for pagination. */
|
|
22
|
+
export type TOffset = number | undefined;
|
|
23
|
+
/** Number of items to skip for pagination. */
|
|
24
|
+
export type TSkip = number | undefined;
|
|
25
|
+
/** Sorting order for results - regular columns (`fieldName ASC`) and JSON/JSONB paths (`metadata.field DESC`). */
|
|
26
|
+
export type TOrderBy = string[] | undefined;
|
|
27
|
+
/** Comprehensive filter configuration used across all repository query methods. */
|
|
28
|
+
export type TFilter<T = any> = {
|
|
29
|
+
where?: TWhere<T>;
|
|
30
|
+
fields?: TFields;
|
|
31
|
+
include?: TInclusion[];
|
|
32
|
+
order?: string[];
|
|
33
|
+
limit?: number;
|
|
34
|
+
offset?: number;
|
|
35
|
+
skip?: number;
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/common/types.ts"],"names":[],"mappings":"AAAA,gTAAgT;AAEhT,mIAAmI;AACnI,MAAM,MAAM,OAAO,CAAC,CAAC,GAAG,GAAG,IAAI,OAAO,CAAC;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO;CAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;AAErF,qEAAqE;AACrE,MAAM,MAAM,MAAM,CAAC,CAAC,GAAG,GAAG,IAAI;KAAG,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG;CAAE,GAAG;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAA;CAAE,CAAC;AAEnG,+CAA+C;AAC/C,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC,CAAC;AAEF,oFAAoF;AACpF,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAExC,gDAAgD;AAChD,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAEzC,8CAA8C;AAC9C,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;AAEvC,kHAAkH;AAClH,MAAM,MAAM,QAAQ,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;AAE5C,mFAAmF;AACnF,MAAM,MAAM,OAAO,CAAC,CAAC,GAAG,GAAG,IAAI;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** The filter shape, free of any runtime import. The zod schemas that validate this shape over HTTP stay in `@venizia/ignis-core` - they parse query strings and pull in the OpenAPI layer, which is a server concern. Do not import a value here; the purity guard fails if this file resolves to anything. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/common/types.ts"],"names":[],"mappings":";AAAA,gTAAgT"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./common"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { TSchemaDecorator } from './common/types';
|
|
3
|
+
export declare const buildQuerySchemas: (opts?: {
|
|
4
|
+
decorate?: TSchemaDecorator;
|
|
5
|
+
}) => {
|
|
6
|
+
FieldsSchema: z.ZodOptional<z.ZodUnion<[z.ZodRecord<z.ZodString, z.ZodBoolean>, z.ZodArray<z.ZodString>]>>;
|
|
7
|
+
FilterSchema: any;
|
|
8
|
+
InclusionSchema: any;
|
|
9
|
+
LimitSchema: z.ZodOptional<z.ZodNumber>;
|
|
10
|
+
OffsetSchema: z.ZodOptional<z.ZodNumber>;
|
|
11
|
+
OrderBySchema: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
12
|
+
SkipSchema: z.ZodOptional<z.ZodNumber>;
|
|
13
|
+
WhereSchema: z.ZodUnion<readonly [z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>, z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<any, string>>, z.ZodType<any, unknown, z.core.$ZodTypeInternals<any, unknown>>>]>;
|
|
14
|
+
};
|
|
15
|
+
export type TQuerySchemas = ReturnType<typeof buildQuerySchemas>;
|
|
16
|
+
//# sourceMappingURL=builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../src/schemas/builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAOvD,eAAO,MAAM,iBAAiB,GAAI,OAAO;IAAE,QAAQ,CAAC,EAAE,gBAAgB,CAAA;CAAE;;;;;;;;;CA8JvE,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildQuerySchemas = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
/** The schemas are built by a factory rather than declared at module scope because documentation metadata has to be injected. `.openapi()` returns a NEW schema instead of mutating, and three of these decorations sit on inner nodes of a nested tree, so a consumer cannot annotate them after the tree is composed - the outer node would still hold the undecorated children. */
|
|
6
|
+
/** Built with plain `zod`, never `@hono/zod-openapi`: the OpenAPI layer pulls in Hono, and these schemas must stay usable in a browser. `@hono/zod-openapi` declares `zod` as a peer, so it patches the same prototype - a server that imports it can decorate these schemas even though they were built without it. */
|
|
7
|
+
const identityDecorator = schema => schema;
|
|
8
|
+
const buildQuerySchemas = (opts) => {
|
|
9
|
+
const decorate = opts?.decorate ?? identityDecorator;
|
|
10
|
+
const LimitSchema = decorate(zod_1.z.number().optional(), {
|
|
11
|
+
description: 'Maximum number of items to return. Defaults to 10 for top-level list queries.',
|
|
12
|
+
examples: [1, 2, 3],
|
|
13
|
+
});
|
|
14
|
+
const OffsetSchema = decorate(zod_1.z.number().optional(), {
|
|
15
|
+
description: 'Number of items to offset for pagination.',
|
|
16
|
+
examples: [1, 2, 3],
|
|
17
|
+
});
|
|
18
|
+
const SkipSchema = decorate(zod_1.z.number().optional(), {
|
|
19
|
+
description: 'Number of items to skip for pagination.',
|
|
20
|
+
examples: [1, 2, 3],
|
|
21
|
+
});
|
|
22
|
+
const OrderBySchema = decorate(zod_1.z.array(zod_1.z.string()).optional(), {
|
|
23
|
+
description: "Sorting order for results. Supports regular columns ('fieldName ASC') and JSON/JSONB paths ('metadata.field DESC', 'data.nested[0].value ASC').",
|
|
24
|
+
examples: [
|
|
25
|
+
'id DESC',
|
|
26
|
+
'createdAt ASC',
|
|
27
|
+
'metadata.priority DESC',
|
|
28
|
+
'data.nested.value ASC',
|
|
29
|
+
'items[0].score DESC',
|
|
30
|
+
],
|
|
31
|
+
});
|
|
32
|
+
const FieldsSchema = decorate(zod_1.z.record(zod_1.z.string(), zod_1.z.boolean()).or(zod_1.z.array(zod_1.z.string())).optional(), {
|
|
33
|
+
description: 'Fields selection - either an array of field names to include, or an object with field names as keys and boolean values (true to include, false to exclude)',
|
|
34
|
+
examples: [
|
|
35
|
+
JSON.stringify(['id', 'name', 'email']),
|
|
36
|
+
JSON.stringify({ id: true, name: true }),
|
|
37
|
+
JSON.stringify({ id: true, name: true, email: true, fullName: false }),
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
/** @internal Recursive schema for where clause validation with nested AND/OR. */
|
|
41
|
+
const RecursiveWhereSchema = zod_1.z.lazy(() => zod_1.z.record(zod_1.z.string(), zod_1.z.any()).and(zod_1.z.object({
|
|
42
|
+
and: zod_1.z.array(RecursiveWhereSchema).optional(),
|
|
43
|
+
or: zod_1.z.array(RecursiveWhereSchema).optional(),
|
|
44
|
+
})));
|
|
45
|
+
const WhereSchema = decorate(zod_1.z.union([
|
|
46
|
+
RecursiveWhereSchema,
|
|
47
|
+
zod_1.z
|
|
48
|
+
.string()
|
|
49
|
+
.transform(val => {
|
|
50
|
+
if (val) {
|
|
51
|
+
return JSON.parse(val);
|
|
52
|
+
}
|
|
53
|
+
return undefined;
|
|
54
|
+
})
|
|
55
|
+
.pipe(RecursiveWhereSchema),
|
|
56
|
+
]), { type: 'object', description: 'Query conditions for selecting data.' });
|
|
57
|
+
/** Zod schema for including related entities in queries with optional nested filtering. */
|
|
58
|
+
const InclusionSchema = decorate(zod_1.z
|
|
59
|
+
.array(zod_1.z.object({
|
|
60
|
+
relation: decorate(zod_1.z.string(), { description: 'Model relation name' }),
|
|
61
|
+
scope: decorate(zod_1.z
|
|
62
|
+
.lazy(() => FilterSchema) // eslint-disable-line @typescript-eslint/no-use-before-define
|
|
63
|
+
.optional(), { description: 'Model relation filter' }),
|
|
64
|
+
shouldSkipDefaultFilter: decorate(zod_1.z.boolean().optional(), {
|
|
65
|
+
description: 'Skip the default filter for this relation',
|
|
66
|
+
}),
|
|
67
|
+
}))
|
|
68
|
+
.optional(), {
|
|
69
|
+
description: 'Define related models to include in the response.',
|
|
70
|
+
examples: [
|
|
71
|
+
JSON.stringify({ include: [{ relation: 'posts' }] }),
|
|
72
|
+
JSON.stringify({ include: [{ relation: 'posts', scope: { limit: 5 } }] }),
|
|
73
|
+
],
|
|
74
|
+
});
|
|
75
|
+
/** @internal Filter schema object definition. */
|
|
76
|
+
const InternalFilterSchema = zod_1.z.object({
|
|
77
|
+
where: WhereSchema.optional(),
|
|
78
|
+
fields: FieldsSchema,
|
|
79
|
+
include: InclusionSchema,
|
|
80
|
+
order: OrderBySchema,
|
|
81
|
+
limit: LimitSchema,
|
|
82
|
+
offset: OffsetSchema,
|
|
83
|
+
skip: SkipSchema,
|
|
84
|
+
});
|
|
85
|
+
/** Comprehensive Zod schema for repository query filtering. Supports object and JSON string formats. */
|
|
86
|
+
const FilterSchema = decorate(zod_1.z
|
|
87
|
+
.union([
|
|
88
|
+
InternalFilterSchema,
|
|
89
|
+
zod_1.z
|
|
90
|
+
.string()
|
|
91
|
+
.transform(val => {
|
|
92
|
+
if (val) {
|
|
93
|
+
return JSON.parse(val);
|
|
94
|
+
}
|
|
95
|
+
return {};
|
|
96
|
+
})
|
|
97
|
+
.pipe(InternalFilterSchema),
|
|
98
|
+
])
|
|
99
|
+
.optional(), {
|
|
100
|
+
type: 'object',
|
|
101
|
+
description: 'A comprehensive filter object for querying data, including conditions, field selection, relations, pagination, and sorting.',
|
|
102
|
+
examples: [
|
|
103
|
+
JSON.stringify({ where: { name: 'John Doe' }, limit: 10 }),
|
|
104
|
+
JSON.stringify({
|
|
105
|
+
fields: { id: true, name: true, email: true },
|
|
106
|
+
order: ['createdAt DESC'],
|
|
107
|
+
}),
|
|
108
|
+
JSON.stringify({ include: [{ relation: 'posts', scope: { limit: 5 } }] }),
|
|
109
|
+
JSON.stringify({
|
|
110
|
+
where: { or: [{ status: 'active' }, { isPublished: true }] },
|
|
111
|
+
skip: 20,
|
|
112
|
+
limit: 10,
|
|
113
|
+
}),
|
|
114
|
+
JSON.stringify({
|
|
115
|
+
where: { and: [{ role: 'admin' }, { createdAt: { gte: 'YYYY-MM-DD' } }] },
|
|
116
|
+
}),
|
|
117
|
+
],
|
|
118
|
+
});
|
|
119
|
+
return {
|
|
120
|
+
FieldsSchema,
|
|
121
|
+
FilterSchema,
|
|
122
|
+
InclusionSchema,
|
|
123
|
+
LimitSchema,
|
|
124
|
+
OffsetSchema,
|
|
125
|
+
OrderBySchema,
|
|
126
|
+
SkipSchema,
|
|
127
|
+
WhereSchema,
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
exports.buildQuerySchemas = buildQuerySchemas;
|
|
131
|
+
//# sourceMappingURL=builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../../src/schemas/builder.ts"],"names":[],"mappings":"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"}
|