@m5kdev/backend 0.8.8 → 0.8.10
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/dist/src/modules/auth/auth.dto.d.cts +6 -6
- package/dist/src/modules/auth/auth.dto.d.mts +6 -6
- package/dist/src/modules/auth/auth.lib.d.cts +4 -4
- package/dist/src/modules/auth/auth.lib.d.mts +4 -4
- package/dist/src/modules/auth/auth.trpc.d.cts +17 -17
- package/dist/src/modules/auth/auth.trpc.d.mts +17 -17
- package/dist/src/modules/base/base.repository.cjs +1 -1
- package/dist/src/modules/base/base.repository.mjs +1 -1
- package/dist/src/modules/billing/billing.repository.d.cts +11 -11
- package/dist/src/modules/billing/billing.service.d.cts +7 -7
- package/dist/src/modules/connect/connect.dto.d.cts +8 -8
- package/dist/src/modules/connect/connect.dto.d.mts +8 -8
- package/dist/src/modules/connect/connect.repository.d.cts +6 -6
- package/dist/src/modules/connect/connect.repository.d.mts +6 -6
- package/dist/src/modules/connect/connect.service.d.cts +12 -12
- package/dist/src/modules/connect/connect.service.d.mts +12 -12
- package/dist/src/modules/connect/connect.trpc.d.cts +4 -4
- package/dist/src/modules/connect/connect.trpc.d.mts +4 -4
- package/dist/src/modules/recurrence/recurrence.service.d.cts +4 -4
- package/dist/src/modules/recurrence/recurrence.service.d.mts +4 -4
- package/dist/src/modules/recurrence/recurrence.trpc.d.cts +2 -2
- package/dist/src/modules/recurrence/recurrence.trpc.d.mts +2 -2
- package/dist/src/modules/tag/tag.trpc.d.cts +4 -4
- package/dist/src/modules/tag/tag.trpc.d.mts +4 -4
- package/dist/src/modules/utils/getConditionsFromFilters.cjs +32 -0
- package/dist/src/modules/utils/getConditionsFromFilters.cjs.map +1 -1
- package/dist/src/modules/utils/getConditionsFromFilters.mjs +33 -1
- package/dist/src/modules/utils/getConditionsFromFilters.mjs.map +1 -1
- package/dist/src/types.d.cts +17 -17
- package/dist/src/types.d.mts +17 -17
- package/package.json +3 -3
|
@@ -394,24 +394,24 @@ declare class ConnectRepository extends BaseTableRepository<Orm, Schema, Record<
|
|
|
394
394
|
}[]>>;
|
|
395
395
|
upsert(data: ConnectInsert, tx?: Orm): Promise<ServerResult<{
|
|
396
396
|
id: string;
|
|
397
|
-
createdAt: Date;
|
|
398
|
-
updatedAt: Date | null;
|
|
399
|
-
expiresAt: Date | null;
|
|
400
397
|
userId: string;
|
|
401
398
|
provider: string;
|
|
402
|
-
accessToken: string;
|
|
403
|
-
refreshToken: string | null;
|
|
404
|
-
scope: string | null;
|
|
405
399
|
accountType: string;
|
|
406
400
|
providerAccountId: string;
|
|
407
401
|
handle: string | null;
|
|
408
402
|
displayName: string | null;
|
|
409
403
|
avatarUrl: string | null;
|
|
404
|
+
accessToken: string;
|
|
405
|
+
refreshToken: string | null;
|
|
410
406
|
tokenType: string | null;
|
|
407
|
+
scope: string | null;
|
|
408
|
+
expiresAt: Date | null;
|
|
411
409
|
parentId: string | null;
|
|
412
410
|
metadataJson: unknown;
|
|
413
411
|
revokedAt: Date | null;
|
|
414
412
|
lastRefreshedAt: Date | null;
|
|
413
|
+
createdAt: Date;
|
|
414
|
+
updatedAt: Date | null;
|
|
415
415
|
}>>;
|
|
416
416
|
}
|
|
417
417
|
//#endregion
|
|
@@ -20,45 +20,45 @@ declare class ConnectService extends BaseService<{
|
|
|
20
20
|
}>;
|
|
21
21
|
handleCallback(user: User, sessionId: string, providerId: string, code: string, state: string): Promise<ServerResult<{
|
|
22
22
|
id: string;
|
|
23
|
-
createdAt: Date;
|
|
24
|
-
updatedAt: Date | null;
|
|
25
|
-
expiresAt: Date | null;
|
|
26
23
|
userId: string;
|
|
27
24
|
provider: string;
|
|
28
|
-
accessToken: string;
|
|
29
|
-
refreshToken: string | null;
|
|
30
|
-
scope: string | null;
|
|
31
25
|
accountType: string;
|
|
32
26
|
providerAccountId: string;
|
|
33
27
|
handle: string | null;
|
|
34
28
|
displayName: string | null;
|
|
35
29
|
avatarUrl: string | null;
|
|
30
|
+
accessToken: string;
|
|
31
|
+
refreshToken: string | null;
|
|
36
32
|
tokenType: string | null;
|
|
33
|
+
scope: string | null;
|
|
34
|
+
expiresAt: Date | null;
|
|
37
35
|
parentId: string | null;
|
|
38
36
|
metadataJson: unknown;
|
|
39
37
|
revokedAt: Date | null;
|
|
40
38
|
lastRefreshedAt: Date | null;
|
|
39
|
+
createdAt: Date;
|
|
40
|
+
updatedAt: Date | null;
|
|
41
41
|
}>>;
|
|
42
42
|
refreshToken(connectionId: string): Promise<ServerResult<{
|
|
43
43
|
id: string;
|
|
44
|
-
createdAt: Date;
|
|
45
|
-
updatedAt: Date | null;
|
|
46
|
-
expiresAt: Date | null;
|
|
47
44
|
userId: string;
|
|
48
45
|
provider: string;
|
|
49
|
-
accessToken: string;
|
|
50
|
-
refreshToken: string | null;
|
|
51
|
-
scope: string | null;
|
|
52
46
|
accountType: string;
|
|
53
47
|
providerAccountId: string;
|
|
54
48
|
handle: string | null;
|
|
55
49
|
displayName: string | null;
|
|
56
50
|
avatarUrl: string | null;
|
|
51
|
+
accessToken: string;
|
|
52
|
+
refreshToken: string | null;
|
|
57
53
|
tokenType: string | null;
|
|
54
|
+
scope: string | null;
|
|
55
|
+
expiresAt: Date | null;
|
|
58
56
|
parentId: string | null;
|
|
59
57
|
metadataJson: unknown;
|
|
60
58
|
revokedAt: Date | null;
|
|
61
59
|
lastRefreshedAt: Date | null;
|
|
60
|
+
createdAt: Date;
|
|
61
|
+
updatedAt: Date | null;
|
|
62
62
|
}>>;
|
|
63
63
|
readonly list: ServiceProcedure<{
|
|
64
64
|
providers?: string[] | undefined;
|
|
@@ -20,45 +20,45 @@ declare class ConnectService extends BaseService<{
|
|
|
20
20
|
}>;
|
|
21
21
|
handleCallback(user: User, sessionId: string, providerId: string, code: string, state: string): Promise<ServerResult<{
|
|
22
22
|
id: string;
|
|
23
|
-
createdAt: Date;
|
|
24
|
-
updatedAt: Date | null;
|
|
25
|
-
expiresAt: Date | null;
|
|
26
23
|
userId: string;
|
|
27
24
|
provider: string;
|
|
28
|
-
accessToken: string;
|
|
29
|
-
refreshToken: string | null;
|
|
30
|
-
scope: string | null;
|
|
31
25
|
accountType: string;
|
|
32
26
|
providerAccountId: string;
|
|
33
27
|
handle: string | null;
|
|
34
28
|
displayName: string | null;
|
|
35
29
|
avatarUrl: string | null;
|
|
30
|
+
accessToken: string;
|
|
31
|
+
refreshToken: string | null;
|
|
36
32
|
tokenType: string | null;
|
|
33
|
+
scope: string | null;
|
|
34
|
+
expiresAt: Date | null;
|
|
37
35
|
parentId: string | null;
|
|
38
36
|
metadataJson: unknown;
|
|
39
37
|
revokedAt: Date | null;
|
|
40
38
|
lastRefreshedAt: Date | null;
|
|
39
|
+
createdAt: Date;
|
|
40
|
+
updatedAt: Date | null;
|
|
41
41
|
}>>;
|
|
42
42
|
refreshToken(connectionId: string): Promise<ServerResult<{
|
|
43
43
|
id: string;
|
|
44
|
-
createdAt: Date;
|
|
45
|
-
updatedAt: Date | null;
|
|
46
|
-
expiresAt: Date | null;
|
|
47
44
|
userId: string;
|
|
48
45
|
provider: string;
|
|
49
|
-
accessToken: string;
|
|
50
|
-
refreshToken: string | null;
|
|
51
|
-
scope: string | null;
|
|
52
46
|
accountType: string;
|
|
53
47
|
providerAccountId: string;
|
|
54
48
|
handle: string | null;
|
|
55
49
|
displayName: string | null;
|
|
56
50
|
avatarUrl: string | null;
|
|
51
|
+
accessToken: string;
|
|
52
|
+
refreshToken: string | null;
|
|
57
53
|
tokenType: string | null;
|
|
54
|
+
scope: string | null;
|
|
55
|
+
expiresAt: Date | null;
|
|
58
56
|
parentId: string | null;
|
|
59
57
|
metadataJson: unknown;
|
|
60
58
|
revokedAt: Date | null;
|
|
61
59
|
lastRefreshedAt: Date | null;
|
|
60
|
+
createdAt: Date;
|
|
61
|
+
updatedAt: Date | null;
|
|
62
62
|
}>>;
|
|
63
63
|
readonly list: ServiceProcedure<{
|
|
64
64
|
providers?: string[] | undefined;
|
|
@@ -19,22 +19,22 @@ declare function createConnectTRPC({
|
|
|
19
19
|
};
|
|
20
20
|
output: {
|
|
21
21
|
id: string;
|
|
22
|
-
createdAt: Date;
|
|
23
22
|
userId: string;
|
|
24
23
|
provider: string;
|
|
25
24
|
accountType: string;
|
|
26
25
|
providerAccountId: string;
|
|
27
|
-
|
|
28
|
-
expiresAt?: Date | null | undefined;
|
|
29
|
-
scope?: string | null | undefined;
|
|
26
|
+
createdAt: Date;
|
|
30
27
|
handle?: string | null | undefined;
|
|
31
28
|
displayName?: string | null | undefined;
|
|
32
29
|
avatarUrl?: string | null | undefined;
|
|
33
30
|
tokenType?: string | null | undefined;
|
|
31
|
+
scope?: string | null | undefined;
|
|
32
|
+
expiresAt?: Date | null | undefined;
|
|
34
33
|
parentId?: string | null | undefined;
|
|
35
34
|
metadataJson?: unknown;
|
|
36
35
|
revokedAt?: Date | null | undefined;
|
|
37
36
|
lastRefreshedAt?: Date | null | undefined;
|
|
37
|
+
updatedAt?: Date | null | undefined;
|
|
38
38
|
}[];
|
|
39
39
|
meta: any;
|
|
40
40
|
}>;
|
|
@@ -19,22 +19,22 @@ declare function createConnectTRPC({
|
|
|
19
19
|
};
|
|
20
20
|
output: {
|
|
21
21
|
id: string;
|
|
22
|
-
createdAt: Date;
|
|
23
22
|
userId: string;
|
|
24
23
|
provider: string;
|
|
25
24
|
accountType: string;
|
|
26
25
|
providerAccountId: string;
|
|
27
|
-
|
|
28
|
-
expiresAt?: Date | null | undefined;
|
|
29
|
-
scope?: string | null | undefined;
|
|
26
|
+
createdAt: Date;
|
|
30
27
|
handle?: string | null | undefined;
|
|
31
28
|
displayName?: string | null | undefined;
|
|
32
29
|
avatarUrl?: string | null | undefined;
|
|
33
30
|
tokenType?: string | null | undefined;
|
|
31
|
+
scope?: string | null | undefined;
|
|
32
|
+
expiresAt?: Date | null | undefined;
|
|
34
33
|
parentId?: string | null | undefined;
|
|
35
34
|
metadataJson?: unknown;
|
|
36
35
|
revokedAt?: Date | null | undefined;
|
|
37
36
|
lastRefreshedAt?: Date | null | undefined;
|
|
37
|
+
updatedAt?: Date | null | undefined;
|
|
38
38
|
}[];
|
|
39
39
|
meta: any;
|
|
40
40
|
}>;
|
|
@@ -17,8 +17,8 @@ declare class RecurrenceService extends BaseService<{
|
|
|
17
17
|
order?: "asc" | "desc" | undefined;
|
|
18
18
|
filters?: {
|
|
19
19
|
columnId: string;
|
|
20
|
-
type: "string" | "number" | "boolean" | "date" | "enum";
|
|
21
|
-
method: "
|
|
20
|
+
type: "string" | "number" | "boolean" | "date" | "enum" | "jsonArray";
|
|
21
|
+
method: "intersect" | "contains" | "starts_with" | "ends_with" | "equals" | "greater_than" | "less_than" | "on" | "between" | "before" | "after" | "oneOf" | "isEmpty" | "isNotEmpty" | "is_null" | "is_not_null";
|
|
22
22
|
value: string | number | boolean | string[];
|
|
23
23
|
valueTo?: string | undefined;
|
|
24
24
|
endColumnId?: string | undefined;
|
|
@@ -30,11 +30,11 @@ declare class RecurrenceService extends BaseService<{
|
|
|
30
30
|
actor: UserActor;
|
|
31
31
|
}, {
|
|
32
32
|
rows: {
|
|
33
|
-
name: string | null;
|
|
34
33
|
id: string;
|
|
34
|
+
name: string | null;
|
|
35
|
+
userId: string | null;
|
|
35
36
|
createdAt: Date;
|
|
36
37
|
updatedAt: Date;
|
|
37
|
-
userId: string | null;
|
|
38
38
|
metadata: Record<string, any> | null;
|
|
39
39
|
organizationId: string | null;
|
|
40
40
|
teamId: string | null;
|
|
@@ -17,8 +17,8 @@ declare class RecurrenceService extends BaseService<{
|
|
|
17
17
|
order?: "asc" | "desc" | undefined;
|
|
18
18
|
filters?: {
|
|
19
19
|
columnId: string;
|
|
20
|
-
type: "string" | "number" | "boolean" | "date" | "enum";
|
|
21
|
-
method: "
|
|
20
|
+
type: "string" | "number" | "boolean" | "date" | "enum" | "jsonArray";
|
|
21
|
+
method: "intersect" | "contains" | "starts_with" | "ends_with" | "equals" | "greater_than" | "less_than" | "on" | "between" | "before" | "after" | "oneOf" | "isEmpty" | "isNotEmpty" | "is_null" | "is_not_null";
|
|
22
22
|
value: string | number | boolean | string[];
|
|
23
23
|
valueTo?: string | undefined;
|
|
24
24
|
endColumnId?: string | undefined;
|
|
@@ -30,11 +30,11 @@ declare class RecurrenceService extends BaseService<{
|
|
|
30
30
|
actor: UserActor;
|
|
31
31
|
}, {
|
|
32
32
|
rows: {
|
|
33
|
-
name: string | null;
|
|
34
33
|
id: string;
|
|
34
|
+
name: string | null;
|
|
35
|
+
userId: string | null;
|
|
35
36
|
createdAt: Date;
|
|
36
37
|
updatedAt: Date;
|
|
37
|
-
userId: string | null;
|
|
38
38
|
metadata: Record<string, any> | null;
|
|
39
39
|
organizationId: string | null;
|
|
40
40
|
teamId: string | null;
|
|
@@ -20,8 +20,8 @@ declare function createRecurrenceTRPC({
|
|
|
20
20
|
order?: "asc" | "desc" | undefined;
|
|
21
21
|
filters?: {
|
|
22
22
|
columnId: string;
|
|
23
|
-
type: "string" | "number" | "boolean" | "date" | "enum";
|
|
24
|
-
method: "
|
|
23
|
+
type: "string" | "number" | "boolean" | "date" | "enum" | "jsonArray";
|
|
24
|
+
method: "intersect" | "contains" | "starts_with" | "ends_with" | "equals" | "greater_than" | "less_than" | "on" | "between" | "before" | "after" | "oneOf" | "isEmpty" | "isNotEmpty" | "is_null" | "is_not_null";
|
|
25
25
|
value: string | number | boolean | string[];
|
|
26
26
|
valueTo?: string | undefined;
|
|
27
27
|
endColumnId?: string | undefined;
|
|
@@ -20,8 +20,8 @@ declare function createRecurrenceTRPC({
|
|
|
20
20
|
order?: "asc" | "desc" | undefined;
|
|
21
21
|
filters?: {
|
|
22
22
|
columnId: string;
|
|
23
|
-
type: "string" | "number" | "boolean" | "date" | "enum";
|
|
24
|
-
method: "
|
|
23
|
+
type: "string" | "number" | "boolean" | "date" | "enum" | "jsonArray";
|
|
24
|
+
method: "intersect" | "contains" | "starts_with" | "ends_with" | "equals" | "greater_than" | "less_than" | "on" | "between" | "before" | "after" | "oneOf" | "isEmpty" | "isNotEmpty" | "is_null" | "is_not_null";
|
|
25
25
|
value: string | number | boolean | string[];
|
|
26
26
|
valueTo?: string | undefined;
|
|
27
27
|
endColumnId?: string | undefined;
|
|
@@ -20,8 +20,8 @@ declare function createTagTRPC({
|
|
|
20
20
|
order?: "asc" | "desc" | undefined;
|
|
21
21
|
filters?: {
|
|
22
22
|
columnId: string;
|
|
23
|
-
type: "string" | "number" | "boolean" | "date" | "enum";
|
|
24
|
-
method: "
|
|
23
|
+
type: "string" | "number" | "boolean" | "date" | "enum" | "jsonArray";
|
|
24
|
+
method: "intersect" | "contains" | "starts_with" | "ends_with" | "equals" | "greater_than" | "less_than" | "on" | "between" | "before" | "after" | "oneOf" | "isEmpty" | "isNotEmpty" | "is_null" | "is_not_null";
|
|
25
25
|
value: string | number | boolean | string[];
|
|
26
26
|
valueTo?: string | undefined;
|
|
27
27
|
endColumnId?: string | undefined;
|
|
@@ -54,8 +54,8 @@ declare function createTagTRPC({
|
|
|
54
54
|
resourceType: string;
|
|
55
55
|
resourceIds?: {
|
|
56
56
|
columnId: string;
|
|
57
|
-
type: "string" | "number" | "boolean" | "date" | "enum";
|
|
58
|
-
method: "
|
|
57
|
+
type: "string" | "number" | "boolean" | "date" | "enum" | "jsonArray";
|
|
58
|
+
method: "intersect" | "contains" | "starts_with" | "ends_with" | "equals" | "greater_than" | "less_than" | "on" | "between" | "before" | "after" | "oneOf" | "isEmpty" | "isNotEmpty" | "is_null" | "is_not_null";
|
|
59
59
|
value: string | number | boolean | string[];
|
|
60
60
|
valueTo?: string | undefined;
|
|
61
61
|
endColumnId?: string | undefined;
|
|
@@ -20,8 +20,8 @@ declare function createTagTRPC({
|
|
|
20
20
|
order?: "asc" | "desc" | undefined;
|
|
21
21
|
filters?: {
|
|
22
22
|
columnId: string;
|
|
23
|
-
type: "string" | "number" | "boolean" | "date" | "enum";
|
|
24
|
-
method: "
|
|
23
|
+
type: "string" | "number" | "boolean" | "date" | "enum" | "jsonArray";
|
|
24
|
+
method: "intersect" | "contains" | "starts_with" | "ends_with" | "equals" | "greater_than" | "less_than" | "on" | "between" | "before" | "after" | "oneOf" | "isEmpty" | "isNotEmpty" | "is_null" | "is_not_null";
|
|
25
25
|
value: string | number | boolean | string[];
|
|
26
26
|
valueTo?: string | undefined;
|
|
27
27
|
endColumnId?: string | undefined;
|
|
@@ -54,8 +54,8 @@ declare function createTagTRPC({
|
|
|
54
54
|
resourceType: string;
|
|
55
55
|
resourceIds?: {
|
|
56
56
|
columnId: string;
|
|
57
|
-
type: "string" | "number" | "boolean" | "date" | "enum";
|
|
58
|
-
method: "
|
|
57
|
+
type: "string" | "number" | "boolean" | "date" | "enum" | "jsonArray";
|
|
58
|
+
method: "intersect" | "contains" | "starts_with" | "ends_with" | "equals" | "greater_than" | "less_than" | "on" | "between" | "before" | "after" | "oneOf" | "isEmpty" | "isNotEmpty" | "is_null" | "is_not_null";
|
|
59
59
|
value: string | number | boolean | string[];
|
|
60
60
|
valueTo?: string | undefined;
|
|
61
61
|
endColumnId?: string | undefined;
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
const require_src_modules_utils_getGlobalSearchCondition = require("./getGlobalSearchCondition.cjs");
|
|
3
4
|
let drizzle_orm = require("drizzle-orm");
|
|
4
5
|
let luxon = require("luxon");
|
|
5
6
|
//#region src/modules/utils/getConditionsFromFilters.ts
|
|
7
|
+
function getJsonArrayLikeCondition(column, value) {
|
|
8
|
+
return drizzle_orm.sql`${column} LIKE ${`%${require_src_modules_utils_getGlobalSearchCondition.escapeLikeUserInput(JSON.stringify(value))}%`} ESCAPE '\\'`;
|
|
9
|
+
}
|
|
6
10
|
const getUTCDateBoundaries = (isoString) => {
|
|
7
11
|
const dateTime = luxon.DateTime.fromISO(isoString, { zone: "utc" });
|
|
8
12
|
return {
|
|
@@ -22,6 +26,10 @@ const getConditionsFromFilters = (conditions, filters, table) => {
|
|
|
22
26
|
if (method === "isEmpty") conditions.push((0, drizzle_orm.or)((0, drizzle_orm.isNull)(column), (0, drizzle_orm.eq)(column, "")));
|
|
23
27
|
else conditions.push((0, drizzle_orm.and)((0, drizzle_orm.isNotNull)(column), (0, drizzle_orm.ne)(column, "")));
|
|
24
28
|
continue;
|
|
29
|
+
case "jsonArray":
|
|
30
|
+
if (method === "isEmpty") conditions.push((0, drizzle_orm.or)((0, drizzle_orm.isNull)(column), (0, drizzle_orm.eq)(column, ""), (0, drizzle_orm.eq)(column, "[]")));
|
|
31
|
+
else conditions.push((0, drizzle_orm.and)((0, drizzle_orm.isNotNull)(column), (0, drizzle_orm.ne)(column, ""), (0, drizzle_orm.ne)(column, "[]")));
|
|
32
|
+
continue;
|
|
25
33
|
case "number":
|
|
26
34
|
if (method === "isEmpty") conditions.push((0, drizzle_orm.or)((0, drizzle_orm.isNull)(column), (0, drizzle_orm.eq)(column, 0)));
|
|
27
35
|
else conditions.push((0, drizzle_orm.and)((0, drizzle_orm.isNotNull)(column), (0, drizzle_orm.ne)(column, 0)));
|
|
@@ -142,6 +150,30 @@ const getConditionsFromFilters = (conditions, filters, table) => {
|
|
|
142
150
|
break;
|
|
143
151
|
}
|
|
144
152
|
break;
|
|
153
|
+
case "jsonArray":
|
|
154
|
+
switch (method) {
|
|
155
|
+
case "oneOf":
|
|
156
|
+
if (Array.isArray(value) && value.length > 0) {
|
|
157
|
+
const clauses = value.filter((v) => typeof v === "string" && v.length > 0).map((v) => getJsonArrayLikeCondition(column, v));
|
|
158
|
+
if (clauses.length === 1) conditions.push(clauses[0]);
|
|
159
|
+
else if (clauses.length > 1) conditions.push((0, drizzle_orm.or)(...clauses));
|
|
160
|
+
}
|
|
161
|
+
break;
|
|
162
|
+
case "equals":
|
|
163
|
+
if (Array.isArray(value) && value.length > 0) {
|
|
164
|
+
const clauses = value.filter((v) => typeof v === "string" && v.length > 0).map((v) => getJsonArrayLikeCondition(column, v));
|
|
165
|
+
if (clauses.length === 1) conditions.push(clauses[0]);
|
|
166
|
+
else if (clauses.length > 1) conditions.push((0, drizzle_orm.and)(...clauses));
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
case "is_null":
|
|
170
|
+
conditions.push((0, drizzle_orm.isNull)(column));
|
|
171
|
+
break;
|
|
172
|
+
case "is_not_null":
|
|
173
|
+
conditions.push((0, drizzle_orm.isNotNull)(column));
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
145
177
|
}
|
|
146
178
|
}
|
|
147
179
|
return conditions;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getConditionsFromFilters.cjs","names":["DateTime"],"sources":["../../../../src/modules/utils/getConditionsFromFilters.ts"],"sourcesContent":["import type { QueryFilters } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport { and, between, eq, gte, inArray, isNotNull, isNull, like, lte, ne, or } from \"drizzle-orm\";\r\nimport type { SQLiteTableWithColumns } from \"drizzle-orm/sqlite-core\";\r\nimport { DateTime } from \"luxon\";\r\nimport type { ConditionBuilder } from \"../base/base.repository\";\r\n\r\ntype ColumnDataType = \"string\" | \"number\" | \"date\" | \"boolean\" | \"enum\";\r\n\r\n// Helper: Create UTC date boundaries from ISO string\r\nconst getUTCDateBoundaries = (isoString: string) => {\r\n const dateTime = DateTime.fromISO(isoString, { zone: \"utc\" });\r\n return {\r\n start: dateTime.startOf(\"day\").toJSDate(),\r\n end: dateTime.endOf(\"day\").toJSDate(),\r\n };\r\n};\r\n\r\nexport const getConditionsFromFilters = <T extends SQLiteTableWithColumns<any>>(\r\n conditions: ConditionBuilder,\r\n filters: QueryFilters | undefined,\r\n table: T\r\n): ConditionBuilder => {\r\n if (!filters || filters.length === 0) {\r\n return conditions;\r\n }\r\n\r\n // Process each filter (maximum one filter per column)\r\n for (const filter of filters) {\r\n const { columnId, type, method, value, valueTo } = filter;\r\n\r\n // Get the column from the table using columnId\r\n const column = (table as any)[columnId];\r\n if (!column) {\r\n continue; // Skip if column doesn't exist\r\n }\r\n\r\n // Handle isEmpty/isNotEmpty methods (work across types, ignore value)\r\n if (method === \"isEmpty\" || method === \"isNotEmpty\") {\r\n switch (type as ColumnDataType) {\r\n case \"string\":\r\n case \"enum\":\r\n // isEmpty: IS NULL OR = ''\r\n // isNotEmpty: IS NOT NULL AND != ''\r\n if (method === \"isEmpty\") {\r\n conditions.push(or(isNull(column), eq(column, \"\")));\r\n } else {\r\n conditions.push(and(isNotNull(column), ne(column, \"\")));\r\n }\r\n continue;\r\n case \"number\":\r\n // isEmpty: IS NULL OR = 0\r\n // isNotEmpty: IS NOT NULL AND != 0\r\n if (method === \"isEmpty\") {\r\n conditions.push(or(isNull(column), eq(column, 0)));\r\n } else {\r\n conditions.push(and(isNotNull(column), ne(column, 0)));\r\n }\r\n continue;\r\n case \"boolean\":\r\n // Should not happen per plan, but handle gracefully\r\n continue;\r\n default:\r\n continue;\r\n }\r\n }\r\n\r\n // Apply filter based on type and method\r\n switch (type as ColumnDataType) {\r\n case \"string\":\r\n switch (method) {\r\n case \"contains\":\r\n if (typeof value === \"string\") {\r\n conditions.push(like(column, `%${value}%`));\r\n }\r\n break;\r\n case \"equals\":\r\n if (typeof value === \"string\") {\r\n conditions.push(eq(column, value));\r\n }\r\n break;\r\n case \"starts_with\":\r\n if (typeof value === \"string\") {\r\n conditions.push(like(column, `${value}%`));\r\n }\r\n break;\r\n case \"ends_with\":\r\n if (typeof value === \"string\") {\r\n conditions.push(like(column, `%${value}`));\r\n }\r\n break;\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n\r\n case \"number\":\r\n switch (method) {\r\n case \"equals\":\r\n if (typeof value === \"number\") {\r\n conditions.push(eq(column, value));\r\n }\r\n break;\r\n case \"greater_than\":\r\n if (typeof value === \"number\") {\r\n conditions.push(gte(column, value));\r\n }\r\n break;\r\n case \"less_than\":\r\n if (typeof value === \"number\") {\r\n conditions.push(lte(column, value));\r\n }\r\n break;\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n\r\n case \"date\":\r\n if (typeof value !== \"string\") break;\r\n\r\n switch (method) {\r\n case \"on\": {\r\n const { start, end } = getUTCDateBoundaries(value);\r\n conditions.push(and(gte(column, start), lte(column, end)));\r\n break;\r\n }\r\n case \"between\":\r\n if (valueTo) {\r\n const { start } = getUTCDateBoundaries(value);\r\n const { end } = getUTCDateBoundaries(valueTo);\r\n conditions.push(between(column, start, end));\r\n }\r\n break;\r\n case \"before\": {\r\n const { end } = getUTCDateBoundaries(value);\r\n conditions.push(lte(column, end));\r\n break;\r\n }\r\n case \"after\": {\r\n const { start } = getUTCDateBoundaries(value);\r\n conditions.push(gte(column, start));\r\n break;\r\n }\r\n case \"intersect\": {\r\n // Interval overlap: [columnId, endColumnId] intersects with [value, valueTo]\r\n // Logic: columnId <= valueTo AND (endColumnId IS NULL OR endColumnId >= value)\r\n if (!valueTo || !filter.endColumnId) break;\r\n\r\n const endColumn = (table as any)[filter.endColumnId];\r\n if (!endColumn) break;\r\n\r\n const { start } = getUTCDateBoundaries(value);\r\n const { end } = getUTCDateBoundaries(valueTo);\r\n\r\n conditions.push(and(lte(column, end), or(isNull(endColumn), gte(endColumn, start))));\r\n break;\r\n }\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n\r\n case \"boolean\":\r\n switch (method) {\r\n case \"equals\":\r\n if (typeof value === \"boolean\") {\r\n conditions.push(eq(column, value));\r\n }\r\n break;\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n\r\n break;\r\n\r\n case \"enum\":\r\n switch (method) {\r\n case \"oneOf\":\r\n if (Array.isArray(value) && value.length > 0) {\r\n conditions.push(inArray(column, value));\r\n }\r\n break;\r\n case \"equals\":\r\n if (typeof value === \"string\") {\r\n conditions.push(eq(column, value));\r\n }\r\n break;\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n }\r\n }\r\n\r\n return conditions;\r\n};\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"getConditionsFromFilters.cjs","names":["escapeLikeUserInput","DateTime"],"sources":["../../../../src/modules/utils/getConditionsFromFilters.ts"],"sourcesContent":["import type { QueryFilters } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport {\r\n and,\r\n between,\r\n eq,\r\n gte,\r\n inArray,\r\n isNotNull,\r\n isNull,\r\n like,\r\n lte,\r\n ne,\r\n or,\r\n sql,\r\n} from \"drizzle-orm\";\r\nimport type { SQLiteColumn, SQLiteTableWithColumns } from \"drizzle-orm/sqlite-core\";\r\nimport { DateTime } from \"luxon\";\r\nimport type { ConditionBuilder } from \"../base/base.repository\";\r\nimport { escapeLikeUserInput } from \"./getGlobalSearchCondition\";\r\n\r\ntype ColumnDataType = \"string\" | \"number\" | \"date\" | \"boolean\" | \"enum\" | \"jsonArray\";\r\n\r\nfunction getJsonArrayLikeCondition(\r\n column: SQLiteColumn,\r\n value: string\r\n): ReturnType<typeof sql> {\r\n // We store JSON arrays as TEXT (e.g. [\"a\",\"b\"]). To avoid partial token matches,\r\n // search for the JSON-stringified element, including quotes/escapes.\r\n const needle = JSON.stringify(value);\r\n const pattern = `%${escapeLikeUserInput(needle)}%`;\r\n return sql`${column} LIKE ${pattern} ESCAPE '\\\\'`;\r\n}\r\n\r\n// Helper: Create UTC date boundaries from ISO string\r\nconst getUTCDateBoundaries = (isoString: string) => {\r\n const dateTime = DateTime.fromISO(isoString, { zone: \"utc\" });\r\n return {\r\n start: dateTime.startOf(\"day\").toJSDate(),\r\n end: dateTime.endOf(\"day\").toJSDate(),\r\n };\r\n};\r\n\r\n// biome-ignore lint/suspicious/noExplicitAny: Drizzle TableConfig is complex; we access columns dynamically by `columnId`.\r\nexport const getConditionsFromFilters = <T extends SQLiteTableWithColumns<any>>(\r\n conditions: ConditionBuilder,\r\n filters: QueryFilters | undefined,\r\n table: T\r\n): ConditionBuilder => {\r\n if (!filters || filters.length === 0) {\r\n return conditions;\r\n }\r\n\r\n // Process each filter (maximum one filter per column)\r\n for (const filter of filters) {\r\n const { columnId, type, method, value, valueTo } = filter;\r\n\r\n // Get the column from the table using columnId\r\n const column = (table as unknown as Record<string, SQLiteColumn>)[columnId];\r\n if (!column) {\r\n continue; // Skip if column doesn't exist\r\n }\r\n\r\n // Handle isEmpty/isNotEmpty methods (work across types, ignore value)\r\n if (method === \"isEmpty\" || method === \"isNotEmpty\") {\r\n switch (type as ColumnDataType) {\r\n case \"string\":\r\n case \"enum\":\r\n // isEmpty: IS NULL OR = ''\r\n // isNotEmpty: IS NOT NULL AND != ''\r\n if (method === \"isEmpty\") {\r\n conditions.push(or(isNull(column), eq(column, \"\")));\r\n } else {\r\n conditions.push(and(isNotNull(column), ne(column, \"\")));\r\n }\r\n continue;\r\n case \"jsonArray\":\r\n // isEmpty: IS NULL OR = '' OR = '[]'\r\n // isNotEmpty: IS NOT NULL AND != '' AND != '[]'\r\n if (method === \"isEmpty\") {\r\n conditions.push(or(isNull(column), eq(column, \"\"), eq(column, \"[]\")));\r\n } else {\r\n conditions.push(and(isNotNull(column), ne(column, \"\"), ne(column, \"[]\")));\r\n }\r\n continue;\r\n case \"number\":\r\n // isEmpty: IS NULL OR = 0\r\n // isNotEmpty: IS NOT NULL AND != 0\r\n if (method === \"isEmpty\") {\r\n conditions.push(or(isNull(column), eq(column, 0)));\r\n } else {\r\n conditions.push(and(isNotNull(column), ne(column, 0)));\r\n }\r\n continue;\r\n case \"boolean\":\r\n // Should not happen per plan, but handle gracefully\r\n continue;\r\n default:\r\n continue;\r\n }\r\n }\r\n\r\n // Apply filter based on type and method\r\n switch (type as ColumnDataType) {\r\n case \"string\":\r\n switch (method) {\r\n case \"contains\":\r\n if (typeof value === \"string\") {\r\n conditions.push(like(column, `%${value}%`));\r\n }\r\n break;\r\n case \"equals\":\r\n if (typeof value === \"string\") {\r\n conditions.push(eq(column, value));\r\n }\r\n break;\r\n case \"starts_with\":\r\n if (typeof value === \"string\") {\r\n conditions.push(like(column, `${value}%`));\r\n }\r\n break;\r\n case \"ends_with\":\r\n if (typeof value === \"string\") {\r\n conditions.push(like(column, `%${value}`));\r\n }\r\n break;\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n\r\n case \"number\":\r\n switch (method) {\r\n case \"equals\":\r\n if (typeof value === \"number\") {\r\n conditions.push(eq(column, value));\r\n }\r\n break;\r\n case \"greater_than\":\r\n if (typeof value === \"number\") {\r\n conditions.push(gte(column, value));\r\n }\r\n break;\r\n case \"less_than\":\r\n if (typeof value === \"number\") {\r\n conditions.push(lte(column, value));\r\n }\r\n break;\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n\r\n case \"date\":\r\n if (typeof value !== \"string\") break;\r\n\r\n switch (method) {\r\n case \"on\": {\r\n const { start, end } = getUTCDateBoundaries(value);\r\n conditions.push(and(gte(column, start), lte(column, end)));\r\n break;\r\n }\r\n case \"between\":\r\n if (valueTo) {\r\n const { start } = getUTCDateBoundaries(value);\r\n const { end } = getUTCDateBoundaries(valueTo);\r\n conditions.push(between(column, start, end));\r\n }\r\n break;\r\n case \"before\": {\r\n const { end } = getUTCDateBoundaries(value);\r\n conditions.push(lte(column, end));\r\n break;\r\n }\r\n case \"after\": {\r\n const { start } = getUTCDateBoundaries(value);\r\n conditions.push(gte(column, start));\r\n break;\r\n }\r\n case \"intersect\": {\r\n // Interval overlap: [columnId, endColumnId] intersects with [value, valueTo]\r\n // Logic: columnId <= valueTo AND (endColumnId IS NULL OR endColumnId >= value)\r\n if (!valueTo || !filter.endColumnId) break;\r\n\r\n const endColumn = (table as unknown as Record<string, SQLiteColumn>)[filter.endColumnId];\r\n if (!endColumn) break;\r\n\r\n const { start } = getUTCDateBoundaries(value);\r\n const { end } = getUTCDateBoundaries(valueTo);\r\n\r\n conditions.push(and(lte(column, end), or(isNull(endColumn), gte(endColumn, start))));\r\n break;\r\n }\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n\r\n case \"boolean\":\r\n switch (method) {\r\n case \"equals\":\r\n if (typeof value === \"boolean\") {\r\n conditions.push(eq(column, value));\r\n }\r\n break;\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n\r\n break;\r\n\r\n case \"enum\":\r\n switch (method) {\r\n case \"oneOf\":\r\n if (Array.isArray(value) && value.length > 0) {\r\n conditions.push(inArray(column, value));\r\n }\r\n break;\r\n case \"equals\":\r\n if (typeof value === \"string\") {\r\n conditions.push(eq(column, value));\r\n }\r\n break;\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n\r\n case \"jsonArray\":\r\n switch (method) {\r\n case \"oneOf\": {\r\n if (Array.isArray(value) && value.length > 0) {\r\n const clauses = value\r\n .filter((v): v is string => typeof v === \"string\" && v.length > 0)\r\n .map((v) => getJsonArrayLikeCondition(column, v));\r\n\r\n if (clauses.length === 1) {\r\n conditions.push(clauses[0]);\r\n } else if (clauses.length > 1) {\r\n conditions.push(or(...clauses));\r\n }\r\n }\r\n break;\r\n }\r\n case \"equals\": {\r\n if (Array.isArray(value) && value.length > 0) {\r\n const clauses = value\r\n .filter((v): v is string => typeof v === \"string\" && v.length > 0)\r\n .map((v) => getJsonArrayLikeCondition(column, v));\r\n\r\n if (clauses.length === 1) {\r\n conditions.push(clauses[0]);\r\n } else if (clauses.length > 1) {\r\n conditions.push(and(...clauses));\r\n }\r\n }\r\n break;\r\n }\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n }\r\n }\r\n\r\n return conditions;\r\n};\r\n"],"mappings":"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"}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { escapeLikeUserInput } from "./getGlobalSearchCondition.mjs";
|
|
2
|
+
import { and, between, eq, gte, inArray, isNotNull, isNull, like, lte, ne, or, sql } from "drizzle-orm";
|
|
2
3
|
import { DateTime } from "luxon";
|
|
3
4
|
//#region src/modules/utils/getConditionsFromFilters.ts
|
|
5
|
+
function getJsonArrayLikeCondition(column, value) {
|
|
6
|
+
return sql`${column} LIKE ${`%${escapeLikeUserInput(JSON.stringify(value))}%`} ESCAPE '\\'`;
|
|
7
|
+
}
|
|
4
8
|
const getUTCDateBoundaries = (isoString) => {
|
|
5
9
|
const dateTime = DateTime.fromISO(isoString, { zone: "utc" });
|
|
6
10
|
return {
|
|
@@ -20,6 +24,10 @@ const getConditionsFromFilters = (conditions, filters, table) => {
|
|
|
20
24
|
if (method === "isEmpty") conditions.push(or(isNull(column), eq(column, "")));
|
|
21
25
|
else conditions.push(and(isNotNull(column), ne(column, "")));
|
|
22
26
|
continue;
|
|
27
|
+
case "jsonArray":
|
|
28
|
+
if (method === "isEmpty") conditions.push(or(isNull(column), eq(column, ""), eq(column, "[]")));
|
|
29
|
+
else conditions.push(and(isNotNull(column), ne(column, ""), ne(column, "[]")));
|
|
30
|
+
continue;
|
|
23
31
|
case "number":
|
|
24
32
|
if (method === "isEmpty") conditions.push(or(isNull(column), eq(column, 0)));
|
|
25
33
|
else conditions.push(and(isNotNull(column), ne(column, 0)));
|
|
@@ -140,6 +148,30 @@ const getConditionsFromFilters = (conditions, filters, table) => {
|
|
|
140
148
|
break;
|
|
141
149
|
}
|
|
142
150
|
break;
|
|
151
|
+
case "jsonArray":
|
|
152
|
+
switch (method) {
|
|
153
|
+
case "oneOf":
|
|
154
|
+
if (Array.isArray(value) && value.length > 0) {
|
|
155
|
+
const clauses = value.filter((v) => typeof v === "string" && v.length > 0).map((v) => getJsonArrayLikeCondition(column, v));
|
|
156
|
+
if (clauses.length === 1) conditions.push(clauses[0]);
|
|
157
|
+
else if (clauses.length > 1) conditions.push(or(...clauses));
|
|
158
|
+
}
|
|
159
|
+
break;
|
|
160
|
+
case "equals":
|
|
161
|
+
if (Array.isArray(value) && value.length > 0) {
|
|
162
|
+
const clauses = value.filter((v) => typeof v === "string" && v.length > 0).map((v) => getJsonArrayLikeCondition(column, v));
|
|
163
|
+
if (clauses.length === 1) conditions.push(clauses[0]);
|
|
164
|
+
else if (clauses.length > 1) conditions.push(and(...clauses));
|
|
165
|
+
}
|
|
166
|
+
break;
|
|
167
|
+
case "is_null":
|
|
168
|
+
conditions.push(isNull(column));
|
|
169
|
+
break;
|
|
170
|
+
case "is_not_null":
|
|
171
|
+
conditions.push(isNotNull(column));
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
break;
|
|
143
175
|
}
|
|
144
176
|
}
|
|
145
177
|
return conditions;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getConditionsFromFilters.mjs","names":[],"sources":["../../../../src/modules/utils/getConditionsFromFilters.ts"],"sourcesContent":["import type { QueryFilters } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport { and, between, eq, gte, inArray, isNotNull, isNull, like, lte, ne, or } from \"drizzle-orm\";\r\nimport type { SQLiteTableWithColumns } from \"drizzle-orm/sqlite-core\";\r\nimport { DateTime } from \"luxon\";\r\nimport type { ConditionBuilder } from \"../base/base.repository\";\r\n\r\ntype ColumnDataType = \"string\" | \"number\" | \"date\" | \"boolean\" | \"enum\";\r\n\r\n// Helper: Create UTC date boundaries from ISO string\r\nconst getUTCDateBoundaries = (isoString: string) => {\r\n const dateTime = DateTime.fromISO(isoString, { zone: \"utc\" });\r\n return {\r\n start: dateTime.startOf(\"day\").toJSDate(),\r\n end: dateTime.endOf(\"day\").toJSDate(),\r\n };\r\n};\r\n\r\nexport const getConditionsFromFilters = <T extends SQLiteTableWithColumns<any>>(\r\n conditions: ConditionBuilder,\r\n filters: QueryFilters | undefined,\r\n table: T\r\n): ConditionBuilder => {\r\n if (!filters || filters.length === 0) {\r\n return conditions;\r\n }\r\n\r\n // Process each filter (maximum one filter per column)\r\n for (const filter of filters) {\r\n const { columnId, type, method, value, valueTo } = filter;\r\n\r\n // Get the column from the table using columnId\r\n const column = (table as any)[columnId];\r\n if (!column) {\r\n continue; // Skip if column doesn't exist\r\n }\r\n\r\n // Handle isEmpty/isNotEmpty methods (work across types, ignore value)\r\n if (method === \"isEmpty\" || method === \"isNotEmpty\") {\r\n switch (type as ColumnDataType) {\r\n case \"string\":\r\n case \"enum\":\r\n // isEmpty: IS NULL OR = ''\r\n // isNotEmpty: IS NOT NULL AND != ''\r\n if (method === \"isEmpty\") {\r\n conditions.push(or(isNull(column), eq(column, \"\")));\r\n } else {\r\n conditions.push(and(isNotNull(column), ne(column, \"\")));\r\n }\r\n continue;\r\n case \"number\":\r\n // isEmpty: IS NULL OR = 0\r\n // isNotEmpty: IS NOT NULL AND != 0\r\n if (method === \"isEmpty\") {\r\n conditions.push(or(isNull(column), eq(column, 0)));\r\n } else {\r\n conditions.push(and(isNotNull(column), ne(column, 0)));\r\n }\r\n continue;\r\n case \"boolean\":\r\n // Should not happen per plan, but handle gracefully\r\n continue;\r\n default:\r\n continue;\r\n }\r\n }\r\n\r\n // Apply filter based on type and method\r\n switch (type as ColumnDataType) {\r\n case \"string\":\r\n switch (method) {\r\n case \"contains\":\r\n if (typeof value === \"string\") {\r\n conditions.push(like(column, `%${value}%`));\r\n }\r\n break;\r\n case \"equals\":\r\n if (typeof value === \"string\") {\r\n conditions.push(eq(column, value));\r\n }\r\n break;\r\n case \"starts_with\":\r\n if (typeof value === \"string\") {\r\n conditions.push(like(column, `${value}%`));\r\n }\r\n break;\r\n case \"ends_with\":\r\n if (typeof value === \"string\") {\r\n conditions.push(like(column, `%${value}`));\r\n }\r\n break;\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n\r\n case \"number\":\r\n switch (method) {\r\n case \"equals\":\r\n if (typeof value === \"number\") {\r\n conditions.push(eq(column, value));\r\n }\r\n break;\r\n case \"greater_than\":\r\n if (typeof value === \"number\") {\r\n conditions.push(gte(column, value));\r\n }\r\n break;\r\n case \"less_than\":\r\n if (typeof value === \"number\") {\r\n conditions.push(lte(column, value));\r\n }\r\n break;\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n\r\n case \"date\":\r\n if (typeof value !== \"string\") break;\r\n\r\n switch (method) {\r\n case \"on\": {\r\n const { start, end } = getUTCDateBoundaries(value);\r\n conditions.push(and(gte(column, start), lte(column, end)));\r\n break;\r\n }\r\n case \"between\":\r\n if (valueTo) {\r\n const { start } = getUTCDateBoundaries(value);\r\n const { end } = getUTCDateBoundaries(valueTo);\r\n conditions.push(between(column, start, end));\r\n }\r\n break;\r\n case \"before\": {\r\n const { end } = getUTCDateBoundaries(value);\r\n conditions.push(lte(column, end));\r\n break;\r\n }\r\n case \"after\": {\r\n const { start } = getUTCDateBoundaries(value);\r\n conditions.push(gte(column, start));\r\n break;\r\n }\r\n case \"intersect\": {\r\n // Interval overlap: [columnId, endColumnId] intersects with [value, valueTo]\r\n // Logic: columnId <= valueTo AND (endColumnId IS NULL OR endColumnId >= value)\r\n if (!valueTo || !filter.endColumnId) break;\r\n\r\n const endColumn = (table as any)[filter.endColumnId];\r\n if (!endColumn) break;\r\n\r\n const { start } = getUTCDateBoundaries(value);\r\n const { end } = getUTCDateBoundaries(valueTo);\r\n\r\n conditions.push(and(lte(column, end), or(isNull(endColumn), gte(endColumn, start))));\r\n break;\r\n }\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n\r\n case \"boolean\":\r\n switch (method) {\r\n case \"equals\":\r\n if (typeof value === \"boolean\") {\r\n conditions.push(eq(column, value));\r\n }\r\n break;\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n\r\n break;\r\n\r\n case \"enum\":\r\n switch (method) {\r\n case \"oneOf\":\r\n if (Array.isArray(value) && value.length > 0) {\r\n conditions.push(inArray(column, value));\r\n }\r\n break;\r\n case \"equals\":\r\n if (typeof value === \"string\") {\r\n conditions.push(eq(column, value));\r\n }\r\n break;\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n }\r\n }\r\n\r\n return conditions;\r\n};\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"getConditionsFromFilters.mjs","names":[],"sources":["../../../../src/modules/utils/getConditionsFromFilters.ts"],"sourcesContent":["import type { QueryFilters } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport {\r\n and,\r\n between,\r\n eq,\r\n gte,\r\n inArray,\r\n isNotNull,\r\n isNull,\r\n like,\r\n lte,\r\n ne,\r\n or,\r\n sql,\r\n} from \"drizzle-orm\";\r\nimport type { SQLiteColumn, SQLiteTableWithColumns } from \"drizzle-orm/sqlite-core\";\r\nimport { DateTime } from \"luxon\";\r\nimport type { ConditionBuilder } from \"../base/base.repository\";\r\nimport { escapeLikeUserInput } from \"./getGlobalSearchCondition\";\r\n\r\ntype ColumnDataType = \"string\" | \"number\" | \"date\" | \"boolean\" | \"enum\" | \"jsonArray\";\r\n\r\nfunction getJsonArrayLikeCondition(\r\n column: SQLiteColumn,\r\n value: string\r\n): ReturnType<typeof sql> {\r\n // We store JSON arrays as TEXT (e.g. [\"a\",\"b\"]). To avoid partial token matches,\r\n // search for the JSON-stringified element, including quotes/escapes.\r\n const needle = JSON.stringify(value);\r\n const pattern = `%${escapeLikeUserInput(needle)}%`;\r\n return sql`${column} LIKE ${pattern} ESCAPE '\\\\'`;\r\n}\r\n\r\n// Helper: Create UTC date boundaries from ISO string\r\nconst getUTCDateBoundaries = (isoString: string) => {\r\n const dateTime = DateTime.fromISO(isoString, { zone: \"utc\" });\r\n return {\r\n start: dateTime.startOf(\"day\").toJSDate(),\r\n end: dateTime.endOf(\"day\").toJSDate(),\r\n };\r\n};\r\n\r\n// biome-ignore lint/suspicious/noExplicitAny: Drizzle TableConfig is complex; we access columns dynamically by `columnId`.\r\nexport const getConditionsFromFilters = <T extends SQLiteTableWithColumns<any>>(\r\n conditions: ConditionBuilder,\r\n filters: QueryFilters | undefined,\r\n table: T\r\n): ConditionBuilder => {\r\n if (!filters || filters.length === 0) {\r\n return conditions;\r\n }\r\n\r\n // Process each filter (maximum one filter per column)\r\n for (const filter of filters) {\r\n const { columnId, type, method, value, valueTo } = filter;\r\n\r\n // Get the column from the table using columnId\r\n const column = (table as unknown as Record<string, SQLiteColumn>)[columnId];\r\n if (!column) {\r\n continue; // Skip if column doesn't exist\r\n }\r\n\r\n // Handle isEmpty/isNotEmpty methods (work across types, ignore value)\r\n if (method === \"isEmpty\" || method === \"isNotEmpty\") {\r\n switch (type as ColumnDataType) {\r\n case \"string\":\r\n case \"enum\":\r\n // isEmpty: IS NULL OR = ''\r\n // isNotEmpty: IS NOT NULL AND != ''\r\n if (method === \"isEmpty\") {\r\n conditions.push(or(isNull(column), eq(column, \"\")));\r\n } else {\r\n conditions.push(and(isNotNull(column), ne(column, \"\")));\r\n }\r\n continue;\r\n case \"jsonArray\":\r\n // isEmpty: IS NULL OR = '' OR = '[]'\r\n // isNotEmpty: IS NOT NULL AND != '' AND != '[]'\r\n if (method === \"isEmpty\") {\r\n conditions.push(or(isNull(column), eq(column, \"\"), eq(column, \"[]\")));\r\n } else {\r\n conditions.push(and(isNotNull(column), ne(column, \"\"), ne(column, \"[]\")));\r\n }\r\n continue;\r\n case \"number\":\r\n // isEmpty: IS NULL OR = 0\r\n // isNotEmpty: IS NOT NULL AND != 0\r\n if (method === \"isEmpty\") {\r\n conditions.push(or(isNull(column), eq(column, 0)));\r\n } else {\r\n conditions.push(and(isNotNull(column), ne(column, 0)));\r\n }\r\n continue;\r\n case \"boolean\":\r\n // Should not happen per plan, but handle gracefully\r\n continue;\r\n default:\r\n continue;\r\n }\r\n }\r\n\r\n // Apply filter based on type and method\r\n switch (type as ColumnDataType) {\r\n case \"string\":\r\n switch (method) {\r\n case \"contains\":\r\n if (typeof value === \"string\") {\r\n conditions.push(like(column, `%${value}%`));\r\n }\r\n break;\r\n case \"equals\":\r\n if (typeof value === \"string\") {\r\n conditions.push(eq(column, value));\r\n }\r\n break;\r\n case \"starts_with\":\r\n if (typeof value === \"string\") {\r\n conditions.push(like(column, `${value}%`));\r\n }\r\n break;\r\n case \"ends_with\":\r\n if (typeof value === \"string\") {\r\n conditions.push(like(column, `%${value}`));\r\n }\r\n break;\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n\r\n case \"number\":\r\n switch (method) {\r\n case \"equals\":\r\n if (typeof value === \"number\") {\r\n conditions.push(eq(column, value));\r\n }\r\n break;\r\n case \"greater_than\":\r\n if (typeof value === \"number\") {\r\n conditions.push(gte(column, value));\r\n }\r\n break;\r\n case \"less_than\":\r\n if (typeof value === \"number\") {\r\n conditions.push(lte(column, value));\r\n }\r\n break;\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n\r\n case \"date\":\r\n if (typeof value !== \"string\") break;\r\n\r\n switch (method) {\r\n case \"on\": {\r\n const { start, end } = getUTCDateBoundaries(value);\r\n conditions.push(and(gte(column, start), lte(column, end)));\r\n break;\r\n }\r\n case \"between\":\r\n if (valueTo) {\r\n const { start } = getUTCDateBoundaries(value);\r\n const { end } = getUTCDateBoundaries(valueTo);\r\n conditions.push(between(column, start, end));\r\n }\r\n break;\r\n case \"before\": {\r\n const { end } = getUTCDateBoundaries(value);\r\n conditions.push(lte(column, end));\r\n break;\r\n }\r\n case \"after\": {\r\n const { start } = getUTCDateBoundaries(value);\r\n conditions.push(gte(column, start));\r\n break;\r\n }\r\n case \"intersect\": {\r\n // Interval overlap: [columnId, endColumnId] intersects with [value, valueTo]\r\n // Logic: columnId <= valueTo AND (endColumnId IS NULL OR endColumnId >= value)\r\n if (!valueTo || !filter.endColumnId) break;\r\n\r\n const endColumn = (table as unknown as Record<string, SQLiteColumn>)[filter.endColumnId];\r\n if (!endColumn) break;\r\n\r\n const { start } = getUTCDateBoundaries(value);\r\n const { end } = getUTCDateBoundaries(valueTo);\r\n\r\n conditions.push(and(lte(column, end), or(isNull(endColumn), gte(endColumn, start))));\r\n break;\r\n }\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n\r\n case \"boolean\":\r\n switch (method) {\r\n case \"equals\":\r\n if (typeof value === \"boolean\") {\r\n conditions.push(eq(column, value));\r\n }\r\n break;\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n\r\n break;\r\n\r\n case \"enum\":\r\n switch (method) {\r\n case \"oneOf\":\r\n if (Array.isArray(value) && value.length > 0) {\r\n conditions.push(inArray(column, value));\r\n }\r\n break;\r\n case \"equals\":\r\n if (typeof value === \"string\") {\r\n conditions.push(eq(column, value));\r\n }\r\n break;\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n\r\n case \"jsonArray\":\r\n switch (method) {\r\n case \"oneOf\": {\r\n if (Array.isArray(value) && value.length > 0) {\r\n const clauses = value\r\n .filter((v): v is string => typeof v === \"string\" && v.length > 0)\r\n .map((v) => getJsonArrayLikeCondition(column, v));\r\n\r\n if (clauses.length === 1) {\r\n conditions.push(clauses[0]);\r\n } else if (clauses.length > 1) {\r\n conditions.push(or(...clauses));\r\n }\r\n }\r\n break;\r\n }\r\n case \"equals\": {\r\n if (Array.isArray(value) && value.length > 0) {\r\n const clauses = value\r\n .filter((v): v is string => typeof v === \"string\" && v.length > 0)\r\n .map((v) => getJsonArrayLikeCondition(column, v));\r\n\r\n if (clauses.length === 1) {\r\n conditions.push(clauses[0]);\r\n } else if (clauses.length > 1) {\r\n conditions.push(and(...clauses));\r\n }\r\n }\r\n break;\r\n }\r\n case \"is_null\":\r\n conditions.push(isNull(column));\r\n break;\r\n case \"is_not_null\":\r\n conditions.push(isNotNull(column));\r\n break;\r\n }\r\n break;\r\n }\r\n }\r\n\r\n return conditions;\r\n};\r\n"],"mappings":";;;;AAsBA,SAAS,0BACP,QACA,OACwB;AAKxB,QAAO,GAAG,GAAG,OAAO,QADJ,IAAI,oBADL,KAAK,UAAU,MAAM,CACW,CAAC,GACZ;;AAItC,MAAM,wBAAwB,cAAsB;CAClD,MAAM,WAAW,SAAS,QAAQ,WAAW,EAAE,MAAM,OAAO,CAAC;AAC7D,QAAO;EACL,OAAO,SAAS,QAAQ,MAAM,CAAC,UAAU;EACzC,KAAK,SAAS,MAAM,MAAM,CAAC,UAAU;EACtC;;AAIH,MAAa,4BACX,YACA,SACA,UACqB;AACrB,KAAI,CAAC,WAAW,QAAQ,WAAW,EACjC,QAAO;AAIT,MAAK,MAAM,UAAU,SAAS;EAC5B,MAAM,EAAE,UAAU,MAAM,QAAQ,OAAO,YAAY;EAGnD,MAAM,SAAU,MAAkD;AAClE,MAAI,CAAC,OACH;AAIF,MAAI,WAAW,aAAa,WAAW,aACrC,SAAQ,MAAR;GACE,KAAK;GACL,KAAK;AAGH,QAAI,WAAW,UACb,YAAW,KAAK,GAAG,OAAO,OAAO,EAAE,GAAG,QAAQ,GAAG,CAAC,CAAC;QAEnD,YAAW,KAAK,IAAI,UAAU,OAAO,EAAE,GAAG,QAAQ,GAAG,CAAC,CAAC;AAEzD;GACF,KAAK;AAGH,QAAI,WAAW,UACb,YAAW,KAAK,GAAG,OAAO,OAAO,EAAE,GAAG,QAAQ,GAAG,EAAE,GAAG,QAAQ,KAAK,CAAC,CAAC;QAErE,YAAW,KAAK,IAAI,UAAU,OAAO,EAAE,GAAG,QAAQ,GAAG,EAAE,GAAG,QAAQ,KAAK,CAAC,CAAC;AAE3E;GACF,KAAK;AAGH,QAAI,WAAW,UACb,YAAW,KAAK,GAAG,OAAO,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC;QAElD,YAAW,KAAK,IAAI,UAAU,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC;AAExD;GACF,KAAK,UAEH;GACF,QACE;;AAKN,UAAQ,MAAR;GACE,KAAK;AACH,YAAQ,QAAR;KACE,KAAK;AACH,UAAI,OAAO,UAAU,SACnB,YAAW,KAAK,KAAK,QAAQ,IAAI,MAAM,GAAG,CAAC;AAE7C;KACF,KAAK;AACH,UAAI,OAAO,UAAU,SACnB,YAAW,KAAK,GAAG,QAAQ,MAAM,CAAC;AAEpC;KACF,KAAK;AACH,UAAI,OAAO,UAAU,SACnB,YAAW,KAAK,KAAK,QAAQ,GAAG,MAAM,GAAG,CAAC;AAE5C;KACF,KAAK;AACH,UAAI,OAAO,UAAU,SACnB,YAAW,KAAK,KAAK,QAAQ,IAAI,QAAQ,CAAC;AAE5C;KACF,KAAK;AACH,iBAAW,KAAK,OAAO,OAAO,CAAC;AAC/B;KACF,KAAK;AACH,iBAAW,KAAK,UAAU,OAAO,CAAC;AAClC;;AAEJ;GAEF,KAAK;AACH,YAAQ,QAAR;KACE,KAAK;AACH,UAAI,OAAO,UAAU,SACnB,YAAW,KAAK,GAAG,QAAQ,MAAM,CAAC;AAEpC;KACF,KAAK;AACH,UAAI,OAAO,UAAU,SACnB,YAAW,KAAK,IAAI,QAAQ,MAAM,CAAC;AAErC;KACF,KAAK;AACH,UAAI,OAAO,UAAU,SACnB,YAAW,KAAK,IAAI,QAAQ,MAAM,CAAC;AAErC;KACF,KAAK;AACH,iBAAW,KAAK,OAAO,OAAO,CAAC;AAC/B;KACF,KAAK;AACH,iBAAW,KAAK,UAAU,OAAO,CAAC;AAClC;;AAEJ;GAEF,KAAK;AACH,QAAI,OAAO,UAAU,SAAU;AAE/B,YAAQ,QAAR;KACE,KAAK,MAAM;MACT,MAAM,EAAE,OAAO,QAAQ,qBAAqB,MAAM;AAClD,iBAAW,KAAK,IAAI,IAAI,QAAQ,MAAM,EAAE,IAAI,QAAQ,IAAI,CAAC,CAAC;AAC1D;;KAEF,KAAK;AACH,UAAI,SAAS;OACX,MAAM,EAAE,UAAU,qBAAqB,MAAM;OAC7C,MAAM,EAAE,QAAQ,qBAAqB,QAAQ;AAC7C,kBAAW,KAAK,QAAQ,QAAQ,OAAO,IAAI,CAAC;;AAE9C;KACF,KAAK,UAAU;MACb,MAAM,EAAE,QAAQ,qBAAqB,MAAM;AAC3C,iBAAW,KAAK,IAAI,QAAQ,IAAI,CAAC;AACjC;;KAEF,KAAK,SAAS;MACZ,MAAM,EAAE,UAAU,qBAAqB,MAAM;AAC7C,iBAAW,KAAK,IAAI,QAAQ,MAAM,CAAC;AACnC;;KAEF,KAAK,aAAa;AAGhB,UAAI,CAAC,WAAW,CAAC,OAAO,YAAa;MAErC,MAAM,YAAa,MAAkD,OAAO;AAC5E,UAAI,CAAC,UAAW;MAEhB,MAAM,EAAE,UAAU,qBAAqB,MAAM;MAC7C,MAAM,EAAE,QAAQ,qBAAqB,QAAQ;AAE7C,iBAAW,KAAK,IAAI,IAAI,QAAQ,IAAI,EAAE,GAAG,OAAO,UAAU,EAAE,IAAI,WAAW,MAAM,CAAC,CAAC,CAAC;AACpF;;KAEF,KAAK;AACH,iBAAW,KAAK,OAAO,OAAO,CAAC;AAC/B;KACF,KAAK;AACH,iBAAW,KAAK,UAAU,OAAO,CAAC;AAClC;;AAEJ;GAEF,KAAK;AACH,YAAQ,QAAR;KACE,KAAK;AACH,UAAI,OAAO,UAAU,UACnB,YAAW,KAAK,GAAG,QAAQ,MAAM,CAAC;AAEpC;KACF,KAAK;AACH,iBAAW,KAAK,OAAO,OAAO,CAAC;AAC/B;KACF,KAAK;AACH,iBAAW,KAAK,UAAU,OAAO,CAAC;AAClC;;AAGJ;GAEF,KAAK;AACH,YAAQ,QAAR;KACE,KAAK;AACH,UAAI,MAAM,QAAQ,MAAM,IAAI,MAAM,SAAS,EACzC,YAAW,KAAK,QAAQ,QAAQ,MAAM,CAAC;AAEzC;KACF,KAAK;AACH,UAAI,OAAO,UAAU,SACnB,YAAW,KAAK,GAAG,QAAQ,MAAM,CAAC;AAEpC;KACF,KAAK;AACH,iBAAW,KAAK,OAAO,OAAO,CAAC;AAC/B;KACF,KAAK;AACH,iBAAW,KAAK,UAAU,OAAO,CAAC;AAClC;;AAEJ;GAEF,KAAK;AACH,YAAQ,QAAR;KACE,KAAK;AACH,UAAI,MAAM,QAAQ,MAAM,IAAI,MAAM,SAAS,GAAG;OAC5C,MAAM,UAAU,MACb,QAAQ,MAAmB,OAAO,MAAM,YAAY,EAAE,SAAS,EAAE,CACjE,KAAK,MAAM,0BAA0B,QAAQ,EAAE,CAAC;AAEnD,WAAI,QAAQ,WAAW,EACrB,YAAW,KAAK,QAAQ,GAAG;gBAClB,QAAQ,SAAS,EAC1B,YAAW,KAAK,GAAG,GAAG,QAAQ,CAAC;;AAGnC;KAEF,KAAK;AACH,UAAI,MAAM,QAAQ,MAAM,IAAI,MAAM,SAAS,GAAG;OAC5C,MAAM,UAAU,MACb,QAAQ,MAAmB,OAAO,MAAM,YAAY,EAAE,SAAS,EAAE,CACjE,KAAK,MAAM,0BAA0B,QAAQ,EAAE,CAAC;AAEnD,WAAI,QAAQ,WAAW,EACrB,YAAW,KAAK,QAAQ,GAAG;gBAClB,QAAQ,SAAS,EAC1B,YAAW,KAAK,IAAI,GAAG,QAAQ,CAAC;;AAGpC;KAEF,KAAK;AACH,iBAAW,KAAK,OAAO,OAAO,CAAC;AAC/B;KACF,KAAK;AACH,iBAAW,KAAK,UAAU,OAAO,CAAC;AAClC;;AAEJ;;;AAIN,QAAO"}
|