@eienjs/adonisjs-api-query 0.1.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 +21 -0
- package/README.md +43 -0
- package/build/api_query_request-QXOB4BN6.js +18 -0
- package/build/api_query_request-QXOB4BN6.js.map +1 -0
- package/build/chunk-HQN7LHVO.js +106 -0
- package/build/chunk-HQN7LHVO.js.map +1 -0
- package/build/chunk-MKQ3HMMA.js +198 -0
- package/build/chunk-MKQ3HMMA.js.map +1 -0
- package/build/chunk-OS75QJZN.js +159 -0
- package/build/chunk-OS75QJZN.js.map +1 -0
- package/build/chunk-PBQFWYKU.js +349 -0
- package/build/chunk-PBQFWYKU.js.map +1 -0
- package/build/chunk-XIRHVLVQ.js +10 -0
- package/build/chunk-XIRHVLVQ.js.map +1 -0
- package/build/config.stub +82 -0
- package/build/configure.d.ts +2 -0
- package/build/filters_query-ZXNA4X75.js +55 -0
- package/build/filters_query-ZXNA4X75.js.map +1 -0
- package/build/includes_query-2XNHHWJB.js +70 -0
- package/build/includes_query-2XNHHWJB.js.map +1 -0
- package/build/index.d.ts +19 -0
- package/build/index.js +130 -0
- package/build/index.js.map +1 -0
- package/build/metafile-esm.json +1 -0
- package/build/providers/api_query_provider.d.ts +42 -0
- package/build/providers/api_query_provider.js +30 -0
- package/build/providers/api_query_provider.js.map +1 -0
- package/build/sorts_query-LUETK3FD.js +63 -0
- package/build/sorts_query-LUETK3FD.js.map +1 -0
- package/build/src/allowed_filter.d.ts +37 -0
- package/build/src/allowed_include.d.ts +17 -0
- package/build/src/allowed_sort.d.ts +18 -0
- package/build/src/api_query_builder_request.d.ts +31 -0
- package/build/src/bindings/api_query_request.d.ts +2 -0
- package/build/src/bindings/filters_query.d.ts +3 -0
- package/build/src/bindings/includes_query.d.ts +3 -0
- package/build/src/bindings/sorts_query.d.ts +3 -0
- package/build/src/define_config.d.ts +3 -0
- package/build/src/enums/filter_operator.d.ts +10 -0
- package/build/src/enums/sort_direction.d.ts +5 -0
- package/build/src/exceptions/allowed_fields_must_be_called_before_allowed_includes.d.ts +6 -0
- package/build/src/exceptions/invalid_append_query.d.ts +5 -0
- package/build/src/exceptions/invalid_direction.d.ts +4 -0
- package/build/src/exceptions/invalid_field_query.d.ts +5 -0
- package/build/src/exceptions/invalid_filter_query.d.ts +7 -0
- package/build/src/exceptions/invalid_filter_value.d.ts +4 -0
- package/build/src/exceptions/invalid_include_query.d.ts +7 -0
- package/build/src/exceptions/invalid_query.d.ts +4 -0
- package/build/src/exceptions/invalid_sort_query.d.ts +7 -0
- package/build/src/exceptions/unknown_included_fields_query.d.ts +5 -0
- package/build/src/filters/filters_begin_with_strict.d.ts +8 -0
- package/build/src/filters/filters_callback.d.ts +7 -0
- package/build/src/filters/filters_ends_with_strict.d.ts +8 -0
- package/build/src/filters/filters_exact.d.ts +12 -0
- package/build/src/filters/filters_operator.d.ts +14 -0
- package/build/src/filters/filters_partial.d.ts +12 -0
- package/build/src/filters/filters_trashed.d.ts +6 -0
- package/build/src/includes/included_callback.d.ts +8 -0
- package/build/src/includes/included_count.d.ts +5 -0
- package/build/src/includes/included_relationship.d.ts +9 -0
- package/build/src/sorts/sorts_callback.d.ts +7 -0
- package/build/src/sorts/sorts_field.d.ts +5 -0
- package/build/src/types.d.ts +90 -0
- package/build/src/types.js +1 -0
- package/build/src/types.js.map +1 -0
- package/build/src/utils/helpers.d.ts +3 -0
- package/build/stubs/main.d.ts +1 -0
- package/package.json +143 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ApiQueryBuilderRequest,
|
|
3
|
+
substrReplace
|
|
4
|
+
} from "./chunk-MKQ3HMMA.js";
|
|
5
|
+
import {
|
|
6
|
+
InvalidQuery
|
|
7
|
+
} from "./chunk-XIRHVLVQ.js";
|
|
8
|
+
|
|
9
|
+
// src/enums/filter_operator.ts
|
|
10
|
+
var FilterOperator = {
|
|
11
|
+
Dynamic: "",
|
|
12
|
+
Equal: "=",
|
|
13
|
+
LessThan: "<",
|
|
14
|
+
GreaterThan: ">",
|
|
15
|
+
LessThanOrEqual: "<=",
|
|
16
|
+
GreaterThanOrEqual: ">=",
|
|
17
|
+
NotEqual: "<>"
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// src/allowed_filter.ts
|
|
21
|
+
import { Collection } from "collect.js";
|
|
22
|
+
|
|
23
|
+
// src/filters/filters_exact.ts
|
|
24
|
+
import collect from "collect.js";
|
|
25
|
+
var FiltersExact = class {
|
|
26
|
+
constructor(addRelationConstraint = true) {
|
|
27
|
+
this.addRelationConstraint = addRelationConstraint;
|
|
28
|
+
}
|
|
29
|
+
relationConstraints = [];
|
|
30
|
+
handle(query, value, property) {
|
|
31
|
+
if (this.addRelationConstraint && this.isRelationProperty(query, property)) {
|
|
32
|
+
this.withRelationConstraint(query, value, property);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (Array.isArray(value)) {
|
|
36
|
+
void query.whereIn(this.qualifyColumn(query, property), value);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (value === null) {
|
|
40
|
+
void query.whereNull(this.qualifyColumn(query, property));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
void query.where(this.qualifyColumn(query, property), "=", value);
|
|
44
|
+
}
|
|
45
|
+
qualifyColumn(query, column) {
|
|
46
|
+
if (column.includes(".")) {
|
|
47
|
+
return column;
|
|
48
|
+
}
|
|
49
|
+
return `${query.model.table}.${query.model.$getColumn(column)?.columnName}`;
|
|
50
|
+
}
|
|
51
|
+
isRelationProperty(query, property) {
|
|
52
|
+
if (!property.includes(".")) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
if (this.relationConstraints.includes(property)) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
const firstRelationShip = property.split(".")[0];
|
|
59
|
+
return query.model.$relationsDefinitions.has(firstRelationShip);
|
|
60
|
+
}
|
|
61
|
+
withRelationConstraint(query, value, property) {
|
|
62
|
+
const [relation, relationProperty] = collect(property.split(".")).pipe((parts) => [
|
|
63
|
+
parts.except([parts.last()]).implode("."),
|
|
64
|
+
parts.last()
|
|
65
|
+
]);
|
|
66
|
+
void query.whereHas(relation, (subQuery) => {
|
|
67
|
+
const columnName = this.qualifyColumn(query, relationProperty);
|
|
68
|
+
this.relationConstraints.push(columnName);
|
|
69
|
+
this.handle(subQuery, value, columnName);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// src/filters/filters_partial.ts
|
|
75
|
+
var FiltersPartial = class _FiltersPartial extends FiltersExact {
|
|
76
|
+
handle(query, value, property) {
|
|
77
|
+
if (this.addRelationConstraint && this.isRelationProperty(query, property)) {
|
|
78
|
+
this.withRelationConstraint(query, value, property);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const dialect = this.getDatabaseDialect(query);
|
|
82
|
+
if (Array.isArray(value)) {
|
|
83
|
+
if (value.filter((item) => item.toString().length > 0).length === 0) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
void query.where((subQuery) => {
|
|
87
|
+
for (const partialValue of value.filter((item) => item.toString().length > 0)) {
|
|
88
|
+
const [innerSql, innerBindings] = this.getWhereRawParameters(partialValue, property, dialect);
|
|
89
|
+
void subQuery.orWhereRaw(innerSql, innerBindings);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const [sql, bindings] = this.getWhereRawParameters(value, property, dialect);
|
|
95
|
+
void query.whereRaw(sql, bindings);
|
|
96
|
+
}
|
|
97
|
+
getDatabaseDialect(query) {
|
|
98
|
+
return query.client.dialect.name;
|
|
99
|
+
}
|
|
100
|
+
getWhereRawParameters(value, property, dialect) {
|
|
101
|
+
const resolvedValue = `${value}`.toLowerCase();
|
|
102
|
+
return [
|
|
103
|
+
`LOWER(${property}) LIKE ?${_FiltersPartial.maybeSpecifyEscapeChar(dialect)}`,
|
|
104
|
+
[`%${_FiltersPartial.escapeLike(resolvedValue)}%`]
|
|
105
|
+
];
|
|
106
|
+
}
|
|
107
|
+
static escapeLike(value) {
|
|
108
|
+
return value.replaceAll("\\", "\\\\").replaceAll("_", String.raw`\\_`).replaceAll("%", String.raw`\\%`);
|
|
109
|
+
}
|
|
110
|
+
static maybeSpecifyEscapeChar(dialect) {
|
|
111
|
+
if (["sqlite3", "better-sqlite3", "libsql", "mssql"].includes(dialect)) {
|
|
112
|
+
return "";
|
|
113
|
+
}
|
|
114
|
+
return String.raw`ESCAPE '\'`;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// src/filters/filters_begin_with_strict.ts
|
|
119
|
+
var FiltersBeginWithStrict = class _FiltersBeginWithStrict extends FiltersPartial {
|
|
120
|
+
getWhereRawParameters(value, property, dialect) {
|
|
121
|
+
return [
|
|
122
|
+
`${property} LIKE ?${_FiltersBeginWithStrict.maybeSpecifyEscapeChar(dialect)}`,
|
|
123
|
+
[`${_FiltersBeginWithStrict.escapeLike(value.toString())}%`]
|
|
124
|
+
];
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// src/filters/filters_callback.ts
|
|
129
|
+
var FiltersCallback = class {
|
|
130
|
+
constructor(callback) {
|
|
131
|
+
this.callback = callback;
|
|
132
|
+
}
|
|
133
|
+
handle(query, value, property) {
|
|
134
|
+
this.callback(query, value, property);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// src/filters/filters_ends_with_strict.ts
|
|
139
|
+
var FiltersEndsWithStrict = class _FiltersEndsWithStrict extends FiltersPartial {
|
|
140
|
+
getWhereRawParameters(value, property, dialect) {
|
|
141
|
+
return [
|
|
142
|
+
`${property} LIKE ?${_FiltersEndsWithStrict.maybeSpecifyEscapeChar(dialect)}`,
|
|
143
|
+
[`%${_FiltersEndsWithStrict.escapeLike(value.toString())}`]
|
|
144
|
+
];
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// src/filters/filters_operator.ts
|
|
149
|
+
var FiltersOperator = class extends FiltersExact {
|
|
150
|
+
constructor($addRelationConstraint, $filterOperator, $boolean) {
|
|
151
|
+
super($addRelationConstraint);
|
|
152
|
+
this.$addRelationConstraint = $addRelationConstraint;
|
|
153
|
+
this.$filterOperator = $filterOperator;
|
|
154
|
+
this.$boolean = $boolean;
|
|
155
|
+
}
|
|
156
|
+
handle(query, value, property) {
|
|
157
|
+
let filterOperator = this.$filterOperator;
|
|
158
|
+
if (this.$addRelationConstraint && this.isRelationProperty(query, property)) {
|
|
159
|
+
this.withRelationConstraint(query, value, property);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (Array.isArray(value)) {
|
|
163
|
+
const items = value;
|
|
164
|
+
void query.where((subQuery) => {
|
|
165
|
+
for (const item of items) {
|
|
166
|
+
this.handle(subQuery, item, property);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (filterOperator === FilterOperator.Dynamic) {
|
|
172
|
+
filterOperator = this.getDynamicFilterOperator(value.toString());
|
|
173
|
+
value = this.removeDynamicFilterOperatorFromValue(value.toString(), filterOperator);
|
|
174
|
+
}
|
|
175
|
+
if (this.$boolean === "and") {
|
|
176
|
+
void query.where(this.qualifyColumn(query, property), filterOperator, value);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
void query.orWhere(this.qualifyColumn(query, property), filterOperator, value);
|
|
180
|
+
}
|
|
181
|
+
getDynamicFilterOperator(value) {
|
|
182
|
+
let filterOperator = FilterOperator.Equal;
|
|
183
|
+
for (const filterOperatorCase of Object.values(FilterOperator)) {
|
|
184
|
+
if (value.startsWith(filterOperatorCase) && filterOperatorCase !== FilterOperator.Dynamic) {
|
|
185
|
+
filterOperator = filterOperatorCase;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return filterOperator;
|
|
189
|
+
}
|
|
190
|
+
removeDynamicFilterOperatorFromValue(value, filterOperator) {
|
|
191
|
+
if (value.includes(filterOperator)) {
|
|
192
|
+
value = substrReplace(value, "", 0, filterOperator.length);
|
|
193
|
+
}
|
|
194
|
+
return value;
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
// src/filters/filters_trashed.ts
|
|
199
|
+
var FiltersTrashed = class {
|
|
200
|
+
handle(query, value, _property) {
|
|
201
|
+
if (!("withTrashed" in query && "onlyTrashed" in query)) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const queryWithSoftDeletes = query;
|
|
205
|
+
if (value === "with") {
|
|
206
|
+
void queryWithSoftDeletes.withTrashed();
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (value === "only") {
|
|
210
|
+
void queryWithSoftDeletes.onlyTrashed();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// src/allowed_filter.ts
|
|
216
|
+
var AllowedFilter = class _AllowedFilter {
|
|
217
|
+
static setFilterArrayValueDelimiter(delimiter) {
|
|
218
|
+
if (delimiter) {
|
|
219
|
+
ApiQueryBuilderRequest.setFilterArrayValueDelimiter(delimiter);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
static exact(name, internalName, addRelationConstraint = true, arrayValueDelimiter) {
|
|
223
|
+
this.setFilterArrayValueDelimiter(arrayValueDelimiter);
|
|
224
|
+
return new _AllowedFilter(name, new FiltersExact(addRelationConstraint), internalName);
|
|
225
|
+
}
|
|
226
|
+
static partial(name, internalName, addRelationConstraint = true, arrayValueDelimiter) {
|
|
227
|
+
this.setFilterArrayValueDelimiter(arrayValueDelimiter);
|
|
228
|
+
return new _AllowedFilter(name, new FiltersPartial(addRelationConstraint), internalName);
|
|
229
|
+
}
|
|
230
|
+
static beginsWithStrict(name, internalName, addRelationConstraint = true, arrayValueDelimiter) {
|
|
231
|
+
this.setFilterArrayValueDelimiter(arrayValueDelimiter);
|
|
232
|
+
return new _AllowedFilter(name, new FiltersBeginWithStrict(addRelationConstraint), internalName);
|
|
233
|
+
}
|
|
234
|
+
static endsWithStrict(name, internalName, addRelationConstraint = true, arrayValueDelimiter) {
|
|
235
|
+
this.setFilterArrayValueDelimiter(arrayValueDelimiter);
|
|
236
|
+
return new _AllowedFilter(name, new FiltersEndsWithStrict(addRelationConstraint), internalName);
|
|
237
|
+
}
|
|
238
|
+
static callback(name, callback, internalName, arrayValueDelimiter) {
|
|
239
|
+
this.setFilterArrayValueDelimiter(arrayValueDelimiter);
|
|
240
|
+
return new _AllowedFilter(name, new FiltersCallback(callback), internalName);
|
|
241
|
+
}
|
|
242
|
+
static trashed(name = "trashed", internalName) {
|
|
243
|
+
return new _AllowedFilter(name, new FiltersTrashed(), internalName);
|
|
244
|
+
}
|
|
245
|
+
static custom(name, filterClass, internalName, arrayValueDelimiter) {
|
|
246
|
+
this.setFilterArrayValueDelimiter(arrayValueDelimiter);
|
|
247
|
+
return new _AllowedFilter(name, filterClass, internalName);
|
|
248
|
+
}
|
|
249
|
+
static operator(name, filterOperator, boolean = "and", internalName, addRelationConstraint = true, arrayValueDelimiter) {
|
|
250
|
+
this.setFilterArrayValueDelimiter(arrayValueDelimiter);
|
|
251
|
+
return new _AllowedFilter(
|
|
252
|
+
name,
|
|
253
|
+
new FiltersOperator(addRelationConstraint, filterOperator, boolean),
|
|
254
|
+
internalName
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
name;
|
|
258
|
+
filterClass;
|
|
259
|
+
internalName;
|
|
260
|
+
ignored;
|
|
261
|
+
default;
|
|
262
|
+
$hasDefault = false;
|
|
263
|
+
nullable = false;
|
|
264
|
+
constructor(name, filterClass, internalName) {
|
|
265
|
+
this.name = name;
|
|
266
|
+
this.filterClass = filterClass;
|
|
267
|
+
this.ignored = new Collection();
|
|
268
|
+
this.internalName = internalName ?? this.name;
|
|
269
|
+
}
|
|
270
|
+
filter(query, value) {
|
|
271
|
+
const valueToFilter = this.resolveValueForFiltering(value);
|
|
272
|
+
if (!this.nullable && valueToFilter === null) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
this.filterClass.handle(query, valueToFilter, this.internalName);
|
|
276
|
+
}
|
|
277
|
+
getFilterClass() {
|
|
278
|
+
return this.filterClass;
|
|
279
|
+
}
|
|
280
|
+
getName() {
|
|
281
|
+
return this.name;
|
|
282
|
+
}
|
|
283
|
+
isForFilter(filterName) {
|
|
284
|
+
return this.name === filterName;
|
|
285
|
+
}
|
|
286
|
+
ignore(...values) {
|
|
287
|
+
this.ignored = this.ignored.merge(values).flatten();
|
|
288
|
+
return this;
|
|
289
|
+
}
|
|
290
|
+
getIgnored() {
|
|
291
|
+
return this.ignored.toArray();
|
|
292
|
+
}
|
|
293
|
+
getInternalName() {
|
|
294
|
+
return this.internalName;
|
|
295
|
+
}
|
|
296
|
+
setDefault(defaultValue) {
|
|
297
|
+
this.default = defaultValue;
|
|
298
|
+
this.$hasDefault = true;
|
|
299
|
+
if (defaultValue === null) {
|
|
300
|
+
this.setNullable(true);
|
|
301
|
+
}
|
|
302
|
+
return this;
|
|
303
|
+
}
|
|
304
|
+
getDefault() {
|
|
305
|
+
return this.default;
|
|
306
|
+
}
|
|
307
|
+
hasDefault() {
|
|
308
|
+
return this.$hasDefault;
|
|
309
|
+
}
|
|
310
|
+
setNullable(nullable = true) {
|
|
311
|
+
this.nullable = nullable;
|
|
312
|
+
return this;
|
|
313
|
+
}
|
|
314
|
+
unsetDefault() {
|
|
315
|
+
this.$hasDefault = false;
|
|
316
|
+
this.default = void 0;
|
|
317
|
+
return this;
|
|
318
|
+
}
|
|
319
|
+
resolveValueForFiltering(value) {
|
|
320
|
+
if (Array.isArray(value)) {
|
|
321
|
+
const remainingProperties = value.map((subValue) => this.resolveValueForFiltering(subValue));
|
|
322
|
+
return remainingProperties.length === 0 ? null : remainingProperties;
|
|
323
|
+
}
|
|
324
|
+
return this.ignored.contains(value) ? null : value;
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
// src/exceptions/invalid_filter_query.ts
|
|
329
|
+
import { ResponseStatus } from "@adonisjs/core/http";
|
|
330
|
+
var InvalidFilterQuery = class _InvalidFilterQuery extends InvalidQuery {
|
|
331
|
+
constructor(unknownFilters, allowedFilters) {
|
|
332
|
+
const notAllowed = unknownFilters.join(", ");
|
|
333
|
+
const allowed = allowedFilters.join(", ");
|
|
334
|
+
const message = `Requested filter(s) \`${notAllowed}\` are not allowed. Allowed filter(s) are \`${allowed}\``;
|
|
335
|
+
super(message, { status: ResponseStatus.BadRequest });
|
|
336
|
+
this.unknownFilters = unknownFilters;
|
|
337
|
+
this.allowedFilters = allowedFilters;
|
|
338
|
+
}
|
|
339
|
+
static filtersNotAllowed(unknownFilters, allowedFilters) {
|
|
340
|
+
return new _InvalidFilterQuery(unknownFilters, allowedFilters);
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
export {
|
|
345
|
+
FilterOperator,
|
|
346
|
+
AllowedFilter,
|
|
347
|
+
InvalidFilterQuery
|
|
348
|
+
};
|
|
349
|
+
//# sourceMappingURL=chunk-PBQFWYKU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/enums/filter_operator.ts","../src/allowed_filter.ts","../src/filters/filters_exact.ts","../src/filters/filters_partial.ts","../src/filters/filters_begin_with_strict.ts","../src/filters/filters_callback.ts","../src/filters/filters_ends_with_strict.ts","../src/filters/filters_operator.ts","../src/filters/filters_trashed.ts","../src/exceptions/invalid_filter_query.ts"],"sourcesContent":["export const FilterOperator = {\n Dynamic: '',\n Equal: '=',\n LessThan: '<',\n GreaterThan: '>',\n LessThanOrEqual: '<=',\n GreaterThanOrEqual: '>=',\n NotEqual: '<>',\n} as const;\n\nexport type FilterOperator = (typeof FilterOperator)[keyof typeof FilterOperator];\n","import { type LucidModel, type ModelAttributes, type ModelQueryBuilderContract } from '@adonisjs/lucid/types/model';\nimport { type StrictValuesWithoutRaw } from '@adonisjs/lucid/types/querybuilder';\nimport { Collection } from 'collect.js';\nimport { ApiQueryBuilderRequest } from './api_query_builder_request.js';\nimport { type FilterOperator } from './enums/filter_operator.js';\nimport { FiltersBeginWithStrict } from './filters/filters_begin_with_strict.js';\nimport { FiltersCallback } from './filters/filters_callback.js';\nimport { FiltersEndsWithStrict } from './filters/filters_ends_with_strict.js';\nimport { FiltersExact } from './filters/filters_exact.js';\nimport { FiltersOperator } from './filters/filters_operator.js';\nimport { FiltersPartial } from './filters/filters_partial.js';\nimport { FiltersTrashed } from './filters/filters_trashed.js';\nimport { type ExtractKeys, type Filter } from './types.js';\n\nexport class AllowedFilter<Model extends LucidModel> {\n public static setFilterArrayValueDelimiter(delimiter?: string): void {\n if (delimiter) {\n ApiQueryBuilderRequest.setFilterArrayValueDelimiter(delimiter);\n }\n }\n\n public static exact<Model extends LucidModel>(\n name: string,\n internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>,\n addRelationConstraint = true,\n arrayValueDelimiter?: string,\n ): AllowedFilter<Model> {\n this.setFilterArrayValueDelimiter(arrayValueDelimiter);\n\n return new AllowedFilter<Model>(name, new FiltersExact<Model>(addRelationConstraint), internalName);\n }\n\n public static partial<Model extends LucidModel>(\n name: string,\n internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>,\n addRelationConstraint = true,\n arrayValueDelimiter?: string,\n ): AllowedFilter<Model> {\n this.setFilterArrayValueDelimiter(arrayValueDelimiter);\n\n return new AllowedFilter<Model>(name, new FiltersPartial<Model>(addRelationConstraint), internalName);\n }\n\n public static beginsWithStrict<Model extends LucidModel>(\n name: string,\n internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>,\n addRelationConstraint = true,\n arrayValueDelimiter?: string,\n ): AllowedFilter<Model> {\n this.setFilterArrayValueDelimiter(arrayValueDelimiter);\n\n return new AllowedFilter<Model>(name, new FiltersBeginWithStrict<Model>(addRelationConstraint), internalName);\n }\n\n public static endsWithStrict<Model extends LucidModel>(\n name: string,\n internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>,\n addRelationConstraint = true,\n arrayValueDelimiter?: string,\n ): AllowedFilter<Model> {\n this.setFilterArrayValueDelimiter(arrayValueDelimiter);\n\n return new AllowedFilter<Model>(name, new FiltersEndsWithStrict<Model>(addRelationConstraint), internalName);\n }\n\n public static callback<Model extends LucidModel>(\n name: string,\n callback: (query: ModelQueryBuilderContract<Model>, value: unknown, property: string) => void,\n internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>,\n arrayValueDelimiter?: string,\n ): AllowedFilter<Model> {\n this.setFilterArrayValueDelimiter(arrayValueDelimiter);\n\n return new AllowedFilter<Model>(name, new FiltersCallback<Model>(callback), internalName);\n }\n\n public static trashed<Model extends LucidModel>(\n name = 'trashed',\n internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>,\n ): AllowedFilter<Model> {\n return new AllowedFilter<Model>(name, new FiltersTrashed<Model>(), internalName);\n }\n\n public static custom<Model extends LucidModel>(\n name: string,\n filterClass: Filter<Model>,\n internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>,\n arrayValueDelimiter?: string,\n ): AllowedFilter<Model> {\n this.setFilterArrayValueDelimiter(arrayValueDelimiter);\n\n return new AllowedFilter<Model>(name, filterClass, internalName);\n }\n\n public static operator<Model extends LucidModel>(\n name: string,\n filterOperator: FilterOperator,\n boolean: 'and' | 'or' = 'and',\n internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>,\n addRelationConstraint = true,\n arrayValueDelimiter?: string,\n ): AllowedFilter<Model> {\n this.setFilterArrayValueDelimiter(arrayValueDelimiter);\n\n return new AllowedFilter<Model>(\n name,\n new FiltersOperator<Model>(addRelationConstraint, filterOperator, boolean),\n internalName,\n );\n }\n\n protected name: string;\n\n protected filterClass: Filter<Model>;\n\n protected internalName: string;\n\n protected ignored: Collection<unknown>;\n\n protected default: unknown;\n\n protected $hasDefault = false;\n\n protected nullable = false;\n\n public constructor(\n name: string,\n filterClass: Filter<Model>,\n internalName?: ExtractKeys<ModelAttributes<InstanceType<Model>>>,\n ) {\n this.name = name;\n this.filterClass = filterClass;\n this.ignored = new Collection();\n this.internalName = internalName ?? this.name;\n }\n\n public filter(query: ModelQueryBuilderContract<Model>, value: unknown): void {\n const valueToFilter = this.resolveValueForFiltering(value);\n if (!this.nullable && valueToFilter === null) {\n return;\n }\n\n this.filterClass.handle(query, valueToFilter, this.internalName);\n }\n\n public getFilterClass(): Filter<Model> {\n return this.filterClass;\n }\n\n public getName(): string {\n return this.name;\n }\n\n public isForFilter(filterName: string): boolean {\n return this.name === filterName;\n }\n\n public ignore(...values: unknown[]): this {\n this.ignored = this.ignored.merge(values).flatten();\n\n return this;\n }\n\n public getIgnored(): unknown[] {\n return this.ignored.toArray();\n }\n\n public getInternalName(): string {\n return this.internalName;\n }\n\n public setDefault(defaultValue: unknown): this {\n this.default = defaultValue;\n this.$hasDefault = true;\n\n if (defaultValue === null) {\n this.setNullable(true);\n }\n\n return this;\n }\n\n public getDefault(): unknown {\n return this.default;\n }\n\n public hasDefault(): boolean {\n return this.$hasDefault;\n }\n\n public setNullable(nullable = true): this {\n this.nullable = nullable;\n\n return this;\n }\n\n public unsetDefault(): this {\n this.$hasDefault = false;\n this.default = undefined;\n\n return this;\n }\n\n protected resolveValueForFiltering(value: unknown): StrictValuesWithoutRaw | null {\n if (Array.isArray(value)) {\n const remainingProperties = value.map((subValue) => this.resolveValueForFiltering(subValue));\n\n return remainingProperties.length === 0 ? null : (remainingProperties as StrictValuesWithoutRaw);\n }\n\n return this.ignored.contains(value) ? null : (value as StrictValuesWithoutRaw);\n }\n}\n","import { type LucidModel, type ModelQueryBuilderContract } from '@adonisjs/lucid/types/model';\nimport { type StrictValuesWithoutRaw } from '@adonisjs/lucid/types/querybuilder';\nimport { type ExtractModelRelations } from '@adonisjs/lucid/types/relations';\nimport collect, { type Collection } from 'collect.js';\nimport { type Filter } from '../types.js';\n\nexport class FiltersExact<Model extends LucidModel> implements Filter<Model> {\n protected relationConstraints: string[] = [];\n\n public constructor(protected addRelationConstraint = true) {}\n\n public handle(\n query: ModelQueryBuilderContract<Model, InstanceType<Model>>,\n value: StrictValuesWithoutRaw | null,\n property: string,\n ): void {\n if (this.addRelationConstraint && this.isRelationProperty(query, property)) {\n this.withRelationConstraint(query, value, property);\n\n return;\n }\n\n if (Array.isArray(value)) {\n void query.whereIn(this.qualifyColumn(query, property), value);\n\n return;\n }\n\n if (value === null) {\n void query.whereNull(this.qualifyColumn(query, property));\n\n return;\n }\n\n void query.where(this.qualifyColumn(query, property), '=', value);\n }\n\n protected qualifyColumn(query: ModelQueryBuilderContract<Model, InstanceType<Model>>, column: string): string {\n if (column.includes('.')) {\n return column;\n }\n\n return `${query.model.table}.${query.model.$getColumn(column)?.columnName}`;\n }\n\n protected isRelationProperty(\n query: ModelQueryBuilderContract<Model, InstanceType<Model>>,\n property: string,\n ): boolean {\n if (!property.includes('.')) {\n return false;\n }\n\n if (this.relationConstraints.includes(property)) {\n return false;\n }\n\n const firstRelationShip = property.split('.')[0];\n\n return query.model.$relationsDefinitions.has(firstRelationShip);\n }\n\n protected withRelationConstraint(\n query: ModelQueryBuilderContract<Model, InstanceType<Model>>,\n value: StrictValuesWithoutRaw | null,\n property: string,\n ): void {\n const [relation, relationProperty] = collect(property.split('.')).pipe((parts: Collection<string>) => [\n parts.except([parts.last()]).implode('.') as ExtractModelRelations<InstanceType<Model>>,\n parts.last(),\n ]);\n\n void query.whereHas(relation, (subQuery: ModelQueryBuilderContract<Model>) => {\n const columnName = this.qualifyColumn(query, relationProperty);\n this.relationConstraints.push(columnName);\n\n this.handle(subQuery, value, columnName);\n });\n }\n}\n","import { type DialectContract } from '@adonisjs/lucid/types/database';\nimport { type LucidModel, type ModelQueryBuilderContract } from '@adonisjs/lucid/types/model';\nimport { type StrictValuesWithoutRaw } from '@adonisjs/lucid/types/querybuilder';\nimport { type Filter } from '../types.js';\nimport { FiltersExact } from './filters_exact.js';\n\nexport class FiltersPartial<Model extends LucidModel> extends FiltersExact<Model> implements Filter<Model> {\n public handle(\n query: ModelQueryBuilderContract<Model, InstanceType<Model>>,\n value: StrictValuesWithoutRaw | null,\n property: string,\n ): void {\n if (this.addRelationConstraint && this.isRelationProperty(query, property)) {\n this.withRelationConstraint(query, value, property);\n\n return;\n }\n\n const dialect = this.getDatabaseDialect(query);\n if (Array.isArray(value)) {\n if (value.filter((item) => item.toString().length > 0).length === 0) {\n return;\n }\n\n void query.where((subQuery) => {\n for (const partialValue of value.filter((item) => item.toString().length > 0)) {\n const [innerSql, innerBindings] = this.getWhereRawParameters(partialValue, property, dialect);\n void subQuery.orWhereRaw(innerSql, innerBindings);\n }\n });\n\n return;\n }\n\n const [sql, bindings] = this.getWhereRawParameters(value, property, dialect);\n void query.whereRaw(sql, bindings);\n }\n\n protected getDatabaseDialect(query: ModelQueryBuilderContract<Model, InstanceType<Model>>): DialectContract['name'] {\n return query.client.dialect.name;\n }\n\n protected getWhereRawParameters(\n value: StrictValuesWithoutRaw | null,\n property: string,\n dialect: DialectContract['name'],\n ): [string, string[]] {\n const resolvedValue = `${value}`.toLowerCase();\n\n return [\n `LOWER(${property}) LIKE ?${FiltersPartial.maybeSpecifyEscapeChar(dialect)}`,\n [`%${FiltersPartial.escapeLike(resolvedValue)}%`],\n ];\n }\n\n protected static escapeLike(value: string): string {\n return value\n .replaceAll('\\\\', '\\\\\\\\')\n .replaceAll('_', String.raw`\\\\_`)\n .replaceAll('%', String.raw`\\\\%`);\n }\n\n protected static maybeSpecifyEscapeChar(dialect: DialectContract['name']): string {\n if (['sqlite3', 'better-sqlite3', 'libsql', 'mssql'].includes(dialect)) {\n return '';\n }\n\n return String.raw`ESCAPE '\\'`;\n }\n}\n","import { type DialectContract } from '@adonisjs/lucid/types/database';\nimport { type LucidModel } from '@adonisjs/lucid/types/model';\nimport { type StrictValuesWithoutRaw } from '@adonisjs/lucid/types/querybuilder';\nimport { type Filter } from '../types.js';\nimport { FiltersPartial } from './filters_partial.js';\n\nexport class FiltersBeginWithStrict<Model extends LucidModel> extends FiltersPartial<Model> implements Filter<Model> {\n protected getWhereRawParameters(\n value: StrictValuesWithoutRaw,\n property: string,\n dialect: DialectContract['name'],\n ): [string, string[]] {\n return [\n `${property} LIKE ?${FiltersBeginWithStrict.maybeSpecifyEscapeChar(dialect)}`,\n [`${FiltersBeginWithStrict.escapeLike(value.toString())}%`],\n ];\n }\n}\n","import { type LucidModel, type ModelQueryBuilderContract } from '@adonisjs/lucid/types/model';\nimport { type Filter } from '../types.js';\n\nexport class FiltersCallback<Model extends LucidModel> implements Filter<Model> {\n public constructor(\n private callback: (query: ModelQueryBuilderContract<Model>, value: unknown, property: string) => void,\n ) {}\n\n public handle(query: ModelQueryBuilderContract<Model, InstanceType<Model>>, value: unknown, property: string): void {\n this.callback(query, value, property);\n }\n}\n","import { type DialectContract } from '@adonisjs/lucid/types/database';\nimport { type LucidModel } from '@adonisjs/lucid/types/model';\nimport { type StrictValuesWithoutRaw } from '@adonisjs/lucid/types/querybuilder';\nimport { type Filter } from '../types.js';\nimport { FiltersPartial } from './filters_partial.js';\n\nexport class FiltersEndsWithStrict<Model extends LucidModel> extends FiltersPartial<Model> implements Filter<Model> {\n protected getWhereRawParameters(\n value: StrictValuesWithoutRaw,\n property: string,\n dialect: DialectContract['name'],\n ): [string, string[]] {\n return [\n `${property} LIKE ?${FiltersEndsWithStrict.maybeSpecifyEscapeChar(dialect)}`,\n [`%${FiltersEndsWithStrict.escapeLike(value.toString())}`],\n ];\n }\n}\n","import { type LucidModel, type ModelQueryBuilderContract } from '@adonisjs/lucid/types/model';\nimport { type StrictValuesWithoutRaw } from '@adonisjs/lucid/types/querybuilder';\nimport { FilterOperator } from '../enums/filter_operator.js';\nimport { type Filter } from '../types.js';\nimport { substrReplace } from '../utils/helpers.js';\nimport { FiltersExact } from './filters_exact.js';\n\nexport class FiltersOperator<Model extends LucidModel> extends FiltersExact<Model> implements Filter<Model> {\n public constructor(\n protected $addRelationConstraint: boolean,\n protected $filterOperator: FilterOperator,\n protected $boolean: 'and' | 'or',\n ) {\n super($addRelationConstraint);\n }\n\n public handle(\n query: ModelQueryBuilderContract<Model, InstanceType<Model>>,\n value: StrictValuesWithoutRaw,\n property: string,\n ): void {\n let filterOperator = this.$filterOperator;\n\n if (this.$addRelationConstraint && this.isRelationProperty(query, property)) {\n this.withRelationConstraint(query, value, property);\n\n return;\n }\n\n if (Array.isArray(value)) {\n const items = value;\n\n void query.where((subQuery) => {\n for (const item of items) {\n this.handle(subQuery, item, property);\n }\n });\n\n return;\n }\n\n if (filterOperator === FilterOperator.Dynamic) {\n filterOperator = this.getDynamicFilterOperator(value.toString());\n value = this.removeDynamicFilterOperatorFromValue(value.toString(), filterOperator);\n }\n\n if (this.$boolean === 'and') {\n void query.where(this.qualifyColumn(query, property), filterOperator, value);\n\n return;\n }\n\n void query.orWhere(this.qualifyColumn(query, property), filterOperator, value);\n }\n\n protected getDynamicFilterOperator(value: string): FilterOperator {\n let filterOperator: FilterOperator = FilterOperator.Equal;\n\n for (const filterOperatorCase of Object.values(FilterOperator)) {\n if (value.startsWith(filterOperatorCase) && filterOperatorCase !== FilterOperator.Dynamic) {\n filterOperator = filterOperatorCase;\n }\n }\n\n return filterOperator;\n }\n\n protected removeDynamicFilterOperatorFromValue(value: string, filterOperator: FilterOperator): string {\n if (value.includes(filterOperator)) {\n value = substrReplace(value, '', 0, filterOperator.length);\n }\n\n return value;\n }\n}\n","import { type LucidModel, type ModelQueryBuilderContract } from '@adonisjs/lucid/types/model';\nimport { type StrictValuesWithoutRaw } from '@adonisjs/lucid/types/querybuilder';\nimport { type Filter } from '../types.js';\n\nexport class FiltersTrashed<Model extends LucidModel> implements Filter<Model> {\n public handle(\n query: ModelQueryBuilderContract<Model, InstanceType<Model>>,\n value: StrictValuesWithoutRaw,\n _property: string,\n ): void {\n if (!('withTrashed' in query && 'onlyTrashed' in query)) {\n return;\n }\n\n const queryWithSoftDeletes = query as {\n withTrashed(): ModelQueryBuilderContract<Model>;\n onlyTrashed(): ModelQueryBuilderContract<Model>;\n };\n\n if (value === 'with') {\n void queryWithSoftDeletes.withTrashed();\n\n return;\n }\n\n if (value === 'only') {\n void queryWithSoftDeletes.onlyTrashed();\n }\n }\n}\n","import { ResponseStatus } from '@adonisjs/core/http';\nimport { InvalidQuery } from './invalid_query.js';\n\nexport class InvalidFilterQuery extends InvalidQuery {\n public constructor(\n public readonly unknownFilters: string[],\n public readonly allowedFilters: string[],\n ) {\n const notAllowed = unknownFilters.join(', ');\n const allowed = allowedFilters.join(', ');\n const message = `Requested filter(s) \\`${notAllowed}\\` are not allowed. Allowed filter(s) are \\`${allowed}\\``;\n\n super(message, { status: ResponseStatus.BadRequest });\n }\n\n public static filtersNotAllowed(unknownFilters: string[], allowedFilters: string[]): InvalidFilterQuery {\n return new InvalidFilterQuery(unknownFilters, allowedFilters);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// src/exceptions/invalid_query.ts
|
|
2
|
+
import { Exception } from "@adonisjs/core/exceptions";
|
|
3
|
+
var InvalidQuery = class extends Exception {
|
|
4
|
+
static code = "E_INVALID_QUERY_EXCEPTION";
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
InvalidQuery
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=chunk-XIRHVLVQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/exceptions/invalid_query.ts"],"sourcesContent":["import { Exception } from '@adonisjs/core/exceptions';\n\nexport abstract class InvalidQuery extends Exception {\n public static readonly code = 'E_INVALID_QUERY_EXCEPTION';\n}\n"],"mappings":";AAAA,SAAS,iBAAiB;AAEnB,IAAe,eAAf,cAAoC,UAAU;AAAA,EACnD,OAAuB,OAAO;AAChC;","names":[]}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{{{
|
|
2
|
+
exports({ to: app.configPath('apiquery.ts') })
|
|
3
|
+
}}}
|
|
4
|
+
import { defineConfig } from '@eienjs/adonisjs-api-query'
|
|
5
|
+
|
|
6
|
+
const apiQueryConfig = defineConfig({
|
|
7
|
+
/**
|
|
8
|
+
* By default the package will use the `include`, `filter`, `sort`
|
|
9
|
+
* and `fields` query parameters as described in the readme.
|
|
10
|
+
*
|
|
11
|
+
* You can customize these query string parameters here.
|
|
12
|
+
*/
|
|
13
|
+
parameters: {
|
|
14
|
+
include: 'include',
|
|
15
|
+
filter: 'filter',
|
|
16
|
+
sort: 'sort',
|
|
17
|
+
fields: 'fields',
|
|
18
|
+
append: 'append',
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Related model counts are included using the relationship name suffixed with this string.
|
|
23
|
+
* For example: GET /users?include=postsCount
|
|
24
|
+
*/
|
|
25
|
+
countSuffix: 'Count',
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Related model exists are included using the relationship name suffixed with this string.
|
|
29
|
+
* For example: GET /users?include=postsExists
|
|
30
|
+
*/
|
|
31
|
+
existsSuffix: 'Exists',
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* By default the package will throw an `InvalidFilterQuery` exception when a filter in the
|
|
35
|
+
* URL is not allowed in the `allowedFilters()` method.
|
|
36
|
+
*/
|
|
37
|
+
disableInvalidFilterQueryException: false,
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* By default the package will throw an `InvalidSortQuery` exception when a sort in the
|
|
41
|
+
* URL is not allowed in the `allowedSorts()` method.
|
|
42
|
+
*/
|
|
43
|
+
disableInvalidSortQueryException: false,
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* By default the package will throw an `InvalidIncludeQuery` exception when an include in the
|
|
47
|
+
* URL is not allowed in the `allowedIncludes()` method.
|
|
48
|
+
*/
|
|
49
|
+
disableInvalidIncludesQueryException: false,
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* By default, the package expects relationship names to be camel case plural when using fields[relationship].
|
|
53
|
+
* For example, fetching the id and name for a userOwner relation would look like this:
|
|
54
|
+
* GET /users?fields[userOwner]=id,name
|
|
55
|
+
*
|
|
56
|
+
* Set this to `true` if you don't want that and keep the requested relationship names as-is and allows you to
|
|
57
|
+
* request the fields using a snake case relationship name:
|
|
58
|
+
* GET /users?fields[user_owner]=id,name
|
|
59
|
+
*/
|
|
60
|
+
convertRelationNamesToSnakeCasePlural: false,
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* By default, the package expects relationship names to be camel case plural when using fields[relationship].
|
|
64
|
+
* For example, fetching the id and name for a userOwner relation would look like this:
|
|
65
|
+
* GET /users?fields[userOwner]=id,name
|
|
66
|
+
*
|
|
67
|
+
* Set this to one of `snake_case`, `camelCase` or `none` if you want to enable table name resolution in addition to the relation name resolution
|
|
68
|
+
* GET /users?include=top_orders&fields[orders]=id,name
|
|
69
|
+
*/
|
|
70
|
+
convertRelationTableNameStrategy: false,
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* By default, the package expects the field names to match the database names
|
|
74
|
+
* For example, fetching the field named firstName would look like this:
|
|
75
|
+
* GET /users?fields=firstName
|
|
76
|
+
*
|
|
77
|
+
* Set this to `true` if you want to convert the firstName into first_name for the underlying query
|
|
78
|
+
*/
|
|
79
|
+
convertFieldNamesToSnakeCase: false,
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
export default apiQueryConfig
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AllowedFilter,
|
|
3
|
+
InvalidFilterQuery
|
|
4
|
+
} from "./chunk-PBQFWYKU.js";
|
|
5
|
+
import "./chunk-MKQ3HMMA.js";
|
|
6
|
+
import "./chunk-XIRHVLVQ.js";
|
|
7
|
+
|
|
8
|
+
// src/bindings/filters_query.ts
|
|
9
|
+
import collect from "collect.js";
|
|
10
|
+
var extendModelQueryBuilderWithFiltersQuery = function(builder, config) {
|
|
11
|
+
const ensureAllFiltersExist = (self) => {
|
|
12
|
+
if (config.disableInvalidFilterQueryException) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const filterNames = self.$apiQueryBuilderRequest.filters().keys();
|
|
16
|
+
const allowedFilterNames = self._allowedFilters.map((allowedFilter) => {
|
|
17
|
+
return allowedFilter.getName();
|
|
18
|
+
});
|
|
19
|
+
const diff = filterNames.diff(allowedFilterNames);
|
|
20
|
+
if (diff.isNotEmpty()) {
|
|
21
|
+
throw InvalidFilterQuery.filtersNotAllowed(diff.all(), allowedFilterNames.all());
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const isFilterRequested = (self, allowedFilter) => {
|
|
25
|
+
return self.$apiQueryBuilderRequest.filters().has(allowedFilter.getName());
|
|
26
|
+
};
|
|
27
|
+
const addRequestedFiltersToQuery = (query) => {
|
|
28
|
+
query._allowedFilters.each((allowedFilter) => {
|
|
29
|
+
if (isFilterRequested(query, allowedFilter)) {
|
|
30
|
+
const value = query.$apiQueryBuilderRequest.filters().get(allowedFilter.getName());
|
|
31
|
+
allowedFilter.filter(query, value);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (allowedFilter.hasDefault()) {
|
|
35
|
+
allowedFilter.filter(query, allowedFilter.getDefault());
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
builder.macro("allowedFilters", function(...filters) {
|
|
40
|
+
const arrayFilters = Array.isArray(filters.at(0)) ? filters.at(0) : filters;
|
|
41
|
+
this._allowedFilters = collect(arrayFilters).map((filter) => {
|
|
42
|
+
if (filter instanceof AllowedFilter) {
|
|
43
|
+
return filter;
|
|
44
|
+
}
|
|
45
|
+
return AllowedFilter.partial(filter);
|
|
46
|
+
});
|
|
47
|
+
ensureAllFiltersExist(this);
|
|
48
|
+
addRequestedFiltersToQuery(this);
|
|
49
|
+
return this;
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
export {
|
|
53
|
+
extendModelQueryBuilderWithFiltersQuery
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=filters_query-ZXNA4X75.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/bindings/filters_query.ts"],"sourcesContent":["/* eslint-disable unicorn/no-array-method-this-argument, unicorn/no-array-callback-reference */\nimport { type ModelQueryBuilder } from '@adonisjs/lucid/orm';\nimport { type LucidModel } from '@adonisjs/lucid/types/model';\nimport collect, { type Collection } from 'collect.js';\nimport { AllowedFilter } from '../allowed_filter.js';\nimport { InvalidFilterQuery } from '../exceptions/invalid_filter_query.js';\nimport { type ResolvedApiQueryConfig } from '../types.js';\n\ntype ModelQueryBuilderWithAllowedFilters = ModelQueryBuilder & {\n _allowedFilters: Collection<AllowedFilter<LucidModel>>;\n};\n\nexport const extendModelQueryBuilderWithFiltersQuery = function (\n builder: typeof ModelQueryBuilder,\n config: ResolvedApiQueryConfig,\n): void {\n const ensureAllFiltersExist = (self: ModelQueryBuilderWithAllowedFilters): void => {\n if (config.disableInvalidFilterQueryException) {\n return;\n }\n\n const filterNames = self.$apiQueryBuilderRequest.filters().keys();\n const allowedFilterNames = self._allowedFilters.map((allowedFilter) => {\n return allowedFilter.getName();\n });\n\n const diff = filterNames.diff(allowedFilterNames);\n\n if (diff.isNotEmpty()) {\n throw InvalidFilterQuery.filtersNotAllowed(diff.all(), allowedFilterNames.all());\n }\n };\n\n const isFilterRequested = (\n self: ModelQueryBuilderWithAllowedFilters,\n allowedFilter: AllowedFilter<LucidModel>,\n ): boolean => {\n return self.$apiQueryBuilderRequest.filters().has(allowedFilter.getName());\n };\n\n const addRequestedFiltersToQuery = (query: ModelQueryBuilderWithAllowedFilters): void => {\n query._allowedFilters.each((allowedFilter) => {\n if (isFilterRequested(query, allowedFilter)) {\n const value = query.$apiQueryBuilderRequest.filters().get(allowedFilter.getName());\n allowedFilter.filter(query, value);\n\n return;\n }\n\n if (allowedFilter.hasDefault()) {\n allowedFilter.filter(query, allowedFilter.getDefault());\n }\n });\n };\n\n builder.macro('allowedFilters', function (this: ModelQueryBuilderWithAllowedFilters, ...filters) {\n const arrayFilters = Array.isArray(filters.at(0))\n ? filters.at(0)\n : (filters as (AllowedFilter<LucidModel> | string)[]);\n this._allowedFilters = collect(arrayFilters).map((filter) => {\n if (filter instanceof AllowedFilter) {\n return filter;\n }\n\n return AllowedFilter.partial(filter);\n });\n\n ensureAllFiltersExist(this);\n addRequestedFiltersToQuery(this);\n\n return this;\n });\n};\n"],"mappings":";;;;;;;;AAGA,OAAO,aAAkC;AASlC,IAAM,0CAA0C,SACrD,SACA,QACM;AACN,QAAM,wBAAwB,CAAC,SAAoD;AACjF,QAAI,OAAO,oCAAoC;AAC7C;AAAA,IACF;AAEA,UAAM,cAAc,KAAK,wBAAwB,QAAQ,EAAE,KAAK;AAChE,UAAM,qBAAqB,KAAK,gBAAgB,IAAI,CAAC,kBAAkB;AACrE,aAAO,cAAc,QAAQ;AAAA,IAC/B,CAAC;AAED,UAAM,OAAO,YAAY,KAAK,kBAAkB;AAEhD,QAAI,KAAK,WAAW,GAAG;AACrB,YAAM,mBAAmB,kBAAkB,KAAK,IAAI,GAAG,mBAAmB,IAAI,CAAC;AAAA,IACjF;AAAA,EACF;AAEA,QAAM,oBAAoB,CACxB,MACA,kBACY;AACZ,WAAO,KAAK,wBAAwB,QAAQ,EAAE,IAAI,cAAc,QAAQ,CAAC;AAAA,EAC3E;AAEA,QAAM,6BAA6B,CAAC,UAAqD;AACvF,UAAM,gBAAgB,KAAK,CAAC,kBAAkB;AAC5C,UAAI,kBAAkB,OAAO,aAAa,GAAG;AAC3C,cAAM,QAAQ,MAAM,wBAAwB,QAAQ,EAAE,IAAI,cAAc,QAAQ,CAAC;AACjF,sBAAc,OAAO,OAAO,KAAK;AAEjC;AAAA,MACF;AAEA,UAAI,cAAc,WAAW,GAAG;AAC9B,sBAAc,OAAO,OAAO,cAAc,WAAW,CAAC;AAAA,MACxD;AAAA,IACF,CAAC;AAAA,EACH;AAEA,UAAQ,MAAM,kBAAkB,YAAwD,SAAS;AAC/F,UAAM,eAAe,MAAM,QAAQ,QAAQ,GAAG,CAAC,CAAC,IAC5C,QAAQ,GAAG,CAAC,IACX;AACL,SAAK,kBAAkB,QAAQ,YAAY,EAAE,IAAI,CAAC,WAAW;AAC3D,UAAI,kBAAkB,eAAe;AACnC,eAAO;AAAA,MACT;AAEA,aAAO,cAAc,QAAQ,MAAM;AAAA,IACrC,CAAC;AAED,0BAAsB,IAAI;AAC1B,+BAA2B,IAAI;AAE/B,WAAO;AAAA,EACT,CAAC;AACH;","names":[]}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AllowedInclude,
|
|
3
|
+
InvalidIncludeQuery
|
|
4
|
+
} from "./chunk-OS75QJZN.js";
|
|
5
|
+
import "./chunk-XIRHVLVQ.js";
|
|
6
|
+
|
|
7
|
+
// src/bindings/includes_query.ts
|
|
8
|
+
import { Collection } from "collect.js";
|
|
9
|
+
var extendModelQueryBuilderWithIncludesQuery = function(builder, config) {
|
|
10
|
+
const ensureAllIncludesExist = (self) => {
|
|
11
|
+
if (config.disableInvalidIncludesQueryException) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const includes = self.$apiQueryBuilderRequest.includes();
|
|
15
|
+
const allowedIncludeNames = self._allowedIncludes.map((allowedInclude) => {
|
|
16
|
+
return allowedInclude.getName();
|
|
17
|
+
});
|
|
18
|
+
const diff = includes.diff(allowedIncludeNames);
|
|
19
|
+
if (diff.isNotEmpty()) {
|
|
20
|
+
throw InvalidIncludeQuery.includesNotAllowed(diff.all(), allowedIncludeNames.all());
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const findInclude = (self, include) => {
|
|
24
|
+
return self._allowedIncludes.first((included) => included.isForInclude(include));
|
|
25
|
+
};
|
|
26
|
+
const filterNonExistingIncludes = (self) => {
|
|
27
|
+
const includes = self.$apiQueryBuilderRequest.includes();
|
|
28
|
+
if (!config.disableInvalidIncludesQueryException) {
|
|
29
|
+
return includes;
|
|
30
|
+
}
|
|
31
|
+
return includes.filter((include) => !findInclude(self, include));
|
|
32
|
+
};
|
|
33
|
+
const addIncludesToQuery = (self, includes) => {
|
|
34
|
+
includes.each((include) => {
|
|
35
|
+
const allowedInclude = findInclude(self, include);
|
|
36
|
+
allowedInclude?.include(self);
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
builder.macro("allowedIncludes", function(...includes) {
|
|
40
|
+
const arrayIncludes = Array.isArray(includes.at(0)) ? includes.at(0) : includes;
|
|
41
|
+
this._allowedIncludes = new Collection(arrayIncludes).reject((include) => typeof include === "string" && include.length === 0).reduce((result, include) => {
|
|
42
|
+
if (include instanceof Collection) {
|
|
43
|
+
for (const allowedInclude of include) {
|
|
44
|
+
result = result.push(allowedInclude);
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
if (include.endsWith(config.countSuffix)) {
|
|
49
|
+
for (const allowedInclude of AllowedInclude.count(include)) {
|
|
50
|
+
result = result.push(allowedInclude);
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
for (const allowedInclude of AllowedInclude.relationship(include)) {
|
|
55
|
+
result = result.push(allowedInclude);
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
}, new Collection()).unique((allowedInclude) => {
|
|
59
|
+
return allowedInclude.getName();
|
|
60
|
+
});
|
|
61
|
+
ensureAllIncludesExist(this);
|
|
62
|
+
const resultIncludes = filterNonExistingIncludes(this);
|
|
63
|
+
addIncludesToQuery(this, resultIncludes);
|
|
64
|
+
return this;
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
export {
|
|
68
|
+
extendModelQueryBuilderWithIncludesQuery
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=includes_query-2XNHHWJB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/bindings/includes_query.ts"],"sourcesContent":["import { type ModelQueryBuilder } from '@adonisjs/lucid/orm';\nimport { type LucidModel } from '@adonisjs/lucid/types/model';\nimport { Collection } from 'collect.js';\nimport { AllowedInclude } from '../allowed_include.js';\nimport { InvalidIncludeQuery } from '../exceptions/invalid_include_query.js';\nimport { type ResolvedApiQueryConfig } from '../types.js';\n\ntype ModelQueryBuilderWithAllowedIncludes = ModelQueryBuilder & {\n _allowedIncludes: Collection<AllowedInclude<LucidModel>>;\n};\n\nexport const extendModelQueryBuilderWithIncludesQuery = function (\n builder: typeof ModelQueryBuilder,\n config: ResolvedApiQueryConfig,\n): void {\n const ensureAllIncludesExist = (self: ModelQueryBuilderWithAllowedIncludes): void => {\n if (config.disableInvalidIncludesQueryException) {\n return;\n }\n\n const includes = self.$apiQueryBuilderRequest.includes();\n const allowedIncludeNames = self._allowedIncludes.map((allowedInclude) => {\n return allowedInclude.getName();\n });\n\n const diff = includes.diff(allowedIncludeNames);\n\n if (diff.isNotEmpty()) {\n throw InvalidIncludeQuery.includesNotAllowed(diff.all(), allowedIncludeNames.all());\n }\n };\n\n const findInclude = (\n self: ModelQueryBuilderWithAllowedIncludes,\n include: string,\n ): AllowedInclude<LucidModel> | undefined => {\n return self._allowedIncludes.first((included) => included.isForInclude(include));\n };\n\n const filterNonExistingIncludes = (self: ModelQueryBuilderWithAllowedIncludes) => {\n const includes = self.$apiQueryBuilderRequest.includes();\n\n if (!config.disableInvalidIncludesQueryException) {\n return includes;\n }\n\n return includes.filter((include) => !findInclude(self, include));\n };\n\n const addIncludesToQuery = (self: ModelQueryBuilderWithAllowedIncludes, includes: Collection<string>) => {\n includes.each((include) => {\n const allowedInclude = findInclude(self, include);\n allowedInclude?.include(self);\n });\n };\n\n builder.macro('allowedIncludes', function (this: ModelQueryBuilderWithAllowedIncludes, ...includes) {\n const arrayIncludes = Array.isArray(includes.at(0))\n ? includes.at(0)\n : (includes as (AllowedInclude<LucidModel> | string)[]);\n\n this._allowedIncludes = (\n new Collection(arrayIncludes)\n .reject((include) => typeof include === 'string' && include.length === 0)\n .reduce<Collection<AllowedInclude<LucidModel>>>((result, include) => {\n if (include instanceof Collection) {\n for (const allowedInclude of include) {\n result = result!.push(allowedInclude);\n }\n\n return result!;\n }\n\n if (include.endsWith(config.countSuffix)) {\n for (const allowedInclude of AllowedInclude.count(include)) {\n result = result!.push(allowedInclude);\n }\n\n return result!;\n }\n\n for (const allowedInclude of AllowedInclude.relationship(include)) {\n result = result!.push(allowedInclude);\n }\n\n return result!;\n }, new Collection()) as Collection<AllowedInclude<LucidModel>>\n ).unique((allowedInclude: AllowedInclude<LucidModel>) => {\n return allowedInclude.getName();\n });\n\n ensureAllIncludesExist(this);\n\n const resultIncludes = filterNonExistingIncludes(this);\n addIncludesToQuery(this, resultIncludes);\n\n return this;\n });\n};\n"],"mappings":";;;;;;;AAEA,SAAS,kBAAkB;AASpB,IAAM,2CAA2C,SACtD,SACA,QACM;AACN,QAAM,yBAAyB,CAAC,SAAqD;AACnF,QAAI,OAAO,sCAAsC;AAC/C;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,wBAAwB,SAAS;AACvD,UAAM,sBAAsB,KAAK,iBAAiB,IAAI,CAAC,mBAAmB;AACxE,aAAO,eAAe,QAAQ;AAAA,IAChC,CAAC;AAED,UAAM,OAAO,SAAS,KAAK,mBAAmB;AAE9C,QAAI,KAAK,WAAW,GAAG;AACrB,YAAM,oBAAoB,mBAAmB,KAAK,IAAI,GAAG,oBAAoB,IAAI,CAAC;AAAA,IACpF;AAAA,EACF;AAEA,QAAM,cAAc,CAClB,MACA,YAC2C;AAC3C,WAAO,KAAK,iBAAiB,MAAM,CAAC,aAAa,SAAS,aAAa,OAAO,CAAC;AAAA,EACjF;AAEA,QAAM,4BAA4B,CAAC,SAA+C;AAChF,UAAM,WAAW,KAAK,wBAAwB,SAAS;AAEvD,QAAI,CAAC,OAAO,sCAAsC;AAChD,aAAO;AAAA,IACT;AAEA,WAAO,SAAS,OAAO,CAAC,YAAY,CAAC,YAAY,MAAM,OAAO,CAAC;AAAA,EACjE;AAEA,QAAM,qBAAqB,CAAC,MAA4C,aAAiC;AACvG,aAAS,KAAK,CAAC,YAAY;AACzB,YAAM,iBAAiB,YAAY,MAAM,OAAO;AAChD,sBAAgB,QAAQ,IAAI;AAAA,IAC9B,CAAC;AAAA,EACH;AAEA,UAAQ,MAAM,mBAAmB,YAAyD,UAAU;AAClG,UAAM,gBAAgB,MAAM,QAAQ,SAAS,GAAG,CAAC,CAAC,IAC9C,SAAS,GAAG,CAAC,IACZ;AAEL,SAAK,mBACH,IAAI,WAAW,aAAa,EACzB,OAAO,CAAC,YAAY,OAAO,YAAY,YAAY,QAAQ,WAAW,CAAC,EACvE,OAA+C,CAAC,QAAQ,YAAY;AACnE,UAAI,mBAAmB,YAAY;AACjC,mBAAW,kBAAkB,SAAS;AACpC,mBAAS,OAAQ,KAAK,cAAc;AAAA,QACtC;AAEA,eAAO;AAAA,MACT;AAEA,UAAI,QAAQ,SAAS,OAAO,WAAW,GAAG;AACxC,mBAAW,kBAAkB,eAAe,MAAM,OAAO,GAAG;AAC1D,mBAAS,OAAQ,KAAK,cAAc;AAAA,QACtC;AAEA,eAAO;AAAA,MACT;AAEA,iBAAW,kBAAkB,eAAe,aAAa,OAAO,GAAG;AACjE,iBAAS,OAAQ,KAAK,cAAc;AAAA,MACtC;AAEA,aAAO;AAAA,IACT,GAAG,IAAI,WAAW,CAAC,EACrB,OAAO,CAAC,mBAA+C;AACvD,aAAO,eAAe,QAAQ;AAAA,IAChC,CAAC;AAED,2BAAuB,IAAI;AAE3B,UAAM,iBAAiB,0BAA0B,IAAI;AACrD,uBAAmB,MAAM,cAAc;AAEvC,WAAO;AAAA,EACT,CAAC;AACH;","names":[]}
|