@eienjs/adonisjs-api-query 2.0.0 → 3.0.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/README.md +138 -0
- package/build/configure.d.ts +1 -5
- package/build/configure.js +1 -2
- package/build/index.d.ts +12 -6
- package/build/index.js +26 -20
- package/build/providers/api_query_provider.d.ts +19 -12
- package/build/providers/api_query_provider.js +7 -3
- package/build/src/allowed_filter.d.ts +14 -10
- package/build/src/allowed_filter.js +34 -12
- package/build/src/allowed_include.d.ts +6 -11
- package/build/src/allowed_include.js +14 -15
- package/build/src/allowed_sort.d.ts +2 -6
- package/build/src/allowed_sort.js +1 -2
- package/build/src/api_query_builder_request.d.ts +33 -12
- package/build/src/api_query_builder_request.js +119 -41
- 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 +3 -3
- package/build/src/bindings/filterable_query.js +51 -0
- package/build/src/bindings/filters_query.js +21 -23
- package/build/src/bindings/includes_query.js +32 -33
- package/build/src/bindings/sorts_query.js +20 -23
- 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 +1 -5
- package/build/src/define_config.js +3 -3
- package/build/src/enums/filter_operator.d.ts +2 -5
- package/build/src/enums/filter_operator.js +1 -2
- package/build/src/enums/sort_direction.d.ts +2 -5
- package/build/src/enums/sort_direction.js +1 -2
- package/build/src/exceptions/allowed_fields_must_be_called_before_allowed_includes.d.ts +4 -8
- package/build/src/exceptions/allowed_fields_must_be_called_before_allowed_includes.js +3 -4
- 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 +4 -6
- package/build/src/exceptions/invalid_append_query.js +5 -2
- package/build/src/exceptions/invalid_direction.d.ts +2 -6
- package/build/src/exceptions/invalid_direction.js +1 -2
- package/build/src/exceptions/invalid_field_query.d.ts +7 -0
- package/build/src/exceptions/invalid_field_query.js +17 -0
- package/build/src/exceptions/invalid_filter_query.d.ts +2 -6
- package/build/src/exceptions/invalid_filter_query.js +1 -2
- package/build/src/exceptions/invalid_filter_value.d.ts +2 -6
- package/build/src/exceptions/invalid_filter_value.js +1 -2
- package/build/src/exceptions/invalid_include_query.d.ts +2 -6
- package/build/src/exceptions/invalid_include_query.js +1 -2
- package/build/src/exceptions/invalid_query.d.ts +2 -6
- package/build/src/exceptions/invalid_query.js +1 -2
- package/build/src/exceptions/invalid_sort_query.d.ts +2 -6
- package/build/src/exceptions/invalid_sort_query.js +1 -2
- package/build/src/exceptions/unknown_included_fields_query.d.ts +2 -6
- package/build/src/exceptions/unknown_included_fields_query.js +1 -2
- 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 +2 -6
- package/build/src/filters/filters_begin_with_strict.js +2 -3
- package/build/src/filters/filters_callback.d.ts +2 -6
- package/build/src/filters/filters_callback.js +1 -2
- package/build/src/filters/filters_ends_with_strict.d.ts +2 -6
- package/build/src/filters/filters_ends_with_strict.js +2 -3
- package/build/src/filters/filters_exact.d.ts +2 -6
- package/build/src/filters/filters_exact.js +15 -12
- package/build/src/filters/filters_operator.d.ts +3 -7
- package/build/src/filters/filters_operator.js +10 -11
- package/build/src/filters/filters_partial.d.ts +2 -8
- package/build/src/filters/filters_partial.js +7 -9
- 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 +2 -6
- package/build/src/filters/filters_trashed.js +1 -2
- package/build/src/includes/included_callback.d.ts +2 -6
- package/build/src/includes/included_callback.js +1 -2
- package/build/src/includes/included_count.d.ts +2 -6
- package/build/src/includes/included_count.js +2 -2
- package/build/src/includes/included_relationship.d.ts +4 -8
- package/build/src/includes/included_relationship.js +19 -22
- package/build/src/sorts/sorts_callback.d.ts +2 -6
- package/build/src/sorts/sorts_callback.js +1 -2
- package/build/src/sorts/sorts_field.d.ts +2 -6
- package/build/src/sorts/sorts_field.js +1 -2
- package/build/src/utils/helpers.js +2 -14
- 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 -4
- package/build/stubs/main.js +1 -2
- package/build/types.d.ts +44 -19
- package/package.json +31 -24
package/README.md
CHANGED
|
@@ -39,6 +39,144 @@ export default class MyController {
|
|
|
39
39
|
}
|
|
40
40
|
```
|
|
41
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
|
+
|
|
42
180
|
## Documentation
|
|
43
181
|
|
|
44
182
|
The documentation is available on [EienJS](https://eienjs.com/packages/adonisjs-api-query/getting-started/).
|
package/build/configure.d.ts
CHANGED
package/build/configure.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { stubsRoot } from "./stubs/main.js";
|
|
2
|
-
|
|
2
|
+
// configure.ts
|
|
3
3
|
const configure = async (command) => {
|
|
4
4
|
const codemods = await command.createCodemods();
|
|
5
5
|
await codemods.updateRcFile((rcFile) => {
|
|
@@ -7,5 +7,4 @@ const configure = async (command) => {
|
|
|
7
7
|
});
|
|
8
8
|
await codemods.makeUsingStub(stubsRoot, "config.stub", {});
|
|
9
9
|
};
|
|
10
|
-
//#endregion
|
|
11
10
|
export { configure };
|
package/build/index.d.ts
CHANGED
|
@@ -1,32 +1,38 @@
|
|
|
1
1
|
import { configure } from "./configure.js";
|
|
2
|
-
import { FilterOperator } from "./src/enums/filter_operator.js";
|
|
3
2
|
import { AllowedFilter } from "./src/allowed_filter.js";
|
|
4
3
|
import { AllowedInclude } from "./src/allowed_include.js";
|
|
5
4
|
import { AllowedSort } from "./src/allowed_sort.js";
|
|
6
5
|
import { ApiQueryBuilderRequest } from "./src/api_query_builder_request.js";
|
|
6
|
+
import { BaseFilterable } from "./src/base_filterable.js";
|
|
7
|
+
import { Filterable, filterable } from "./src/decorators/filterable.js";
|
|
7
8
|
import { defineConfig } from "./src/define_config.js";
|
|
9
|
+
import { FilterOperator } from "./src/enums/filter_operator.js";
|
|
8
10
|
import { SortDirection } from "./src/enums/sort_direction.js";
|
|
9
11
|
import { AllowedFieldsMustBeCalledBeforeAllowedIncludes } from "./src/exceptions/allowed_fields_must_be_called_before_allowed_includes.js";
|
|
10
|
-
import {
|
|
12
|
+
import { FilterableNotConfigured } from "./src/exceptions/filterable_not_configured.js";
|
|
11
13
|
import { InvalidAppendQuery } from "./src/exceptions/invalid_append_query.js";
|
|
12
14
|
import { InvalidDirection } from "./src/exceptions/invalid_direction.js";
|
|
15
|
+
import { InvalidFieldQuery } from "./src/exceptions/invalid_field_query.js";
|
|
13
16
|
import { InvalidFilterQuery } from "./src/exceptions/invalid_filter_query.js";
|
|
14
17
|
import { InvalidFilterValue } from "./src/exceptions/invalid_filter_value.js";
|
|
15
18
|
import { InvalidIncludeQuery } from "./src/exceptions/invalid_include_query.js";
|
|
19
|
+
import { InvalidQuery } from "./src/exceptions/invalid_query.js";
|
|
16
20
|
import { InvalidSortQuery } from "./src/exceptions/invalid_sort_query.js";
|
|
17
21
|
import { UnknownIncludedFieldsQuery } from "./src/exceptions/unknown_included_fields_query.js";
|
|
18
|
-
import {
|
|
19
|
-
import { FiltersPartial } from "./src/filters/filters_partial.js";
|
|
22
|
+
import { VineNotInstalledException } from "./src/exceptions/vine_not_installed.js";
|
|
20
23
|
import { FiltersBeginWithStrict } from "./src/filters/filters_begin_with_strict.js";
|
|
21
24
|
import { FiltersCallback } from "./src/filters/filters_callback.js";
|
|
22
25
|
import { FiltersEndsWithStrict } from "./src/filters/filters_ends_with_strict.js";
|
|
26
|
+
import { FiltersExact } from "./src/filters/filters_exact.js";
|
|
23
27
|
import { FiltersOperator } from "./src/filters/filters_operator.js";
|
|
28
|
+
import { FiltersPartial } from "./src/filters/filters_partial.js";
|
|
29
|
+
import { FiltersScope } from "./src/filters/filters_scope.js";
|
|
24
30
|
import { FiltersTrashed } from "./src/filters/filters_trashed.js";
|
|
25
31
|
import { IncludedCallback } from "./src/includes/included_callback.js";
|
|
26
32
|
import { IncludedCount } from "./src/includes/included_count.js";
|
|
27
33
|
import { IncludedRelationship } from "./src/includes/included_relationship.js";
|
|
28
34
|
import { SortsCallback } from "./src/sorts/sorts_callback.js";
|
|
29
35
|
import { SortsField } from "./src/sorts/sorts_field.js";
|
|
36
|
+
import { buildQueryValidator } from "./src/validation/schema_builder.js";
|
|
30
37
|
import { stubsRoot } from "./stubs/main.js";
|
|
31
|
-
export
|
|
32
|
-
export { AllowedFieldsMustBeCalledBeforeAllowedIncludes, AllowedFilter, AllowedInclude, AllowedSort, ApiQueryBuilderRequest, FilterOperator, FiltersBeginWithStrict, FiltersCallback, FiltersEndsWithStrict, FiltersExact, FiltersOperator, FiltersPartial, FiltersTrashed, IncludedCallback, IncludedCount, IncludedRelationship, InvalidAppendQuery, InvalidDirection, InvalidFilterQuery, InvalidFilterValue, InvalidIncludeQuery, InvalidQuery, InvalidSortQuery, SortDirection, SortsCallback, SortsField, UnknownIncludedFieldsQuery, configure, defineConfig, stubsRoot };
|
|
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,32 +1,38 @@
|
|
|
1
|
-
import { stubsRoot } from "./stubs/main.js";
|
|
2
1
|
import { configure } from "./configure.js";
|
|
3
|
-
import { ApiQueryBuilderRequest } from "./src/api_query_builder_request.js";
|
|
4
|
-
import { FiltersExact } from "./src/filters/filters_exact.js";
|
|
5
|
-
import { FiltersPartial } from "./src/filters/filters_partial.js";
|
|
6
|
-
import { FiltersBeginWithStrict } from "./src/filters/filters_begin_with_strict.js";
|
|
7
|
-
import { FiltersCallback } from "./src/filters/filters_callback.js";
|
|
8
|
-
import { FiltersEndsWithStrict } from "./src/filters/filters_ends_with_strict.js";
|
|
9
|
-
import { FilterOperator } from "./src/enums/filter_operator.js";
|
|
10
|
-
import { FiltersOperator } from "./src/filters/filters_operator.js";
|
|
11
|
-
import { FiltersTrashed } from "./src/filters/filters_trashed.js";
|
|
12
2
|
import { AllowedFilter } from "./src/allowed_filter.js";
|
|
13
|
-
import { IncludedCallback } from "./src/includes/included_callback.js";
|
|
14
|
-
import { IncludedCount } from "./src/includes/included_count.js";
|
|
15
|
-
import { IncludedRelationship } from "./src/includes/included_relationship.js";
|
|
16
3
|
import { AllowedInclude } from "./src/allowed_include.js";
|
|
17
|
-
import { SortDirection } from "./src/enums/sort_direction.js";
|
|
18
|
-
import { InvalidDirection } from "./src/exceptions/invalid_direction.js";
|
|
19
|
-
import { SortsCallback } from "./src/sorts/sorts_callback.js";
|
|
20
|
-
import { SortsField } from "./src/sorts/sorts_field.js";
|
|
21
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 { Filterable, filterable } from "./src/decorators/filterable.js";
|
|
22
8
|
import { defineConfig } from "./src/define_config.js";
|
|
9
|
+
import { FilterOperator } from "./src/enums/filter_operator.js";
|
|
10
|
+
import { SortDirection } from "./src/enums/sort_direction.js";
|
|
23
11
|
import { AllowedFieldsMustBeCalledBeforeAllowedIncludes } from "./src/exceptions/allowed_fields_must_be_called_before_allowed_includes.js";
|
|
24
|
-
import {
|
|
12
|
+
import { FilterableNotConfigured } from "./src/exceptions/filterable_not_configured.js";
|
|
25
13
|
import { InvalidAppendQuery } from "./src/exceptions/invalid_append_query.js";
|
|
14
|
+
import { InvalidDirection } from "./src/exceptions/invalid_direction.js";
|
|
15
|
+
import { InvalidFieldQuery } from "./src/exceptions/invalid_field_query.js";
|
|
26
16
|
import { InvalidFilterQuery } from "./src/exceptions/invalid_filter_query.js";
|
|
27
17
|
import { InvalidFilterValue } from "./src/exceptions/invalid_filter_value.js";
|
|
28
18
|
import { InvalidIncludeQuery } from "./src/exceptions/invalid_include_query.js";
|
|
19
|
+
import { InvalidQuery } from "./src/exceptions/invalid_query.js";
|
|
29
20
|
import { InvalidSortQuery } from "./src/exceptions/invalid_sort_query.js";
|
|
30
21
|
import { UnknownIncludedFieldsQuery } from "./src/exceptions/unknown_included_fields_query.js";
|
|
31
|
-
|
|
32
|
-
|
|
22
|
+
import { VineNotInstalledException } from "./src/exceptions/vine_not_installed.js";
|
|
23
|
+
import { FiltersBeginWithStrict } from "./src/filters/filters_begin_with_strict.js";
|
|
24
|
+
import { FiltersCallback } from "./src/filters/filters_callback.js";
|
|
25
|
+
import { FiltersEndsWithStrict } from "./src/filters/filters_ends_with_strict.js";
|
|
26
|
+
import { FiltersExact } from "./src/filters/filters_exact.js";
|
|
27
|
+
import { FiltersOperator } from "./src/filters/filters_operator.js";
|
|
28
|
+
import { FiltersPartial } from "./src/filters/filters_partial.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 };
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import { ExtractKeys, HintedString, SortUnionKeyParams } from "../types.js";
|
|
2
1
|
import { AllowedFilter } from "../src/allowed_filter.js";
|
|
3
2
|
import { AllowedInclude } from "../src/allowed_include.js";
|
|
4
3
|
import { AllowedSort } from "../src/allowed_sort.js";
|
|
5
4
|
import { ApiQueryBuilderRequest } from "../src/api_query_builder_request.js";
|
|
6
|
-
import {
|
|
5
|
+
import { BaseFilterable } from "../src/base_filterable.js";
|
|
6
|
+
import { ExtractKeys, FilterableConstructor, FilterableTarget, HintedString, SortUnionKeyParams } from "../types.js";
|
|
7
7
|
import { HttpRequest } from "@adonisjs/core/http";
|
|
8
8
|
import { LucidModel } from "@adonisjs/lucid/types/model";
|
|
9
9
|
import { ExtractModelRelations } from "@adonisjs/lucid/types/relations";
|
|
10
10
|
import { ApplicationService } from "@adonisjs/core/types";
|
|
11
|
-
|
|
12
|
-
//#region providers/api_query_provider.d.ts
|
|
13
|
-
declare class ApiQueryProvider {
|
|
11
|
+
export default class ApiQueryProvider {
|
|
14
12
|
protected app: ApplicationService;
|
|
15
13
|
constructor(app: ApplicationService);
|
|
16
14
|
boot(): Promise<void>;
|
|
@@ -25,11 +23,19 @@ declare module '@adonisjs/lucid/orm' {
|
|
|
25
23
|
defaultSort(sorts: (AllowedSort<LucidModel> | string)[]): this;
|
|
26
24
|
allowedFilters(...filters: (AllowedFilter<LucidModel> | string)[]): this;
|
|
27
25
|
allowedFilters(filters: (AllowedFilter<LucidModel> | string)[]): this;
|
|
28
|
-
allowedIncludes(...includes: (
|
|
29
|
-
allowedIncludes(includes: (
|
|
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>;
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
declare module '@adonisjs/lucid/types/model' {
|
|
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
|
+
}
|
|
33
39
|
interface ModelQueryBuilderContract<Model extends LucidModel, Result = InstanceType<Model>> {
|
|
34
40
|
withRequest(request: HttpRequest): this;
|
|
35
41
|
allowedSorts(...sorts: (AllowedSort<Model> | HintedString<SortUnionKeyParams<Model>>)[]): this;
|
|
@@ -38,9 +44,10 @@ declare module '@adonisjs/lucid/types/model' {
|
|
|
38
44
|
defaultSort(sorts: (AllowedSort<Model> | HintedString<SortUnionKeyParams<Model>>)[]): this;
|
|
39
45
|
allowedFilters(...filters: (AllowedFilter<Model> | HintedString<ExtractKeys<ModelAttributes<InstanceType<Model>>>>)[]): this;
|
|
40
46
|
allowedFilters(filters: (AllowedFilter<Model> | HintedString<ExtractKeys<ModelAttributes<InstanceType<Model>>>>)[]): this;
|
|
41
|
-
allowedIncludes(...includes: (
|
|
42
|
-
allowedIncludes(includes: (
|
|
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>;
|
|
43
52
|
}
|
|
44
|
-
}
|
|
45
|
-
//#endregion
|
|
46
|
-
export { ApiQueryProvider as default };
|
|
53
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { RuntimeException } from "@adonisjs/core/exceptions";
|
|
2
|
+
import { BaseModel, ModelQueryBuilder } from "@adonisjs/lucid/orm";
|
|
2
3
|
import { configProvider } from "@adonisjs/core";
|
|
3
|
-
|
|
4
|
-
//#region providers/api_query_provider.ts
|
|
4
|
+
// providers/api_query_provider.ts
|
|
5
5
|
var ApiQueryProvider = class {
|
|
6
6
|
app;
|
|
7
7
|
constructor(app) {
|
|
@@ -12,14 +12,18 @@ var ApiQueryProvider = class {
|
|
|
12
12
|
const { extendModelQueryBuilderWithSortsQuery } = await import("../src/bindings/sorts_query.js");
|
|
13
13
|
const { extendModelQueryBuilderWithFiltersQuery } = await import("../src/bindings/filters_query.js");
|
|
14
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");
|
|
15
17
|
const apiQueryConfigProvider = this.app.config.get("apiquery");
|
|
16
18
|
const config = await configProvider.resolve(this.app, apiQueryConfigProvider);
|
|
17
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);
|
|
18
21
|
extendModelQueryBuilderWithRequest(ModelQueryBuilder);
|
|
19
22
|
extendModelQueryBuilderWithSortsQuery(ModelQueryBuilder, config);
|
|
20
23
|
extendModelQueryBuilderWithFiltersQuery(ModelQueryBuilder, config);
|
|
21
24
|
extendModelQueryBuilderWithIncludesQuery(ModelQueryBuilder, config);
|
|
25
|
+
extendLucidWithFilterable(BaseModel, ModelQueryBuilder);
|
|
26
|
+
extendModelQueryBuilderWithValidation(ModelQueryBuilder);
|
|
22
27
|
}
|
|
23
28
|
};
|
|
24
|
-
//#endregion
|
|
25
29
|
export { ApiQueryProvider as default };
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { FilterOperator } from "./enums/filter_operator.js";
|
|
2
|
-
import { EnumType, ExtractKeys, Filter } from "../types.js";
|
|
3
|
-
import { Collection } from "collect.js";
|
|
2
|
+
import { EnumType, ExtractKeys, Filter, ScopeUnionKeyParams } from "../types.js";
|
|
4
3
|
import { LucidModel, ModelAttributes, ModelQueryBuilderContract } from "@adonisjs/lucid/types/model";
|
|
5
4
|
import { StrictValuesWithoutRaw } from "@adonisjs/lucid/types/querybuilder";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
declare class AllowedFilter<Model extends LucidModel> {
|
|
5
|
+
import { SchemaTypes } from "@vinejs/vine/types";
|
|
6
|
+
export declare class AllowedFilter<Model extends LucidModel> {
|
|
9
7
|
protected name: string;
|
|
10
8
|
protected filterClass: Filter<Model>;
|
|
11
9
|
protected internalName: string;
|
|
12
|
-
protected ignored:
|
|
10
|
+
protected ignored: unknown[];
|
|
13
11
|
protected default: unknown;
|
|
14
12
|
protected $hasDefault: boolean;
|
|
15
13
|
protected nullable: boolean;
|
|
16
|
-
|
|
14
|
+
protected validationRule?: SchemaTypes;
|
|
15
|
+
constructor(name: string, filterClass: Filter<Model>, internalName?: string);
|
|
16
|
+
rule(rule: SchemaTypes): this;
|
|
17
|
+
getRule(): SchemaTypes | undefined;
|
|
17
18
|
filter(query: ModelQueryBuilderContract<Model>, value: unknown): void;
|
|
18
19
|
getFilterClass(): Filter<Model>;
|
|
19
20
|
getName(): string;
|
|
@@ -28,14 +29,17 @@ declare class AllowedFilter<Model extends LucidModel> {
|
|
|
28
29
|
unsetDefault(): this;
|
|
29
30
|
protected resolveValueForFiltering(value: unknown): StrictValuesWithoutRaw | null;
|
|
30
31
|
static setFilterArrayValueDelimiter(delimiter?: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* Map of filter name to its Vine rule, for every allowed filter that declares one.
|
|
34
|
+
*/
|
|
35
|
+
static extractRules(filters: readonly unknown[]): Record<string, SchemaTypes>;
|
|
31
36
|
static exact<Model extends LucidModel>(name: string, internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>, shouldAddRelationConstraint?: boolean, arrayValueDelimiter?: string): AllowedFilter<Model>;
|
|
32
37
|
static partial<Model extends LucidModel>(name: string, internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>, shouldAddRelationConstraint?: boolean, arrayValueDelimiter?: string): AllowedFilter<Model>;
|
|
33
38
|
static beginsWithStrict<Model extends LucidModel>(name: string, internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>, shouldAddRelationConstraint?: boolean, arrayValueDelimiter?: string): AllowedFilter<Model>;
|
|
34
39
|
static endsWithStrict<Model extends LucidModel>(name: string, internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>, shouldAddRelationConstraint?: boolean, arrayValueDelimiter?: string): AllowedFilter<Model>;
|
|
35
40
|
static callback<Model extends LucidModel>(name: string, callback: (query: ModelQueryBuilderContract<Model>, value: unknown, property: string) => void, internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>, arrayValueDelimiter?: string): AllowedFilter<Model>;
|
|
36
41
|
static trashed<Model extends LucidModel>(name?: string, internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>): AllowedFilter<Model>;
|
|
42
|
+
static scope<Model extends LucidModel = LucidModel>(name: string, internalName?: ScopeUnionKeyParams<Model>, arrayValueDelimiter?: string): AllowedFilter<Model>;
|
|
37
43
|
static custom<Model extends LucidModel>(name: string, filterClass: Filter<Model>, internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>, arrayValueDelimiter?: string): AllowedFilter<Model>;
|
|
38
44
|
static operator<Model extends LucidModel>(name: string, filterOperator: EnumType<typeof FilterOperator>, boolean?: 'and' | 'or', internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>, shouldAddRelationConstraint?: boolean, arrayValueDelimiter?: string): AllowedFilter<Model>;
|
|
39
|
-
}
|
|
40
|
-
//#endregion
|
|
41
|
-
export { AllowedFilter };
|
|
45
|
+
}
|
|
@@ -1,30 +1,37 @@
|
|
|
1
1
|
import { ApiQueryBuilderRequest } from "./api_query_builder_request.js";
|
|
2
|
-
import { FiltersExact } from "./filters/filters_exact.js";
|
|
3
|
-
import { FiltersPartial } from "./filters/filters_partial.js";
|
|
4
2
|
import { FiltersBeginWithStrict } from "./filters/filters_begin_with_strict.js";
|
|
5
3
|
import { FiltersCallback } from "./filters/filters_callback.js";
|
|
6
4
|
import { FiltersEndsWithStrict } from "./filters/filters_ends_with_strict.js";
|
|
5
|
+
import { FiltersExact } from "./filters/filters_exact.js";
|
|
7
6
|
import { FiltersOperator } from "./filters/filters_operator.js";
|
|
7
|
+
import { FiltersPartial } from "./filters/filters_partial.js";
|
|
8
|
+
import { FiltersScope } from "./filters/filters_scope.js";
|
|
8
9
|
import { FiltersTrashed } from "./filters/filters_trashed.js";
|
|
9
|
-
|
|
10
|
-
//#region src/allowed_filter.ts
|
|
10
|
+
// src/allowed_filter.ts
|
|
11
11
|
var AllowedFilter = class AllowedFilter {
|
|
12
12
|
name;
|
|
13
13
|
filterClass;
|
|
14
14
|
internalName;
|
|
15
|
-
ignored;
|
|
15
|
+
ignored = [];
|
|
16
16
|
default;
|
|
17
17
|
$hasDefault = false;
|
|
18
18
|
nullable = false;
|
|
19
|
+
validationRule;
|
|
19
20
|
constructor(name, filterClass, internalName) {
|
|
20
21
|
this.name = name;
|
|
21
22
|
this.filterClass = filterClass;
|
|
22
|
-
this.ignored = new Collection();
|
|
23
23
|
this.internalName = internalName ?? this.name;
|
|
24
24
|
}
|
|
25
|
+
rule(rule) {
|
|
26
|
+
this.validationRule = rule;
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
getRule() {
|
|
30
|
+
return this.validationRule;
|
|
31
|
+
}
|
|
25
32
|
filter(query, value) {
|
|
26
33
|
const valueToFilter = this.resolveValueForFiltering(value);
|
|
27
|
-
if (
|
|
34
|
+
if (valueToFilter === null && !this.nullable) return;
|
|
28
35
|
this.filterClass.handle(query, valueToFilter, this.internalName);
|
|
29
36
|
}
|
|
30
37
|
getFilterClass() {
|
|
@@ -37,11 +44,11 @@ var AllowedFilter = class AllowedFilter {
|
|
|
37
44
|
return this.name === filterName;
|
|
38
45
|
}
|
|
39
46
|
ignore(...values) {
|
|
40
|
-
this.ignored
|
|
47
|
+
this.ignored.push(...values.flat(Infinity));
|
|
41
48
|
return this;
|
|
42
49
|
}
|
|
43
50
|
getIgnored() {
|
|
44
|
-
return this.ignored
|
|
51
|
+
return this.ignored;
|
|
45
52
|
}
|
|
46
53
|
getInternalName() {
|
|
47
54
|
return this.internalName;
|
|
@@ -69,14 +76,26 @@ var AllowedFilter = class AllowedFilter {
|
|
|
69
76
|
}
|
|
70
77
|
resolveValueForFiltering(value) {
|
|
71
78
|
if (Array.isArray(value)) {
|
|
72
|
-
const remainingProperties = value.map((subValue) => this.resolveValueForFiltering(subValue));
|
|
79
|
+
const remainingProperties = value.map((subValue) => this.resolveValueForFiltering(subValue)).filter((subValue) => subValue !== null);
|
|
73
80
|
return remainingProperties.length === 0 ? null : remainingProperties;
|
|
74
81
|
}
|
|
75
|
-
return this.ignored.
|
|
82
|
+
return this.ignored.includes(value) ? null : value;
|
|
76
83
|
}
|
|
77
84
|
static setFilterArrayValueDelimiter(delimiter) {
|
|
78
85
|
if (delimiter) ApiQueryBuilderRequest.setFilterArrayValueDelimiter(delimiter);
|
|
79
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Map of filter name to its Vine rule, for every allowed filter that declares one.
|
|
89
|
+
*/
|
|
90
|
+
static extractRules(filters) {
|
|
91
|
+
const rules = {};
|
|
92
|
+
for (const filter of filters) {
|
|
93
|
+
if (!(filter instanceof this)) continue;
|
|
94
|
+
const rule = filter.getRule();
|
|
95
|
+
if (rule) rules[filter.getName()] = rule;
|
|
96
|
+
}
|
|
97
|
+
return rules;
|
|
98
|
+
}
|
|
80
99
|
static exact(name, internalName, shouldAddRelationConstraint = true, arrayValueDelimiter) {
|
|
81
100
|
this.setFilterArrayValueDelimiter(arrayValueDelimiter);
|
|
82
101
|
return new AllowedFilter(name, new FiltersExact(shouldAddRelationConstraint), internalName);
|
|
@@ -100,6 +119,10 @@ var AllowedFilter = class AllowedFilter {
|
|
|
100
119
|
static trashed(name = "trashed", internalName) {
|
|
101
120
|
return new AllowedFilter(name, new FiltersTrashed(), internalName);
|
|
102
121
|
}
|
|
122
|
+
static scope(name, internalName, arrayValueDelimiter) {
|
|
123
|
+
this.setFilterArrayValueDelimiter(arrayValueDelimiter);
|
|
124
|
+
return new AllowedFilter(name, new FiltersScope(), internalName);
|
|
125
|
+
}
|
|
103
126
|
static custom(name, filterClass, internalName, arrayValueDelimiter) {
|
|
104
127
|
this.setFilterArrayValueDelimiter(arrayValueDelimiter);
|
|
105
128
|
return new AllowedFilter(name, filterClass, internalName);
|
|
@@ -109,5 +132,4 @@ var AllowedFilter = class AllowedFilter {
|
|
|
109
132
|
return new AllowedFilter(name, new FiltersOperator(shouldAddRelationConstraint, filterOperator, boolean), internalName);
|
|
110
133
|
}
|
|
111
134
|
};
|
|
112
|
-
//#endregion
|
|
113
135
|
export { AllowedFilter };
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { Include } from "../types.js";
|
|
2
|
-
import { Collection } from "collect.js";
|
|
3
2
|
import { LucidModel, ModelQueryBuilderContract } from "@adonisjs/lucid/types/model";
|
|
4
3
|
import { ModelRelations } from "@adonisjs/lucid/types/relations";
|
|
5
|
-
|
|
6
|
-
//#region src/allowed_include.d.ts
|
|
7
|
-
declare class AllowedInclude<Model extends LucidModel> {
|
|
4
|
+
export declare class AllowedInclude<Model extends LucidModel> {
|
|
8
5
|
protected internalName: string;
|
|
9
6
|
protected name: string;
|
|
10
7
|
protected includeClass: Include<Model>;
|
|
@@ -12,10 +9,8 @@ declare class AllowedInclude<Model extends LucidModel> {
|
|
|
12
9
|
include(query: ModelQueryBuilderContract<Model>): void;
|
|
13
10
|
getName(): string;
|
|
14
11
|
isForInclude(includeName: string): boolean;
|
|
15
|
-
static relationship<ParentModel extends LucidModel>(name: string, internalName?: string):
|
|
16
|
-
static count<ParentModel extends LucidModel>(name: string, internalName?: string):
|
|
17
|
-
static callback<ParentModel extends LucidModel, RelatedModel extends LucidModel>(name: string, callback: (query: ModelRelations<RelatedModel, ParentModel>['builder'] | ModelRelations<RelatedModel, ParentModel>['subQuery']) => void, internalName?: string):
|
|
18
|
-
static custom<ParentModel extends LucidModel>(name: string, includeClass: Include<ParentModel>, internalName?: string):
|
|
19
|
-
}
|
|
20
|
-
//#endregion
|
|
21
|
-
export { AllowedInclude };
|
|
12
|
+
static relationship<ParentModel extends LucidModel>(name: string, internalName?: string): AllowedInclude<ParentModel>[];
|
|
13
|
+
static count<ParentModel extends LucidModel>(name: string, internalName?: string): AllowedInclude<ParentModel>[];
|
|
14
|
+
static callback<ParentModel extends LucidModel, RelatedModel extends LucidModel>(name: string, callback: (query: ModelRelations<RelatedModel, ParentModel>['builder'] | ModelRelations<RelatedModel, ParentModel>['subQuery']) => void, internalName?: string): AllowedInclude<ParentModel>[];
|
|
15
|
+
static custom<ParentModel extends LucidModel>(name: string, includeClass: Include<ParentModel>, internalName?: string): AllowedInclude<ParentModel>[];
|
|
16
|
+
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { IncludedCallback } from "./includes/included_callback.js";
|
|
2
2
|
import { IncludedCount } from "./includes/included_count.js";
|
|
3
3
|
import { IncludedRelationship } from "./includes/included_relationship.js";
|
|
4
|
-
import { Collection } from "collect.js";
|
|
5
4
|
import app from "@adonisjs/core/services/app";
|
|
6
|
-
|
|
5
|
+
// src/allowed_include.ts
|
|
7
6
|
var AllowedInclude = class AllowedInclude {
|
|
8
7
|
internalName;
|
|
9
8
|
name;
|
|
@@ -24,25 +23,25 @@ var AllowedInclude = class AllowedInclude {
|
|
|
24
23
|
}
|
|
25
24
|
static relationship(name, internalName) {
|
|
26
25
|
internalName ??= name;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
26
|
+
const relationships = IncludedRelationship.getIndividualRelationshipPathsFromInclude(internalName);
|
|
27
|
+
const aliases = IncludedRelationship.getIndividualRelationshipPathsFromInclude(name);
|
|
28
|
+
const countSuffix = app.config.get("apiquery.countSuffix", "Count");
|
|
29
|
+
const includes = [];
|
|
30
|
+
for (const [index, relationship] of relationships.entries()) {
|
|
31
|
+
const alias = aliases[index];
|
|
32
|
+
includes.push(new AllowedInclude(alias, new IncludedRelationship(), relationship));
|
|
33
|
+
if (!relationship.includes(".")) includes.push(...this.count(`${alias}${countSuffix}`, `${relationship}${countSuffix}`));
|
|
34
|
+
}
|
|
35
|
+
return includes;
|
|
36
36
|
}
|
|
37
37
|
static count(name, internalName) {
|
|
38
|
-
return
|
|
38
|
+
return [new AllowedInclude(name, new IncludedCount(), internalName)];
|
|
39
39
|
}
|
|
40
40
|
static callback(name, callback, internalName) {
|
|
41
|
-
return
|
|
41
|
+
return [new AllowedInclude(name, new IncludedCallback(callback), internalName)];
|
|
42
42
|
}
|
|
43
43
|
static custom(name, includeClass, internalName) {
|
|
44
|
-
return
|
|
44
|
+
return [new AllowedInclude(name, includeClass, internalName)];
|
|
45
45
|
}
|
|
46
46
|
};
|
|
47
|
-
//#endregion
|
|
48
47
|
export { AllowedInclude };
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { ExtractKeys, Sort } from "../types.js";
|
|
2
2
|
import { LucidModel, ModelAttributes, ModelQueryBuilderContract } from "@adonisjs/lucid/types/model";
|
|
3
|
-
|
|
4
|
-
//#region src/allowed_sort.d.ts
|
|
5
|
-
declare class AllowedSort<Model extends LucidModel> {
|
|
3
|
+
export declare class AllowedSort<Model extends LucidModel> {
|
|
6
4
|
protected defaultDirection: string;
|
|
7
5
|
protected internalName: string;
|
|
8
6
|
protected name: string;
|
|
@@ -17,6 +15,4 @@ declare class AllowedSort<Model extends LucidModel> {
|
|
|
17
15
|
static field<Model extends LucidModel>(name: string, internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>): AllowedSort<Model>;
|
|
18
16
|
static custom<Model extends LucidModel>(name: string, sortClass: Sort<Model>, internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>): AllowedSort<Model>;
|
|
19
17
|
static callback<Model extends LucidModel>(name: string, callback: (query: ModelQueryBuilderContract<Model>, isDescending: boolean, property: string) => void, internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>): AllowedSort<Model>;
|
|
20
|
-
}
|
|
21
|
-
//#endregion
|
|
22
|
-
export { AllowedSort };
|
|
18
|
+
}
|
|
@@ -2,7 +2,7 @@ import { SortDirection } from "./enums/sort_direction.js";
|
|
|
2
2
|
import { InvalidDirection } from "./exceptions/invalid_direction.js";
|
|
3
3
|
import { SortsCallback } from "./sorts/sorts_callback.js";
|
|
4
4
|
import { SortsField } from "./sorts/sorts_field.js";
|
|
5
|
-
|
|
5
|
+
// src/allowed_sort.ts
|
|
6
6
|
const REMOVE_HYPHEN_STARTING_IN_ANY_POSITION = /^-+/;
|
|
7
7
|
var AllowedSort = class AllowedSort {
|
|
8
8
|
defaultDirection;
|
|
@@ -46,5 +46,4 @@ var AllowedSort = class AllowedSort {
|
|
|
46
46
|
return new AllowedSort(name, new SortsCallback(callback), internalName);
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
|
-
//#endregion
|
|
50
49
|
export { AllowedSort };
|