@kadirgun/lucid-bravo 0.0.9 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/build/index.js +20 -29
- package/build/src/lucid_bravo.d.ts +9 -9
- package/build/stubs/make/bravos/main.stub +6 -3
- package/build/validators/index.d.ts +1 -0
- package/build/validators/index.js +6836 -0
- package/package.json +10 -2
package/README.md
CHANGED
|
@@ -37,15 +37,15 @@ export default class PostBravo extends LucidBravo<ModelType> {
|
|
|
37
37
|
protected model = Post
|
|
38
38
|
protected defaultLimit = 10
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
protected override getSortable(): LucidBravoAttributes<ModelType>[] {
|
|
41
41
|
return ['id', 'title']
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
protected override getAllowedIncludes(): LucidBravoRelations<Post>[] {
|
|
45
45
|
return ['labels']
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
protected async title(value: string) {
|
|
49
49
|
this.$query.where('title', 'like', `%${value}%`)
|
|
50
50
|
}
|
|
51
51
|
}
|
package/build/index.js
CHANGED
|
@@ -9,29 +9,21 @@ var LucidBravo = class {
|
|
|
9
9
|
$params;
|
|
10
10
|
$http;
|
|
11
11
|
$countQuery;
|
|
12
|
+
$filteredQuery;
|
|
13
|
+
applied = false;
|
|
12
14
|
defaultLimit = 20;
|
|
13
15
|
defaultSort = null;
|
|
14
16
|
constructor(params, query) {
|
|
15
17
|
this.$params = params || {};
|
|
16
18
|
this.$http = HttpContext.getOrFail();
|
|
17
|
-
if (query)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
19
|
+
if (query) this.$query = query;
|
|
20
|
+
else this.$query = this.getModel().query();
|
|
21
|
+
this.model = this.$query.model;
|
|
22
|
+
this.$countQuery = this.$query.clone();
|
|
22
23
|
}
|
|
23
24
|
static build(params, query) {
|
|
24
25
|
return new this(params, query);
|
|
25
26
|
}
|
|
26
|
-
resolveQuery() {
|
|
27
|
-
if (this.$query) return this.$query;
|
|
28
|
-
if (this.model) {
|
|
29
|
-
this.$query = this.model.query();
|
|
30
|
-
this.$countQuery = this.$query.clone();
|
|
31
|
-
return this.$query;
|
|
32
|
-
}
|
|
33
|
-
throw new Error("Either a query must be provided or $model must be set in the subclass");
|
|
34
|
-
}
|
|
35
27
|
/**
|
|
36
28
|
* Return a whitelist of sortable columns
|
|
37
29
|
*/
|
|
@@ -44,33 +36,37 @@ var LucidBravo = class {
|
|
|
44
36
|
getAllowedIncludes() {
|
|
45
37
|
return [];
|
|
46
38
|
}
|
|
39
|
+
getModel() {
|
|
40
|
+
if (this.model) return this.model;
|
|
41
|
+
throw new Error("Model not defined");
|
|
42
|
+
}
|
|
47
43
|
/**
|
|
48
44
|
* Main entry point to apply all filters, includes, sorting and pagination
|
|
49
45
|
*/
|
|
50
46
|
async apply() {
|
|
51
|
-
this.
|
|
47
|
+
if (this.applied) return this.$query;
|
|
52
48
|
await this.applyFilters();
|
|
53
49
|
await this.applyIncludes();
|
|
54
50
|
await this.applySorting();
|
|
55
51
|
await this.applyPagination();
|
|
52
|
+
this.applied = true;
|
|
56
53
|
return this.$query;
|
|
57
54
|
}
|
|
58
|
-
async count() {
|
|
59
|
-
|
|
60
|
-
const result = await this.$countQuery.count("* as total").firstOrFail();
|
|
55
|
+
async count(query) {
|
|
56
|
+
const result = await query.count("* as total").firstOrFail();
|
|
61
57
|
return Number(result.$extras.total);
|
|
62
58
|
}
|
|
63
59
|
async paginate() {
|
|
64
60
|
return {
|
|
65
61
|
items: await this.apply(),
|
|
66
|
-
total: await this.count()
|
|
62
|
+
total: await this.count(this.$countQuery),
|
|
63
|
+
filtered: await this.count(this.$filteredQuery)
|
|
67
64
|
};
|
|
68
65
|
}
|
|
69
66
|
/**
|
|
70
67
|
* Automatically call methods that match camelCase version of snake_case params
|
|
71
68
|
*/
|
|
72
69
|
async applyFilters() {
|
|
73
|
-
this.resolveQuery();
|
|
74
70
|
for (const [key, value] of Object.entries(this.$params)) {
|
|
75
71
|
if ([
|
|
76
72
|
"page",
|
|
@@ -84,25 +80,24 @@ var LucidBravo = class {
|
|
|
84
80
|
if (typeof method !== "function") throw new Error(`Expected ${methodName} to be a method on ${this.constructor.name}`);
|
|
85
81
|
await method.call(this, value);
|
|
86
82
|
}
|
|
83
|
+
this.$filteredQuery = this.$query.clone();
|
|
87
84
|
}
|
|
88
85
|
/**
|
|
89
86
|
* Apply preload include relations based on allowlist
|
|
90
87
|
*/
|
|
91
88
|
async applyIncludes() {
|
|
92
|
-
const query = this.resolveQuery();
|
|
93
89
|
const includes = this.$params.include;
|
|
94
90
|
if (!Array.isArray(includes) || includes.length === 0) return;
|
|
95
91
|
const allowed = this.getAllowedIncludes();
|
|
96
92
|
for (const relation of includes) {
|
|
97
93
|
if (!allowed.includes(relation)) continue;
|
|
98
|
-
query.preload(relation);
|
|
94
|
+
this.$query.preload(relation);
|
|
99
95
|
}
|
|
100
96
|
}
|
|
101
97
|
/**
|
|
102
98
|
* Apply sorting based on sort[field] and sort[order] params
|
|
103
99
|
*/
|
|
104
100
|
async applySorting() {
|
|
105
|
-
const query = this.resolveQuery();
|
|
106
101
|
const sort = this.$params.sort;
|
|
107
102
|
const sortable = this.getSortable();
|
|
108
103
|
let field = sort?.field;
|
|
@@ -111,16 +106,12 @@ var LucidBravo = class {
|
|
|
111
106
|
field = this.defaultSort.field;
|
|
112
107
|
order = this.defaultSort.order;
|
|
113
108
|
}
|
|
114
|
-
if (field && sortable.includes(field)) query.orderBy(field, order);
|
|
109
|
+
if (field && sortable.includes(field)) this.$query.orderBy(field, order);
|
|
115
110
|
}
|
|
116
|
-
/**
|
|
117
|
-
* Apply simple limit and offset pagination
|
|
118
|
-
*/
|
|
119
111
|
async applyPagination() {
|
|
120
|
-
const query = this.resolveQuery();
|
|
121
112
|
const limit = Number(this.$params.limit) || this.defaultLimit;
|
|
122
113
|
const offset = ((Number(this.$params.page) || 1) - 1) * limit;
|
|
123
|
-
if (limit > 0) query.limit(limit).offset(offset);
|
|
114
|
+
if (limit > 0) this.$query.limit(limit).offset(offset);
|
|
124
115
|
}
|
|
125
116
|
};
|
|
126
117
|
//#endregion
|
|
@@ -1,34 +1,37 @@
|
|
|
1
1
|
import type { LucidModel, ModelQueryBuilderContract } from '@adonisjs/lucid/types/model';
|
|
2
|
-
import type { BravoParams, BravoSortOption, LucidBravoRelations, LucidBravoAttributes } from './types.ts';
|
|
3
2
|
import { HttpContext } from '@adonisjs/core/http';
|
|
4
3
|
import type { Constructor } from '@adonisjs/core/types/common';
|
|
4
|
+
import type { BravoParams, BravoSortOption, LucidBravoAttributes, LucidBravoRelations } from './types.ts';
|
|
5
5
|
export declare abstract class LucidBravo<T extends LucidModel> {
|
|
6
|
-
|
|
6
|
+
private model;
|
|
7
7
|
protected $query: ModelQueryBuilderContract<T>;
|
|
8
8
|
protected $params: BravoParams;
|
|
9
9
|
protected $http: HttpContext;
|
|
10
10
|
protected $countQuery: ModelQueryBuilderContract<T>;
|
|
11
|
+
protected $filteredQuery: ModelQueryBuilderContract<T>;
|
|
12
|
+
private applied;
|
|
11
13
|
protected defaultLimit: number;
|
|
12
14
|
protected defaultSort: BravoSortOption | null;
|
|
13
15
|
constructor(params?: BravoParams, query?: ModelQueryBuilderContract<T>);
|
|
14
16
|
static build<T extends LucidModel, B extends LucidBravo<T>>(this: Constructor<B>, params?: BravoParams, query?: ModelQueryBuilderContract<T>): B;
|
|
15
|
-
protected resolveQuery(): ModelQueryBuilderContract<T, InstanceType<T>>;
|
|
16
17
|
/**
|
|
17
18
|
* Return a whitelist of sortable columns
|
|
18
19
|
*/
|
|
19
|
-
getSortable(): LucidBravoAttributes<T>[];
|
|
20
|
+
protected getSortable(): LucidBravoAttributes<T>[];
|
|
20
21
|
/**
|
|
21
22
|
* Return a whitelist of allowed relations for preload include
|
|
22
23
|
*/
|
|
23
|
-
getAllowedIncludes(): LucidBravoRelations<InstanceType<T>>[];
|
|
24
|
+
protected getAllowedIncludes(): LucidBravoRelations<InstanceType<T>>[];
|
|
25
|
+
protected getModel(): T;
|
|
24
26
|
/**
|
|
25
27
|
* Main entry point to apply all filters, includes, sorting and pagination
|
|
26
28
|
*/
|
|
27
29
|
apply(): Promise<InstanceType<T>[]>;
|
|
28
|
-
count
|
|
30
|
+
private count;
|
|
29
31
|
paginate(): Promise<{
|
|
30
32
|
items: InstanceType<T>[];
|
|
31
33
|
total: number;
|
|
34
|
+
filtered: number;
|
|
32
35
|
}>;
|
|
33
36
|
/**
|
|
34
37
|
* Automatically call methods that match camelCase version of snake_case params
|
|
@@ -42,8 +45,5 @@ export declare abstract class LucidBravo<T extends LucidModel> {
|
|
|
42
45
|
* Apply sorting based on sort[field] and sort[order] params
|
|
43
46
|
*/
|
|
44
47
|
protected applySorting(): Promise<void>;
|
|
45
|
-
/**
|
|
46
|
-
* Apply simple limit and offset pagination
|
|
47
|
-
*/
|
|
48
48
|
protected applyPagination(): Promise<void>;
|
|
49
49
|
}
|
|
@@ -14,14 +14,17 @@ import {{ entity.name }} from '{{ modelImportPath }}'
|
|
|
14
14
|
type ModelType = typeof {{ entity.name }}
|
|
15
15
|
|
|
16
16
|
export default class {{ modelName }}Bravo extends LucidBravo<ModelType> {
|
|
17
|
-
protected model = {{ entity.name }}
|
|
18
17
|
protected defaultLimit = 20
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
protected getModel(): ModelType {
|
|
20
|
+
return {{ modelName }}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
protected override getSortable(): LucidBravoAttributes<ModelType>[] {
|
|
21
24
|
return []
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
|
|
27
|
+
protected override getAllowedIncludes(): LucidBravoRelations<{{ entity.name }}>[] {
|
|
25
28
|
return []
|
|
26
29
|
}
|
|
27
30
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { bravoSchema, bravoValidator } from './bravo.ts';
|