@eienjs/adonisjs-api-query 1.1.1 → 3.0.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/{LICENSE.md → LICENSE} +1 -1
- package/README.md +166 -2
- package/build/configure.d.ts +2 -2
- package/build/configure.js +10 -0
- package/build/index.d.ts +38 -31
- package/build/index.js +38 -154
- package/build/providers/api_query_provider.d.ts +48 -37
- package/build/providers/api_query_provider.js +26 -27
- package/build/src/allowed_filter.d.ts +44 -36
- package/build/src/allowed_filter.js +135 -0
- package/build/src/allowed_include.d.ts +15 -16
- package/build/src/allowed_include.js +47 -0
- package/build/src/allowed_sort.d.ts +17 -17
- package/build/src/allowed_sort.js +49 -0
- package/build/src/api_query_builder_request.d.ts +55 -30
- package/build/src/api_query_builder_request.js +200 -0
- package/build/src/base_filterable.d.ts +45 -0
- package/build/src/base_filterable.js +172 -0
- package/build/src/bindings/api_query_request.js +13 -0
- package/build/src/bindings/filterable_query.js +51 -0
- package/build/src/bindings/filters_query.js +38 -0
- package/build/src/bindings/includes_query.js +50 -0
- package/build/src/bindings/sorts_query.js +42 -0
- package/build/src/bindings/validation_query.js +27 -0
- package/build/src/decorators/filterable.d.ts +20 -0
- package/build/src/decorators/filterable.js +24 -0
- package/build/src/define_config.d.ts +3 -3
- package/build/src/define_config.js +25 -0
- package/build/src/enums/filter_operator.d.ts +8 -9
- package/build/src/enums/filter_operator.js +11 -0
- package/build/src/enums/sort_direction.d.ts +3 -4
- package/build/src/enums/sort_direction.js +6 -0
- package/build/src/exceptions/allowed_fields_must_be_called_before_allowed_includes.d.ts +5 -5
- package/build/src/exceptions/allowed_fields_must_be_called_before_allowed_includes.js +10 -0
- package/build/src/exceptions/filterable_not_configured.d.ts +5 -0
- package/build/src/exceptions/filterable_not_configured.js +12 -0
- package/build/src/exceptions/invalid_append_query.d.ts +6 -4
- package/build/src/exceptions/invalid_append_query.js +17 -0
- package/build/src/exceptions/invalid_direction.d.ts +3 -3
- package/build/src/exceptions/invalid_direction.js +9 -0
- package/build/src/exceptions/invalid_field_query.d.ts +6 -4
- package/build/src/exceptions/invalid_field_query.js +17 -0
- package/build/src/exceptions/invalid_filter_query.d.ts +6 -6
- package/build/src/exceptions/invalid_filter_query.js +17 -0
- package/build/src/exceptions/invalid_filter_value.d.ts +3 -3
- package/build/src/exceptions/invalid_filter_value.js +8 -0
- package/build/src/exceptions/invalid_include_query.d.ts +6 -6
- package/build/src/exceptions/invalid_include_query.js +21 -0
- package/build/src/exceptions/invalid_query.d.ts +3 -3
- package/build/{chunk-XIRHVLVQ.js → src/exceptions/invalid_query.js} +3 -7
- package/build/src/exceptions/invalid_sort_query.d.ts +6 -6
- package/build/src/exceptions/invalid_sort_query.js +17 -0
- package/build/src/exceptions/unknown_included_fields_query.d.ts +4 -4
- package/build/src/exceptions/unknown_included_fields_query.js +12 -0
- package/build/src/exceptions/vine_not_installed.d.ts +5 -0
- package/build/src/exceptions/vine_not_installed.js +12 -0
- package/build/src/filters/filters_begin_with_strict.d.ts +6 -6
- package/build/src/filters/filters_begin_with_strict.js +8 -0
- package/build/src/filters/filters_callback.d.ts +6 -6
- package/build/src/filters/filters_callback.js +11 -0
- package/build/src/filters/filters_ends_with_strict.d.ts +6 -6
- package/build/src/filters/filters_ends_with_strict.js +8 -0
- package/build/src/filters/filters_exact.d.ts +11 -11
- package/build/src/filters/filters_exact.js +50 -0
- package/build/src/filters/filters_operator.d.ts +13 -13
- package/build/src/filters/filters_operator.js +52 -0
- package/build/src/filters/filters_partial.d.ts +9 -11
- package/build/src/filters/filters_partial.js +37 -0
- package/build/src/filters/filters_scope.d.ts +12 -0
- package/build/src/filters/filters_scope.js +98 -0
- package/build/src/filters/filters_trashed.d.ts +5 -5
- package/build/src/filters/filters_trashed.js +13 -0
- package/build/src/includes/included_callback.d.ts +7 -7
- package/build/src/includes/included_callback.js +11 -0
- package/build/src/includes/included_count.d.ts +4 -4
- package/build/src/includes/included_count.js +11 -0
- package/build/src/includes/included_relationship.d.ts +8 -8
- package/build/src/includes/included_relationship.js +37 -0
- package/build/src/sorts/sorts_callback.d.ts +6 -6
- package/build/src/sorts/sorts_callback.js +11 -0
- package/build/src/sorts/sorts_field.d.ts +4 -4
- package/build/src/sorts/sorts_field.js +7 -0
- package/build/src/utils/helpers.js +14 -0
- package/build/src/validation/schema_builder.d.ts +3 -0
- package/build/src/validation/schema_builder.js +38 -0
- package/build/src/validation/vine_resolver.js +13 -0
- package/build/stubs/main.d.ts +1 -1
- package/build/stubs/main.js +3 -0
- package/build/types.d.ts +116 -0
- package/build/types.js +1 -0
- package/package.json +101 -88
- package/build/api_query_request-QXOB4BN6.js +0 -18
- package/build/api_query_request-QXOB4BN6.js.map +0 -1
- package/build/chunk-3ITWUZL5.js +0 -108
- package/build/chunk-3ITWUZL5.js.map +0 -1
- package/build/chunk-54HNQTDY.js +0 -348
- package/build/chunk-54HNQTDY.js.map +0 -1
- package/build/chunk-IV3B5WO7.js +0 -160
- package/build/chunk-IV3B5WO7.js.map +0 -1
- package/build/chunk-MKQ3HMMA.js +0 -198
- package/build/chunk-MKQ3HMMA.js.map +0 -1
- package/build/chunk-XIRHVLVQ.js.map +0 -1
- package/build/filters_query-LCFH2F2X.js +0 -55
- package/build/filters_query-LCFH2F2X.js.map +0 -1
- package/build/includes_query-PVONWQMC.js +0 -70
- package/build/includes_query-PVONWQMC.js.map +0 -1
- package/build/index.js.map +0 -1
- package/build/metafile-esm.json +0 -1
- package/build/providers/api_query_provider.js.map +0 -1
- package/build/sorts_query-NJTC5UXX.js +0 -63
- package/build/sorts_query-NJTC5UXX.js.map +0 -1
- package/build/src/bindings/api_query_request.d.ts +0 -2
- package/build/src/bindings/filters_query.d.ts +0 -3
- package/build/src/bindings/includes_query.d.ts +0 -3
- package/build/src/bindings/sorts_query.d.ts +0 -3
- package/build/src/types.d.ts +0 -90
- package/build/src/types.js +0 -1
- package/build/src/types.js.map +0 -1
- package/build/src/utils/helpers.d.ts +0 -3
- /package/build/{config.stub → stubs/config.stub} +0 -0
package/{LICENSE.md → LICENSE}
RENAMED
package/README.md
CHANGED
|
@@ -7,12 +7,176 @@
|
|
|
7
7
|
[![Build Status][badge-build]][build]
|
|
8
8
|
[![Total Downloads][badge-downloads]][downloads]
|
|
9
9
|
|
|
10
|
-
> Easily build Lucid queries from API requests
|
|
10
|
+
> Easily build Lucid queries from API requests for your AdonisJS v7 application.
|
|
11
11
|
|
|
12
12
|
## Introduction
|
|
13
13
|
|
|
14
14
|
This package provides a set of macros on `ModelQueryBuilder` to build [Lucid](https://adonisjs.com/docs/lucid) queries from API requests. Inspired by [Spatie's Laravel Query Builder](https://github.com/spatie/laravel-query-builder).
|
|
15
15
|
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
Install the package using the following command:
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
node ace add @eienjs/adonisjs-api-query
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Automatically the command will register the provider. Now you can use with your controller response:
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
28
|
+
import User from '#models/user';
|
|
29
|
+
|
|
30
|
+
// inside a controller
|
|
31
|
+
export default class MyController {
|
|
32
|
+
public async handle({ request }: HttpContext) {
|
|
33
|
+
const users = await User.query()
|
|
34
|
+
.withRequest(request) // Pass the request to the query builder if async local storage is not enabled
|
|
35
|
+
.allowedFilters('name')
|
|
36
|
+
.allowedIncludes('posts')
|
|
37
|
+
.allowedSorts('id');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Using Filterable Classes
|
|
43
|
+
|
|
44
|
+
Instead of configuring allowed filters, sorts, and includes directly in your controller, you can encapsulate them in a dedicated filterable class extending `BaseFilterable`:
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
// app/filters/user_filterable.ts
|
|
48
|
+
import { AllowedFilter, BaseFilterable } from '@eienjs/adonisjs-api-query';
|
|
49
|
+
import User from '#models/user';
|
|
50
|
+
|
|
51
|
+
export default class UserFilterable extends BaseFilterable.for(() => User) {
|
|
52
|
+
// Allowed filters: columns, AllowedFilter instances, or custom methods
|
|
53
|
+
public filters = [
|
|
54
|
+
'name',
|
|
55
|
+
'status',
|
|
56
|
+
AllowedFilter.exact('email'),
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
// Allowed sorts and default sorts
|
|
60
|
+
public sorts = ['name', 'createdAt'];
|
|
61
|
+
|
|
62
|
+
public defaultSorts = '-createdAt';
|
|
63
|
+
|
|
64
|
+
// Allowed relationship includes
|
|
65
|
+
public includes = ['posts', 'profile'];
|
|
66
|
+
|
|
67
|
+
// Optional setup hook to customize/initialize the query builder
|
|
68
|
+
public setup(query) {
|
|
69
|
+
query.where('isActive', true);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Custom filter method (auto-bound to 'status' filter)
|
|
73
|
+
public filterStatus(query, value: unknown) {
|
|
74
|
+
void query.where('status', value as string);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Attach the filterable class to your Lucid Model using `static $filterable`, `@filterable` decorator, or `Filterable` mixin:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
// app/models/user.ts
|
|
83
|
+
import { BaseModel } from '@adonisjs/lucid/orm';
|
|
84
|
+
import UserFilterable from '#filters/user_filterable';
|
|
85
|
+
|
|
86
|
+
export default class User extends BaseModel {
|
|
87
|
+
// Using a lazy thunk prevents circular dependency issues in ESM
|
|
88
|
+
public static $filterable = () => UserFilterable;
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Now you can run the filtered query in controllers using `User.$filter(request)`:
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// inside a controller
|
|
96
|
+
export default class UsersController {
|
|
97
|
+
public async index({ request }: HttpContext) {
|
|
98
|
+
// Fluent query builder with filters, sorts, includes, and setup automatically applied
|
|
99
|
+
return await User.$filter(request).paginate(1, 15);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
You can also use it directly on existing queries via `query.filter(request)`, or query directly from the filterable class:
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
// On an existing query builder instance
|
|
108
|
+
const admins = await User.query().where('role', 'admin').filter(request);
|
|
109
|
+
|
|
110
|
+
// With an explicit filterable class
|
|
111
|
+
const special = await User.$filter(SpecialUserFilterable, request);
|
|
112
|
+
|
|
113
|
+
// Or directly from the filterable class
|
|
114
|
+
const users = await UserFilterable.$query(request);
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Request Validation with VineJS (Optional)
|
|
118
|
+
|
|
119
|
+
You can validate incoming API query parameters (`filter`, `sort`, `include`, etc.) using `@vinejs/vine`. Validation is 100% optional: `@vinejs/vine` is declared as an optional peer dependency (`>=4.4.0`).
|
|
120
|
+
|
|
121
|
+
#### 1. Defining Rules on a Filterable Class
|
|
122
|
+
|
|
123
|
+
Declare explicit validation rules using VineJS on your filterable class. You can pass a literal plain object, a `vine.object(...)`, or a compiled `vine.create(...)` directly to `rules`:
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { AllowedFilter, BaseFilterable } from '@eienjs/adonisjs-api-query';
|
|
127
|
+
import vine from '@vinejs/vine';
|
|
128
|
+
import User from '#models/user';
|
|
129
|
+
|
|
130
|
+
export default class UserFilterable extends BaseFilterable.for(() => User) {
|
|
131
|
+
public filters = [
|
|
132
|
+
'name',
|
|
133
|
+
'status',
|
|
134
|
+
AllowedFilter.exact('createdAt').rule(vine.date()),
|
|
135
|
+
AllowedFilter.exact('age').rule(vine.number().min(18)),
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
public sorts = ['name', 'createdAt'];
|
|
139
|
+
|
|
140
|
+
// You can define rules as a literal object, vine.object(), or vine.create():
|
|
141
|
+
public rules = vine.object({
|
|
142
|
+
filter: vine.object({
|
|
143
|
+
name: vine.string().minLength(3).optional(),
|
|
144
|
+
status: vine.enum(['active', 'inactive']).optional(),
|
|
145
|
+
}).optional(),
|
|
146
|
+
sort: vine.string().optional(),
|
|
147
|
+
include: vine.string().optional(),
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
#### 2. Automatic & Explicit Validation
|
|
153
|
+
|
|
154
|
+
- **Automatic validation during query execution**: When `rules` or `validator` are defined on a filterable class (or on `AllowedFilter.rule(...)`), the query builder automatically executes validation with VineJS before querying the database. If validation fails, it throws a native `ValidationError` (`errors.E_VALIDATION_ERROR`), which AdonisJS automatically transforms into HTTP 422 Unprocessable Entity:
|
|
155
|
+
```typescript
|
|
156
|
+
// Automatically validates before hitting the database:
|
|
157
|
+
const users = await User.$filter(request).paginate(1, 15);
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
- **Explicit validation & Controller usage**:
|
|
161
|
+
Validation resides directly inside `ApiQueryBuilderRequest` as the central core of the package:
|
|
162
|
+
```typescript
|
|
163
|
+
// Validate request explicitly via filterable:
|
|
164
|
+
const payload = await UserFilterable.validate(request);
|
|
165
|
+
|
|
166
|
+
// Validate and get the query builder:
|
|
167
|
+
const users = await UserFilterable.$validateAndQuery(request);
|
|
168
|
+
|
|
169
|
+
// Or validate directly via ApiQueryBuilderRequest in controllers:
|
|
170
|
+
const apiRequest = new ApiQueryBuilderRequest(request);
|
|
171
|
+
const validated = await apiRequest.validate({
|
|
172
|
+
filter: vine.object({ name: vine.string() }).optional(),
|
|
173
|
+
sort: vine.string().optional(),
|
|
174
|
+
});
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
- **Disabling automatic validation**:
|
|
178
|
+
You can disable automatic validation per-filterable with `public autoValidate = false;` or globally in `config/apiquery.ts` with `autoValidate: false`.
|
|
179
|
+
|
|
16
180
|
## Documentation
|
|
17
181
|
|
|
18
182
|
The documentation is available on [EienJS](https://eienjs.com/packages/adonisjs-api-query/getting-started/).
|
|
@@ -30,7 +194,7 @@ The `@eienjs/adonisjs-api-query` library is licensed for use under the MIT Licen
|
|
|
30
194
|
[source]: https://github.com/eienjs/adonisjs-api-query
|
|
31
195
|
[node-version]: https://www.npmjs.com/package/@eienjs/adonisjs-api-query
|
|
32
196
|
[release]: https://www.npmjs.com/package/@eienjs/adonisjs-api-query
|
|
33
|
-
[license]: https://github.com/eienjs/adonisjs-api-query/blob/main/LICENSE
|
|
197
|
+
[license]: https://github.com/eienjs/adonisjs-api-query/blob/main/LICENSE
|
|
34
198
|
[build]: https://github.com/eienjs/adonisjs-api-query/actions/workflows/build.yml?query=branch:main
|
|
35
199
|
[downloads]: https://www.npmjs.com/package/@eienjs/adonisjs-api-query
|
|
36
200
|
[badge-source]: https://img.shields.io/badge/source-eienjs/adonisjs--api--query-blue.svg?logo=github
|
package/build/configure.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
export declare const configure: (command: Configure) => Promise<void>;
|
|
1
|
+
import Configure from "@adonisjs/core/commands/configure";
|
|
2
|
+
export declare const configure: (command: Configure) => Promise<void>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { stubsRoot } from "./stubs/main.js";
|
|
2
|
+
// configure.ts
|
|
3
|
+
const configure = async (command) => {
|
|
4
|
+
const codemods = await command.createCodemods();
|
|
5
|
+
await codemods.updateRcFile((rcFile) => {
|
|
6
|
+
rcFile.addProvider("@eienjs/adonisjs-api-query/providers/api_query_provider");
|
|
7
|
+
});
|
|
8
|
+
await codemods.makeUsingStub(stubsRoot, "config.stub", {});
|
|
9
|
+
};
|
|
10
|
+
export { configure };
|
package/build/index.d.ts
CHANGED
|
@@ -1,31 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
1
|
+
import { configure } from "./configure.js";
|
|
2
|
+
import { FilterOperator } from "./src/enums/filter_operator.js";
|
|
3
|
+
import { AllowedInclude } from "./src/allowed_include.js";
|
|
4
|
+
import { AllowedSort } from "./src/allowed_sort.js";
|
|
5
|
+
import { ApiQueryBuilderRequest } from "./src/api_query_builder_request.js";
|
|
6
|
+
import { BaseFilterable } from "./src/base_filterable.js";
|
|
7
|
+
import { AllowedFilter } from "./src/allowed_filter.js";
|
|
8
|
+
import { Filterable, filterable } from "./src/decorators/filterable.js";
|
|
9
|
+
import { defineConfig } from "./src/define_config.js";
|
|
10
|
+
import { SortDirection } from "./src/enums/sort_direction.js";
|
|
11
|
+
import { AllowedFieldsMustBeCalledBeforeAllowedIncludes } from "./src/exceptions/allowed_fields_must_be_called_before_allowed_includes.js";
|
|
12
|
+
import { FilterableNotConfigured } from "./src/exceptions/filterable_not_configured.js";
|
|
13
|
+
import { InvalidQuery } from "./src/exceptions/invalid_query.js";
|
|
14
|
+
import { InvalidAppendQuery } from "./src/exceptions/invalid_append_query.js";
|
|
15
|
+
import { InvalidDirection } from "./src/exceptions/invalid_direction.js";
|
|
16
|
+
import { InvalidFieldQuery } from "./src/exceptions/invalid_field_query.js";
|
|
17
|
+
import { InvalidFilterQuery } from "./src/exceptions/invalid_filter_query.js";
|
|
18
|
+
import { InvalidFilterValue } from "./src/exceptions/invalid_filter_value.js";
|
|
19
|
+
import { InvalidIncludeQuery } from "./src/exceptions/invalid_include_query.js";
|
|
20
|
+
import { InvalidSortQuery } from "./src/exceptions/invalid_sort_query.js";
|
|
21
|
+
import { UnknownIncludedFieldsQuery } from "./src/exceptions/unknown_included_fields_query.js";
|
|
22
|
+
import { VineNotInstalledException } from "./src/exceptions/vine_not_installed.js";
|
|
23
|
+
import { FiltersExact } from "./src/filters/filters_exact.js";
|
|
24
|
+
import { FiltersPartial } from "./src/filters/filters_partial.js";
|
|
25
|
+
import { FiltersBeginWithStrict } from "./src/filters/filters_begin_with_strict.js";
|
|
26
|
+
import { FiltersCallback } from "./src/filters/filters_callback.js";
|
|
27
|
+
import { FiltersEndsWithStrict } from "./src/filters/filters_ends_with_strict.js";
|
|
28
|
+
import { FiltersOperator } from "./src/filters/filters_operator.js";
|
|
29
|
+
import { FiltersScope } from "./src/filters/filters_scope.js";
|
|
30
|
+
import { FiltersTrashed } from "./src/filters/filters_trashed.js";
|
|
31
|
+
import { IncludedCallback } from "./src/includes/included_callback.js";
|
|
32
|
+
import { IncludedCount } from "./src/includes/included_count.js";
|
|
33
|
+
import { IncludedRelationship } from "./src/includes/included_relationship.js";
|
|
34
|
+
import { SortsCallback } from "./src/sorts/sorts_callback.js";
|
|
35
|
+
import { SortsField } from "./src/sorts/sorts_field.js";
|
|
36
|
+
import { buildQueryValidator } from "./src/validation/schema_builder.js";
|
|
37
|
+
import { stubsRoot } from "./stubs/main.js";
|
|
38
|
+
export { AllowedFieldsMustBeCalledBeforeAllowedIncludes, AllowedFilter, AllowedInclude, AllowedSort, ApiQueryBuilderRequest, BaseFilterable, FilterOperator, Filterable, FilterableNotConfigured, FiltersBeginWithStrict, FiltersCallback, FiltersEndsWithStrict, FiltersExact, FiltersOperator, FiltersPartial, FiltersScope, FiltersTrashed, IncludedCallback, IncludedCount, IncludedRelationship, InvalidAppendQuery, InvalidDirection, InvalidFieldQuery, InvalidFilterQuery, InvalidFilterValue, InvalidIncludeQuery, InvalidQuery, InvalidSortQuery, SortDirection, SortsCallback, SortsField, UnknownIncludedFieldsQuery, VineNotInstalledException, buildQueryValidator, configure, defineConfig, filterable, stubsRoot };
|
package/build/index.js
CHANGED
|
@@ -1,154 +1,38 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from "./
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
} from "./
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
} from "./
|
|
24
|
-
import {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
} from "./
|
|
31
|
-
import {
|
|
32
|
-
|
|
33
|
-
} from "./
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
import
|
|
37
|
-
import {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
// configure.ts
|
|
41
|
-
var configure = async (command) => {
|
|
42
|
-
const codemods = await command.createCodemods();
|
|
43
|
-
await codemods.updateRcFile((rcFile) => {
|
|
44
|
-
rcFile.addProvider("@eienjs/adonisjs-api-query/api_query_provider");
|
|
45
|
-
});
|
|
46
|
-
await codemods.makeUsingStub(stubsRoot, "config.stub", {});
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
// src/define_config.ts
|
|
50
|
-
import { configProvider } from "@adonisjs/core";
|
|
51
|
-
var defineConfig = function(config) {
|
|
52
|
-
return configProvider.create(async (_) => {
|
|
53
|
-
return {
|
|
54
|
-
parameters: {
|
|
55
|
-
include: config.parameters?.include ?? "include",
|
|
56
|
-
filter: config.parameters?.filter ?? "filter",
|
|
57
|
-
sort: config.parameters?.sort ?? "sort",
|
|
58
|
-
fields: config.parameters?.fields ?? "fields",
|
|
59
|
-
append: config.parameters?.append ?? "append"
|
|
60
|
-
},
|
|
61
|
-
countSuffix: config.countSuffix ?? "Count",
|
|
62
|
-
existsSuffix: config.existsSuffix ?? "Exists",
|
|
63
|
-
disableInvalidFilterQueryException: config.disableInvalidFilterQueryException ?? false,
|
|
64
|
-
disableInvalidSortQueryException: config.disableInvalidSortQueryException ?? false,
|
|
65
|
-
disableInvalidIncludesQueryException: config.disableInvalidIncludesQueryException ?? false,
|
|
66
|
-
convertRelationNamesToSnakeCasePlural: config.convertRelationNamesToSnakeCasePlural ?? false,
|
|
67
|
-
convertRelationTableNameStrategy: config.convertRelationTableNameStrategy ?? false,
|
|
68
|
-
convertFieldNamesToSnakeCase: config.convertFieldNamesToSnakeCase ?? false
|
|
69
|
-
};
|
|
70
|
-
});
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
// src/exceptions/allowed_fields_must_be_called_before_allowed_includes.ts
|
|
74
|
-
import { Exception } from "@adonisjs/core/exceptions";
|
|
75
|
-
var AllowedFieldsMustBeCalledBeforeAllowedIncludes = class extends Exception {
|
|
76
|
-
static code;
|
|
77
|
-
static status;
|
|
78
|
-
constructor() {
|
|
79
|
-
super("The QueryBuilder's `allowedFields` method must be called before the `allowedIncludes` method");
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
// src/exceptions/invalid_append_query.ts
|
|
84
|
-
import { ResponseStatus } from "@adonisjs/core/http";
|
|
85
|
-
var InvalidAppendQuery = class _InvalidAppendQuery extends InvalidQuery {
|
|
86
|
-
constructor(appendsNotAllowed, allowedAppends) {
|
|
87
|
-
const notAllowed = appendsNotAllowed.join(", ");
|
|
88
|
-
const allowed = allowedAppends.join(", ");
|
|
89
|
-
const message = `Requested append(s) \`${notAllowed}\` are not allowed. Allowed append(s) are \`${allowed}\``;
|
|
90
|
-
super(message, { status: ResponseStatus.BadRequest });
|
|
91
|
-
}
|
|
92
|
-
static appendsNotAllowed(appendsNotAllowed, allowedAppends) {
|
|
93
|
-
return new _InvalidAppendQuery(appendsNotAllowed, allowedAppends);
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
// src/exceptions/invalid_filter_value.ts
|
|
98
|
-
import { Exception as Exception2 } from "@adonisjs/core/exceptions";
|
|
99
|
-
var InvalidFilterValue = class _InvalidFilterValue extends Exception2 {
|
|
100
|
-
static make(value) {
|
|
101
|
-
return new _InvalidFilterValue(`Filter value \`${value}\` is invalid`);
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
// src/exceptions/unknown_included_fields_query.ts
|
|
106
|
-
import { ResponseStatus as ResponseStatus2 } from "@adonisjs/core/http";
|
|
107
|
-
var UnknownIncludedFieldsQuery = class extends InvalidQuery {
|
|
108
|
-
unknownFields;
|
|
109
|
-
constructor(unknownFields) {
|
|
110
|
-
const notAllowed = unknownFields.join(", ");
|
|
111
|
-
const message = [
|
|
112
|
-
`Requested field(s) \`${notAllowed}\` are not allowed (yet). `,
|
|
113
|
-
"If you want to allow these fields, please make sure to call the QueryBuilder's `allowedFields` method before the `allowedIncludes` method"
|
|
114
|
-
].join("");
|
|
115
|
-
super(message, { status: ResponseStatus2.BadRequest });
|
|
116
|
-
this.unknownFields = unknownFields;
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
// index.ts
|
|
121
|
-
export * from "collect.js";
|
|
122
|
-
export {
|
|
123
|
-
AllowedFieldsMustBeCalledBeforeAllowedIncludes,
|
|
124
|
-
AllowedFilter,
|
|
125
|
-
AllowedInclude,
|
|
126
|
-
AllowedSort,
|
|
127
|
-
ApiQueryBuilderRequest,
|
|
128
|
-
FilterOperator,
|
|
129
|
-
FiltersBeginWithStrict,
|
|
130
|
-
FiltersCallback,
|
|
131
|
-
FiltersEndsWithStrict,
|
|
132
|
-
FiltersExact,
|
|
133
|
-
FiltersOperator,
|
|
134
|
-
FiltersPartial,
|
|
135
|
-
FiltersTrashed,
|
|
136
|
-
IncludedCallback,
|
|
137
|
-
IncludedCount,
|
|
138
|
-
IncludedRelationship,
|
|
139
|
-
InvalidAppendQuery,
|
|
140
|
-
InvalidDirection,
|
|
141
|
-
InvalidFilterQuery,
|
|
142
|
-
InvalidFilterValue,
|
|
143
|
-
InvalidIncludeQuery,
|
|
144
|
-
InvalidQuery,
|
|
145
|
-
InvalidSortQuery,
|
|
146
|
-
SortDirection,
|
|
147
|
-
SortsCallback,
|
|
148
|
-
SortsField,
|
|
149
|
-
UnknownIncludedFieldsQuery,
|
|
150
|
-
configure,
|
|
151
|
-
defineConfig,
|
|
152
|
-
stubsRoot
|
|
153
|
-
};
|
|
154
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
import { stubsRoot } from "./stubs/main.js";
|
|
2
|
+
import { configure } from "./configure.js";
|
|
3
|
+
import { VineNotInstalledException } from "./src/exceptions/vine_not_installed.js";
|
|
4
|
+
import { buildQueryValidator } from "./src/validation/schema_builder.js";
|
|
5
|
+
import { ApiQueryBuilderRequest } from "./src/api_query_builder_request.js";
|
|
6
|
+
import { FiltersExact } from "./src/filters/filters_exact.js";
|
|
7
|
+
import { FiltersPartial } from "./src/filters/filters_partial.js";
|
|
8
|
+
import { FiltersBeginWithStrict } from "./src/filters/filters_begin_with_strict.js";
|
|
9
|
+
import { FiltersCallback } from "./src/filters/filters_callback.js";
|
|
10
|
+
import { FiltersEndsWithStrict } from "./src/filters/filters_ends_with_strict.js";
|
|
11
|
+
import { FilterOperator } from "./src/enums/filter_operator.js";
|
|
12
|
+
import { FiltersOperator } from "./src/filters/filters_operator.js";
|
|
13
|
+
import { FiltersScope } from "./src/filters/filters_scope.js";
|
|
14
|
+
import { FiltersTrashed } from "./src/filters/filters_trashed.js";
|
|
15
|
+
import { AllowedFilter } from "./src/allowed_filter.js";
|
|
16
|
+
import { IncludedCallback } from "./src/includes/included_callback.js";
|
|
17
|
+
import { IncludedCount } from "./src/includes/included_count.js";
|
|
18
|
+
import { IncludedRelationship } from "./src/includes/included_relationship.js";
|
|
19
|
+
import { AllowedInclude } from "./src/allowed_include.js";
|
|
20
|
+
import { SortDirection } from "./src/enums/sort_direction.js";
|
|
21
|
+
import { InvalidDirection } from "./src/exceptions/invalid_direction.js";
|
|
22
|
+
import { SortsCallback } from "./src/sorts/sorts_callback.js";
|
|
23
|
+
import { SortsField } from "./src/sorts/sorts_field.js";
|
|
24
|
+
import { AllowedSort } from "./src/allowed_sort.js";
|
|
25
|
+
import { BaseFilterable } from "./src/base_filterable.js";
|
|
26
|
+
import { Filterable, filterable } from "./src/decorators/filterable.js";
|
|
27
|
+
import { defineConfig } from "./src/define_config.js";
|
|
28
|
+
import { AllowedFieldsMustBeCalledBeforeAllowedIncludes } from "./src/exceptions/allowed_fields_must_be_called_before_allowed_includes.js";
|
|
29
|
+
import { FilterableNotConfigured } from "./src/exceptions/filterable_not_configured.js";
|
|
30
|
+
import { InvalidQuery } from "./src/exceptions/invalid_query.js";
|
|
31
|
+
import { InvalidAppendQuery } from "./src/exceptions/invalid_append_query.js";
|
|
32
|
+
import { InvalidFieldQuery } from "./src/exceptions/invalid_field_query.js";
|
|
33
|
+
import { InvalidFilterQuery } from "./src/exceptions/invalid_filter_query.js";
|
|
34
|
+
import { InvalidFilterValue } from "./src/exceptions/invalid_filter_value.js";
|
|
35
|
+
import { InvalidIncludeQuery } from "./src/exceptions/invalid_include_query.js";
|
|
36
|
+
import { InvalidSortQuery } from "./src/exceptions/invalid_sort_query.js";
|
|
37
|
+
import { UnknownIncludedFieldsQuery } from "./src/exceptions/unknown_included_fields_query.js";
|
|
38
|
+
export { AllowedFieldsMustBeCalledBeforeAllowedIncludes, AllowedFilter, AllowedInclude, AllowedSort, ApiQueryBuilderRequest, BaseFilterable, FilterOperator, Filterable, FilterableNotConfigured, FiltersBeginWithStrict, FiltersCallback, FiltersEndsWithStrict, FiltersExact, FiltersOperator, FiltersPartial, FiltersScope, FiltersTrashed, IncludedCallback, IncludedCount, IncludedRelationship, InvalidAppendQuery, InvalidDirection, InvalidFieldQuery, InvalidFilterQuery, InvalidFilterValue, InvalidIncludeQuery, InvalidQuery, InvalidSortQuery, SortDirection, SortsCallback, SortsField, UnknownIncludedFieldsQuery, VineNotInstalledException, buildQueryValidator, configure, defineConfig, filterable, stubsRoot };
|
|
@@ -1,42 +1,53 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
1
|
+
import { AllowedInclude } from "../src/allowed_include.js";
|
|
2
|
+
import { AllowedSort } from "../src/allowed_sort.js";
|
|
3
|
+
import { ApiQueryBuilderRequest } from "../src/api_query_builder_request.js";
|
|
4
|
+
import { BaseFilterable } from "../src/base_filterable.js";
|
|
5
|
+
import { ExtractKeys, FilterableConstructor, FilterableTarget, HintedString, SortUnionKeyParams } from "../types.js";
|
|
6
|
+
import { AllowedFilter } from "../src/allowed_filter.js";
|
|
7
|
+
import { HttpRequest } from "@adonisjs/core/http";
|
|
8
|
+
import { LucidModel } from "@adonisjs/lucid/types/model";
|
|
9
|
+
import { ExtractModelRelations } from "@adonisjs/lucid/types/relations";
|
|
10
|
+
import { ApplicationService } from "@adonisjs/core/types";
|
|
11
11
|
export default class ApiQueryProvider {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
protected app: ApplicationService;
|
|
13
|
+
constructor(app: ApplicationService);
|
|
14
|
+
boot(): Promise<void>;
|
|
15
15
|
}
|
|
16
16
|
declare module '@adonisjs/lucid/orm' {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
17
|
+
interface ModelQueryBuilder {
|
|
18
|
+
withRequest(request: HttpRequest): this;
|
|
19
|
+
$apiQueryBuilderRequest: ApiQueryBuilderRequest;
|
|
20
|
+
allowedSorts(...sorts: (AllowedSort<LucidModel> | string)[]): this;
|
|
21
|
+
allowedSorts(sorts: (AllowedSort<LucidModel> | string)[]): this;
|
|
22
|
+
defaultSort(...sorts: (AllowedSort<LucidModel> | string)[]): this;
|
|
23
|
+
defaultSort(sorts: (AllowedSort<LucidModel> | string)[]): this;
|
|
24
|
+
allowedFilters(...filters: (AllowedFilter<LucidModel> | string)[]): this;
|
|
25
|
+
allowedFilters(filters: (AllowedFilter<LucidModel> | string)[]): this;
|
|
26
|
+
allowedIncludes(...includes: (AllowedInclude<LucidModel> | AllowedInclude<LucidModel>[] | string)[]): this;
|
|
27
|
+
allowedIncludes(includes: (AllowedInclude<LucidModel> | AllowedInclude<LucidModel>[] | string)[]): this;
|
|
28
|
+
filter(request?: HttpRequest | ApiQueryBuilderRequest): this;
|
|
29
|
+
filter(filterable: FilterableConstructor | BaseFilterable, request?: HttpRequest | ApiQueryBuilderRequest): this;
|
|
30
|
+
validate(): Promise<unknown>;
|
|
31
|
+
}
|
|
29
32
|
}
|
|
30
33
|
declare module '@adonisjs/lucid/types/model' {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
34
|
+
interface LucidModel {
|
|
35
|
+
$filterable?: FilterableTarget;
|
|
36
|
+
$filter<Model extends LucidModel>(this: Model, request?: HttpRequest | ApiQueryBuilderRequest): ModelQueryBuilderContract<Model, InstanceType<Model>>;
|
|
37
|
+
$filter<Model extends LucidModel>(this: Model, filterable: FilterableConstructor<Model> | BaseFilterable<Model>, request?: HttpRequest | ApiQueryBuilderRequest): ModelQueryBuilderContract<Model, InstanceType<Model>>;
|
|
38
|
+
}
|
|
39
|
+
interface ModelQueryBuilderContract<Model extends LucidModel, Result = InstanceType<Model>> {
|
|
40
|
+
withRequest(request: HttpRequest): this;
|
|
41
|
+
allowedSorts(...sorts: (AllowedSort<Model> | HintedString<SortUnionKeyParams<Model>>)[]): this;
|
|
42
|
+
allowedSorts(sorts: (AllowedSort<Model> | HintedString<SortUnionKeyParams<Model>>)[]): this;
|
|
43
|
+
defaultSort(...sorts: (AllowedSort<Model> | HintedString<SortUnionKeyParams<Model>>)[]): this;
|
|
44
|
+
defaultSort(sorts: (AllowedSort<Model> | HintedString<SortUnionKeyParams<Model>>)[]): this;
|
|
45
|
+
allowedFilters(...filters: (AllowedFilter<Model> | HintedString<ExtractKeys<ModelAttributes<InstanceType<Model>>>>)[]): this;
|
|
46
|
+
allowedFilters(filters: (AllowedFilter<Model> | HintedString<ExtractKeys<ModelAttributes<InstanceType<Model>>>>)[]): this;
|
|
47
|
+
allowedIncludes(...includes: (AllowedInclude<Model> | AllowedInclude<Model>[] | HintedString<ExtractModelRelations<InstanceType<Model>>>)[]): this;
|
|
48
|
+
allowedIncludes(includes: (AllowedInclude<Model> | AllowedInclude<Model>[] | HintedString<ExtractModelRelations<InstanceType<Model>>>)[]): this;
|
|
49
|
+
filter(request?: HttpRequest | ApiQueryBuilderRequest): this;
|
|
50
|
+
filter(filterable: FilterableConstructor<Model> | BaseFilterable<Model>, request?: HttpRequest | ApiQueryBuilderRequest): this;
|
|
51
|
+
validate(): Promise<unknown>;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -1,30 +1,29 @@
|
|
|
1
|
-
// providers/api_query_provider.ts
|
|
2
|
-
import { configProvider } from "@adonisjs/core";
|
|
3
1
|
import { RuntimeException } from "@adonisjs/core/exceptions";
|
|
4
|
-
import { ModelQueryBuilder } from "@adonisjs/lucid/orm";
|
|
2
|
+
import { BaseModel, ModelQueryBuilder } from "@adonisjs/lucid/orm";
|
|
3
|
+
import { configProvider } from "@adonisjs/core";
|
|
4
|
+
// providers/api_query_provider.ts
|
|
5
5
|
var ApiQueryProvider = class {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
ApiQueryProvider as default
|
|
6
|
+
app;
|
|
7
|
+
constructor(app) {
|
|
8
|
+
this.app = app;
|
|
9
|
+
}
|
|
10
|
+
async boot() {
|
|
11
|
+
const { extendModelQueryBuilderWithRequest } = await import("../src/bindings/api_query_request.js");
|
|
12
|
+
const { extendModelQueryBuilderWithSortsQuery } = await import("../src/bindings/sorts_query.js");
|
|
13
|
+
const { extendModelQueryBuilderWithFiltersQuery } = await import("../src/bindings/filters_query.js");
|
|
14
|
+
const { extendModelQueryBuilderWithIncludesQuery } = await import("../src/bindings/includes_query.js");
|
|
15
|
+
const { extendLucidWithFilterable } = await import("../src/bindings/filterable_query.js");
|
|
16
|
+
const { extendModelQueryBuilderWithValidation } = await import("../src/bindings/validation_query.js");
|
|
17
|
+
const apiQueryConfigProvider = this.app.config.get("apiquery");
|
|
18
|
+
const config = await configProvider.resolve(this.app, apiQueryConfigProvider);
|
|
19
|
+
if (!config) throw new RuntimeException("Invalid \"config/apiquery.ts\" file. Make sure you are using the \"defineConfig\" method");
|
|
20
|
+
this.app.config.set("apiquery", config);
|
|
21
|
+
extendModelQueryBuilderWithRequest(ModelQueryBuilder);
|
|
22
|
+
extendModelQueryBuilderWithSortsQuery(ModelQueryBuilder, config);
|
|
23
|
+
extendModelQueryBuilderWithFiltersQuery(ModelQueryBuilder, config);
|
|
24
|
+
extendModelQueryBuilderWithIncludesQuery(ModelQueryBuilder, config);
|
|
25
|
+
extendLucidWithFilterable(BaseModel, ModelQueryBuilder);
|
|
26
|
+
extendModelQueryBuilderWithValidation(ModelQueryBuilder);
|
|
27
|
+
}
|
|
29
28
|
};
|
|
30
|
-
|
|
29
|
+
export { ApiQueryProvider as default };
|