create-m5kdev 0.13.0 → 0.13.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/package.json
CHANGED
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
import { BaseTableRepository } from "@m5kdev/backend/modules/base/base.repository";
|
|
7
7
|
import type { ServerResultAsync } from "@m5kdev/backend/utils/types";
|
|
8
8
|
import { and, asc, count, desc, eq, isNull, like, ne, or } from "drizzle-orm";
|
|
9
|
-
import { ok } from "neverthrow";
|
|
9
|
+
import { err, ok } from "neverthrow";
|
|
10
10
|
import type { Orm, Schema } from "../../db";
|
|
11
11
|
|
|
12
12
|
export class PostsRepository extends BaseTableRepository<
|
|
@@ -16,73 +16,82 @@ export class PostsRepository extends BaseTableRepository<
|
|
|
16
16
|
Schema["posts"]
|
|
17
17
|
> {
|
|
18
18
|
async list(input: PostsListInputSchema = {}): ServerResultAsync<PostsListOutputSchema> {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const conditions = [isNull(this.table.deletedAt)];
|
|
19
|
+
const page = input.page ?? 1;
|
|
20
|
+
const limit = input.limit ?? 6;
|
|
21
|
+
const search = input.search?.trim();
|
|
22
|
+
const conditions = [isNull(this.table.deletedAt)];
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (search) {
|
|
30
|
-
const pattern = `%${search}%`;
|
|
31
|
-
const searchCondition = or(
|
|
32
|
-
like(this.table.title, pattern),
|
|
33
|
-
like(this.table.slug, pattern),
|
|
34
|
-
like(this.table.excerpt, pattern),
|
|
35
|
-
like(this.table.content, pattern)
|
|
36
|
-
);
|
|
24
|
+
if (input.status) {
|
|
25
|
+
conditions.push(eq(this.table.status, input.status));
|
|
26
|
+
}
|
|
37
27
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
if (search) {
|
|
29
|
+
const escapedSearch = search.replace(/[%_]/g, '\\ if (search) {
|
|
30
|
+
const pattern = `%${search}%`;
|
|
31
|
+
const searchCondition = or(
|
|
32
|
+
like(this.table.title, pattern),
|
|
33
|
+
like(this.table.slug, pattern),
|
|
34
|
+
like(this.table.excerpt, pattern),
|
|
35
|
+
like(this.table.content, pattern)
|
|
36
|
+
);
|
|
37
|
+
');
|
|
38
|
+
const pattern = `%${escapedSearch}%`;
|
|
39
|
+
const searchCondition = or(
|
|
40
|
+
like(this.table.title, pattern),
|
|
41
|
+
like(this.table.slug, pattern),
|
|
42
|
+
like(this.table.excerpt, pattern),
|
|
43
|
+
like(this.table.content, pattern)
|
|
44
|
+
);
|
|
45
|
+
if (searchCondition) {
|
|
46
|
+
conditions.push(searchCondition);
|
|
41
47
|
}
|
|
48
|
+
}
|
|
42
49
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
50
|
+
const whereClause = and(...conditions);
|
|
51
|
+
const ordering =
|
|
52
|
+
input.sort === "title"
|
|
53
|
+
? input.order === "asc"
|
|
54
|
+
? asc(this.table.title)
|
|
55
|
+
: desc(this.table.title)
|
|
56
|
+
: input.sort === "publishedAt"
|
|
46
57
|
? input.order === "asc"
|
|
47
|
-
? asc(this.table.
|
|
48
|
-
: desc(this.table.
|
|
49
|
-
: input.
|
|
50
|
-
?
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
? asc(this.table.publishedAt)
|
|
59
|
+
: desc(this.table.publishedAt)
|
|
60
|
+
: input.order === "asc"
|
|
61
|
+
? asc(this.table.updatedAt)
|
|
62
|
+
: desc(this.table.updatedAt);
|
|
63
|
+
|
|
64
|
+
const rowsQuery = this.orm
|
|
65
|
+
.select()
|
|
66
|
+
.from(this.table)
|
|
67
|
+
.where(whereClause)
|
|
68
|
+
.orderBy(ordering, desc(this.table.createdAt))
|
|
69
|
+
.limit(limit)
|
|
70
|
+
.offset((page - 1) * limit);
|
|
56
71
|
|
|
57
|
-
|
|
58
|
-
.select()
|
|
59
|
-
.from(this.table)
|
|
60
|
-
.where(whereClause)
|
|
61
|
-
.orderBy(ordering, desc(this.table.createdAt))
|
|
62
|
-
.limit(limit)
|
|
63
|
-
.offset((page - 1) * limit);
|
|
72
|
+
const countQuery = this.orm.select({ count: count() }).from(this.table).where(whereClause);
|
|
64
73
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
.where(whereClause);
|
|
74
|
+
const result = await this.throwableQuery(() => Promise.all([rowsQuery, countQuery]));
|
|
75
|
+
if (result.isErr()) return err(result.error);
|
|
76
|
+
const [rows, [totalRow]] = result.value;
|
|
69
77
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
});
|
|
78
|
+
return ok({
|
|
79
|
+
rows: rows as PostSchema[],
|
|
80
|
+
total: totalRow?.count ?? 0,
|
|
74
81
|
});
|
|
75
82
|
}
|
|
76
83
|
|
|
77
84
|
async findBySlug(slug: string, excludeId?: string) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
: and(eq(this.table.slug, slug), isNull(this.table.deletedAt));
|
|
85
|
+
const whereClause = excludeId
|
|
86
|
+
? and(eq(this.table.slug, slug), ne(this.table.id, excludeId), isNull(this.table.deletedAt))
|
|
87
|
+
: and(eq(this.table.slug, slug), isNull(this.table.deletedAt));
|
|
82
88
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
89
|
+
const result = await this.throwableQuery(() =>
|
|
90
|
+
this.orm.select().from(this.table).where(whereClause).limit(1)
|
|
91
|
+
);
|
|
92
|
+
if (result.isErr()) return err(result.error);
|
|
93
|
+
const [row] = result.value;
|
|
94
|
+
return ok(row);
|
|
86
95
|
}
|
|
87
96
|
|
|
88
97
|
async resolveUniqueSlug(candidate: string, excludeId?: string) {
|