@mesob/common 0.0.1 → 0.0.3
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/entity/entity-filter-condition.d.ts +7 -0
- package/dist/entity/entity-filter-condition.js +54 -0
- package/dist/entity/entity-filter-condition.js.map +1 -0
- package/dist/entity/entity-list-request-schema.d.ts +40 -0
- package/dist/entity/entity-list-request-schema.js +64 -0
- package/dist/entity/entity-list-request-schema.js.map +1 -0
- package/dist/entity/entity-list-request.d.ts +17 -0
- package/dist/entity/entity-list-request.js +1 -0
- package/dist/entity/entity-list-request.js.map +1 -0
- package/dist/entity/entity-list-response.d.ts +6 -0
- package/dist/entity/entity-list-response.js +1 -0
- package/dist/entity/entity-list-response.js.map +1 -0
- package/dist/entity/entity-list.d.ts +37 -0
- package/dist/entity/entity-list.js +121 -0
- package/dist/entity/entity-list.js.map +1 -0
- package/dist/entity/entity-pagination.d.ts +12 -0
- package/dist/entity/entity-pagination.js +10 -0
- package/dist/entity/entity-pagination.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +316 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/dayjs/index.d.ts +2 -0
- package/dist/lib/dayjs/index.js +27 -0
- package/dist/lib/dayjs/index.js.map +1 -0
- package/dist/utility/logger.d.ts +16 -0
- package/dist/utility/logger.js +50 -0
- package/dist/utility/logger.js.map +1 -0
- package/package.json +37 -6
- package/.turbo/turbo-check-types.log +0 -5
- package/src/entity/entity-filter-condition.ts +0 -79
- package/src/entity/entity-list-request-schema.ts +0 -94
- package/src/entity/entity-list-request.ts +0 -27
- package/src/entity/entity-list-response.ts +0 -4
- package/src/entity/entity-list.ts +0 -201
- package/src/entity/entity-pagination.ts +0 -14
- package/src/index.ts +0 -11
- package/src/lib/dayjs/index.ts +0 -27
- package/src/types.ts +0 -26
- package/src/utility/logger.ts +0 -56
- package/tsconfig.json +0 -17
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { SQLWrapper, SQL } from 'drizzle-orm';
|
|
2
|
+
import { EntityListRequest } from './entity-list-request.js';
|
|
3
|
+
|
|
4
|
+
type Column = SQLWrapper | SQL;
|
|
5
|
+
declare const entityFilterCondition: <T extends Record<string, Column>>(filters: EntityListRequest["f"], columnMap: T) => SQL[];
|
|
6
|
+
|
|
7
|
+
export { entityFilterCondition };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// src/entity/entity-filter-condition.ts
|
|
2
|
+
import {
|
|
3
|
+
eq,
|
|
4
|
+
gt,
|
|
5
|
+
gte,
|
|
6
|
+
ilike,
|
|
7
|
+
isNull,
|
|
8
|
+
like,
|
|
9
|
+
lt,
|
|
10
|
+
lte,
|
|
11
|
+
ne,
|
|
12
|
+
not
|
|
13
|
+
} from "drizzle-orm";
|
|
14
|
+
var operatorMap = {
|
|
15
|
+
eq: (col, val) => eq(col, val),
|
|
16
|
+
neq: (col, val) => ne(col, val),
|
|
17
|
+
gt: (col, val) => gt(col, val),
|
|
18
|
+
gte: (col, val) => gte(col, val),
|
|
19
|
+
lt: (col, val) => lt(col, val),
|
|
20
|
+
lte: (col, val) => lte(col, val),
|
|
21
|
+
like: (col, val) => like(col, val),
|
|
22
|
+
ilike: (col, val) => ilike(col, val)
|
|
23
|
+
};
|
|
24
|
+
var buildCondition = (column, value, operator = "eq") => {
|
|
25
|
+
if (operator === "is") {
|
|
26
|
+
return isNull(column);
|
|
27
|
+
}
|
|
28
|
+
if (operator === "is_not") {
|
|
29
|
+
return not(isNull(column));
|
|
30
|
+
}
|
|
31
|
+
const fn = operatorMap[operator];
|
|
32
|
+
return fn ? fn(column, value) : void 0;
|
|
33
|
+
};
|
|
34
|
+
var entityFilterCondition = (filters, columnMap) => {
|
|
35
|
+
if (!filters) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
const conditions = [];
|
|
39
|
+
for (const filter of filters) {
|
|
40
|
+
const col = columnMap[filter.f];
|
|
41
|
+
if (!col) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const condition = buildCondition(col, filter.v, filter.o ?? "eq");
|
|
45
|
+
if (condition) {
|
|
46
|
+
conditions.push(condition);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return conditions;
|
|
50
|
+
};
|
|
51
|
+
export {
|
|
52
|
+
entityFilterCondition
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=entity-filter-condition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/entity/entity-filter-condition.ts"],"sourcesContent":["import type { SQL, SQLWrapper } from 'drizzle-orm';\nimport {\n eq,\n gt,\n gte,\n ilike,\n isNull,\n like,\n lt,\n lte,\n ne,\n not,\n} from 'drizzle-orm';\nimport type { EntityListRequest } from './entity-list-request';\n\ntype FilterOperator =\n | 'eq'\n | 'neq'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'like'\n | 'ilike'\n | 'is'\n | 'is_not';\n\ntype Column = SQLWrapper | SQL;\n\nconst operatorMap: Record<\n Exclude<FilterOperator, 'is' | 'is_not'>,\n (col: Column, val: string) => SQL\n> = {\n eq: (col, val) => eq(col as any, val),\n neq: (col, val) => ne(col as any, val),\n gt: (col, val) => gt(col as any, val),\n gte: (col, val) => gte(col as any, val),\n lt: (col, val) => lt(col as any, val),\n lte: (col, val) => lte(col as any, val),\n like: (col, val) => like(col as any, val),\n ilike: (col, val) => ilike(col as any, val),\n};\n\nconst buildCondition = (\n column: Column,\n value: string,\n operator: FilterOperator = 'eq',\n): SQL | undefined => {\n if (operator === 'is') {\n return isNull(column as any);\n }\n if (operator === 'is_not') {\n return not(isNull(column as any));\n }\n const fn = operatorMap[operator];\n return fn ? fn(column, value) : undefined;\n};\n\nexport const entityFilterCondition = <T extends Record<string, Column>>(\n filters: EntityListRequest['f'],\n columnMap: T,\n): SQL[] => {\n if (!filters) {\n return [];\n }\n\n const conditions: SQL[] = [];\n for (const filter of filters) {\n const col = columnMap[filter.f as keyof T];\n if (!col) {\n continue;\n }\n const condition = buildCondition(col, filter.v, filter.o ?? 'eq');\n if (condition) {\n conditions.push(condition);\n }\n }\n return conditions;\n};\n"],"mappings":";AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAiBP,IAAM,cAGF;AAAA,EACF,IAAI,CAAC,KAAK,QAAQ,GAAG,KAAY,GAAG;AAAA,EACpC,KAAK,CAAC,KAAK,QAAQ,GAAG,KAAY,GAAG;AAAA,EACrC,IAAI,CAAC,KAAK,QAAQ,GAAG,KAAY,GAAG;AAAA,EACpC,KAAK,CAAC,KAAK,QAAQ,IAAI,KAAY,GAAG;AAAA,EACtC,IAAI,CAAC,KAAK,QAAQ,GAAG,KAAY,GAAG;AAAA,EACpC,KAAK,CAAC,KAAK,QAAQ,IAAI,KAAY,GAAG;AAAA,EACtC,MAAM,CAAC,KAAK,QAAQ,KAAK,KAAY,GAAG;AAAA,EACxC,OAAO,CAAC,KAAK,QAAQ,MAAM,KAAY,GAAG;AAC5C;AAEA,IAAM,iBAAiB,CACrB,QACA,OACA,WAA2B,SACP;AACpB,MAAI,aAAa,MAAM;AACrB,WAAO,OAAO,MAAa;AAAA,EAC7B;AACA,MAAI,aAAa,UAAU;AACzB,WAAO,IAAI,OAAO,MAAa,CAAC;AAAA,EAClC;AACA,QAAM,KAAK,YAAY,QAAQ;AAC/B,SAAO,KAAK,GAAG,QAAQ,KAAK,IAAI;AAClC;AAEO,IAAM,wBAAwB,CACnC,SACA,cACU;AACV,MAAI,CAAC,SAAS;AACZ,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,aAAoB,CAAC;AAC3B,aAAW,UAAU,SAAS;AAC5B,UAAM,MAAM,UAAU,OAAO,CAAY;AACzC,QAAI,CAAC,KAAK;AACR;AAAA,IACF;AACA,UAAM,YAAY,eAAe,KAAK,OAAO,GAAG,OAAO,KAAK,IAAI;AAChE,QAAI,WAAW;AACb,iBAAW,KAAK,SAAS;AAAA,IAC3B;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
declare const entityListRequestSchema: z.ZodObject<{
|
|
4
|
+
s: z.ZodOptional<z.ZodString>;
|
|
5
|
+
l: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
6
|
+
f: z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodObject<{
|
|
7
|
+
f: z.ZodString;
|
|
8
|
+
v: z.ZodString;
|
|
9
|
+
o: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
10
|
+
eq: "eq";
|
|
11
|
+
neq: "neq";
|
|
12
|
+
gt: "gt";
|
|
13
|
+
gte: "gte";
|
|
14
|
+
lt: "lt";
|
|
15
|
+
lte: "lte";
|
|
16
|
+
like: "like";
|
|
17
|
+
ilike: "ilike";
|
|
18
|
+
is: "is";
|
|
19
|
+
is_not: "is_not";
|
|
20
|
+
}>>>;
|
|
21
|
+
}, z.core.$strip>>, z.ZodPipe<z.ZodString, z.ZodTransform<{
|
|
22
|
+
f: string;
|
|
23
|
+
v: string;
|
|
24
|
+
o?: "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "like" | "ilike" | "is" | "is_not";
|
|
25
|
+
}[], string>>]>>;
|
|
26
|
+
o: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
27
|
+
f: z.ZodString;
|
|
28
|
+
d: z.ZodDefault<z.ZodEnum<{
|
|
29
|
+
asc: "asc";
|
|
30
|
+
desc: "desc";
|
|
31
|
+
}>>;
|
|
32
|
+
}, z.core.$strip>, z.ZodPipe<z.ZodString, z.ZodTransform<{
|
|
33
|
+
f: string;
|
|
34
|
+
d: "asc" | "desc";
|
|
35
|
+
}, string>>]>>;
|
|
36
|
+
p: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
37
|
+
pp: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
38
|
+
}, z.core.$strict>;
|
|
39
|
+
|
|
40
|
+
export { entityListRequestSchema };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// src/entity/entity-list-request-schema.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var entityListRequestSchema = z.object({
|
|
4
|
+
s: z.string().optional().describe("Search term"),
|
|
5
|
+
l: z.coerce.number().min(1).max(100).optional().describe("Limit (per page)"),
|
|
6
|
+
f: z.union([
|
|
7
|
+
z.array(
|
|
8
|
+
z.object({
|
|
9
|
+
f: z.string().describe("Field name"),
|
|
10
|
+
v: z.string().describe("Field value"),
|
|
11
|
+
o: z.enum([
|
|
12
|
+
"eq",
|
|
13
|
+
"neq",
|
|
14
|
+
"gt",
|
|
15
|
+
"gte",
|
|
16
|
+
"lt",
|
|
17
|
+
"lte",
|
|
18
|
+
"like",
|
|
19
|
+
"ilike",
|
|
20
|
+
"is",
|
|
21
|
+
"is_not"
|
|
22
|
+
]).optional().default("eq").describe("Filter operator")
|
|
23
|
+
})
|
|
24
|
+
),
|
|
25
|
+
z.string().transform((str, ctx) => {
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(str);
|
|
28
|
+
} catch {
|
|
29
|
+
ctx.addIssue({
|
|
30
|
+
code: z.ZodIssueCode.custom,
|
|
31
|
+
message: "Invalid JSON string for filter"
|
|
32
|
+
});
|
|
33
|
+
return z.NEVER;
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
]).optional().describe("Filters"),
|
|
37
|
+
o: z.union([
|
|
38
|
+
z.object({
|
|
39
|
+
f: z.string().describe("Order field"),
|
|
40
|
+
d: z.enum(["asc", "desc"]).default("desc").describe("Order direction")
|
|
41
|
+
}),
|
|
42
|
+
z.string().transform((str, ctx) => {
|
|
43
|
+
try {
|
|
44
|
+
const parsed = JSON.parse(str);
|
|
45
|
+
return {
|
|
46
|
+
f: parsed.f,
|
|
47
|
+
d: parsed.d || "desc"
|
|
48
|
+
};
|
|
49
|
+
} catch {
|
|
50
|
+
ctx.addIssue({
|
|
51
|
+
code: z.ZodIssueCode.custom,
|
|
52
|
+
message: "Invalid JSON string for order"
|
|
53
|
+
});
|
|
54
|
+
return z.NEVER;
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
]).optional().describe("Ordering"),
|
|
58
|
+
p: z.coerce.number().min(1).optional().describe("Page number"),
|
|
59
|
+
pp: z.coerce.number().min(1).max(100).optional().describe("Per page")
|
|
60
|
+
}).strict();
|
|
61
|
+
export {
|
|
62
|
+
entityListRequestSchema
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=entity-list-request-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/entity/entity-list-request-schema.ts"],"sourcesContent":["import { z } from 'zod';\n\nexport const entityListRequestSchema = z\n .object({\n s: z.string().optional().describe('Search term'),\n l: z.coerce\n .number()\n .min(1)\n .max(100)\n .optional()\n .describe('Limit (per page)'),\n f: z\n .union([\n z.array(\n z.object({\n f: z.string().describe('Field name'),\n v: z.string().describe('Field value'),\n o: z\n .enum([\n 'eq',\n 'neq',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'like',\n 'ilike',\n 'is',\n 'is_not',\n ])\n .optional()\n .default('eq')\n .describe('Filter operator'),\n }),\n ),\n z.string().transform((str, ctx) => {\n try {\n return JSON.parse(str) as Array<{\n f: string;\n v: string;\n o?:\n | 'eq'\n | 'neq'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'like'\n | 'ilike'\n | 'is'\n | 'is_not';\n }>;\n } catch {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'Invalid JSON string for filter',\n });\n return z.NEVER;\n }\n }),\n ])\n .optional()\n .describe('Filters'),\n o: z\n .union([\n z.object({\n f: z.string().describe('Order field'),\n d: z\n .enum(['asc', 'desc'])\n .default('desc')\n .describe('Order direction'),\n }),\n z.string().transform((str, ctx) => {\n try {\n const parsed = JSON.parse(str) as { f: string; d?: 'asc' | 'desc' };\n return {\n f: parsed.f,\n d: parsed.d || 'desc',\n };\n } catch {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'Invalid JSON string for order',\n });\n return z.NEVER;\n }\n }),\n ])\n .optional()\n .describe('Ordering'),\n p: z.coerce.number().min(1).optional().describe('Page number'),\n pp: z.coerce.number().min(1).max(100).optional().describe('Per page'),\n })\n .strict();\n"],"mappings":";AAAA,SAAS,SAAS;AAEX,IAAM,0BAA0B,EACpC,OAAO;AAAA,EACN,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,aAAa;AAAA,EAC/C,GAAG,EAAE,OACF,OAAO,EACP,IAAI,CAAC,EACL,IAAI,GAAG,EACP,SAAS,EACT,SAAS,kBAAkB;AAAA,EAC9B,GAAG,EACA,MAAM;AAAA,IACL,EAAE;AAAA,MACA,EAAE,OAAO;AAAA,QACP,GAAG,EAAE,OAAO,EAAE,SAAS,YAAY;AAAA,QACnC,GAAG,EAAE,OAAO,EAAE,SAAS,aAAa;AAAA,QACpC,GAAG,EACA,KAAK;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC,EACA,SAAS,EACT,QAAQ,IAAI,EACZ,SAAS,iBAAiB;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,IACA,EAAE,OAAO,EAAE,UAAU,CAAC,KAAK,QAAQ;AACjC,UAAI;AACF,eAAO,KAAK,MAAM,GAAG;AAAA,MAevB,QAAQ;AACN,YAAI,SAAS;AAAA,UACX,MAAM,EAAE,aAAa;AAAA,UACrB,SAAS;AAAA,QACX,CAAC;AACD,eAAO,EAAE;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH,CAAC,EACA,SAAS,EACT,SAAS,SAAS;AAAA,EACrB,GAAG,EACA,MAAM;AAAA,IACL,EAAE,OAAO;AAAA,MACP,GAAG,EAAE,OAAO,EAAE,SAAS,aAAa;AAAA,MACpC,GAAG,EACA,KAAK,CAAC,OAAO,MAAM,CAAC,EACpB,QAAQ,MAAM,EACd,SAAS,iBAAiB;AAAA,IAC/B,CAAC;AAAA,IACD,EAAE,OAAO,EAAE,UAAU,CAAC,KAAK,QAAQ;AACjC,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,eAAO;AAAA,UACL,GAAG,OAAO;AAAA,UACV,GAAG,OAAO,KAAK;AAAA,QACjB;AAAA,MACF,QAAQ;AACN,YAAI,SAAS;AAAA,UACX,MAAM,EAAE,aAAa;AAAA,UACrB,SAAS;AAAA,QACX,CAAC;AACD,eAAO,EAAE;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH,CAAC,EACA,SAAS,EACT,SAAS,UAAU;AAAA,EACtB,GAAG,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,aAAa;AAAA,EAC7D,IAAI,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,UAAU;AACtE,CAAC,EACA,OAAO;","names":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type EntityListRequest = {
|
|
2
|
+
s?: string;
|
|
3
|
+
l?: number;
|
|
4
|
+
f?: Array<{
|
|
5
|
+
f: string;
|
|
6
|
+
v: string;
|
|
7
|
+
o?: 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte' | 'like' | 'ilike' | 'is' | 'is_not';
|
|
8
|
+
}>;
|
|
9
|
+
o?: {
|
|
10
|
+
f: string;
|
|
11
|
+
d: 'asc' | 'desc';
|
|
12
|
+
};
|
|
13
|
+
p?: number;
|
|
14
|
+
pp?: number;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type { EntityListRequest };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=entity-list-request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=entity-list-response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { SQLWrapper, Column, ColumnBaseConfig, ColumnDataType, SQL } from 'drizzle-orm';
|
|
2
|
+
import { EntityListRequest } from './entity-list-request.js';
|
|
3
|
+
|
|
4
|
+
type EntityListParams<T> = {
|
|
5
|
+
search?: SQLWrapper[];
|
|
6
|
+
filter?: EntityListRequest['f'];
|
|
7
|
+
booleanFilter?: {
|
|
8
|
+
column: Column<ColumnBaseConfig<ColumnDataType, string>, object, object>;
|
|
9
|
+
value: boolean;
|
|
10
|
+
};
|
|
11
|
+
orderByConfig?: {
|
|
12
|
+
column: string | SQLWrapper;
|
|
13
|
+
direction: 'asc' | 'desc';
|
|
14
|
+
};
|
|
15
|
+
p?: number;
|
|
16
|
+
pp?: number;
|
|
17
|
+
tenantId?: string;
|
|
18
|
+
entity: T;
|
|
19
|
+
skipTenantIdFilter?: boolean;
|
|
20
|
+
};
|
|
21
|
+
declare const entityList: <T extends Record<string, unknown>>({ search, filter, booleanFilter, orderByConfig, p, pp, tenantId, entity, skipTenantIdFilter, }: EntityListParams<T>) => {
|
|
22
|
+
conditions: (SQLWrapper | SQL<unknown>)[];
|
|
23
|
+
orderByConfig: {
|
|
24
|
+
column: string | SQLWrapper;
|
|
25
|
+
direction: "asc" | "desc";
|
|
26
|
+
};
|
|
27
|
+
offset: number;
|
|
28
|
+
limit: number;
|
|
29
|
+
};
|
|
30
|
+
declare const entityResponse: <T extends {
|
|
31
|
+
totalCount: number;
|
|
32
|
+
}>(result: T[]) => {
|
|
33
|
+
data: Omit<T, "totalCount">[];
|
|
34
|
+
total: number;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export { entityList, entityResponse };
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// src/entity/entity-list.ts
|
|
2
|
+
import {
|
|
3
|
+
eq,
|
|
4
|
+
gt,
|
|
5
|
+
gte,
|
|
6
|
+
ilike,
|
|
7
|
+
isNull,
|
|
8
|
+
like,
|
|
9
|
+
lt,
|
|
10
|
+
lte,
|
|
11
|
+
ne,
|
|
12
|
+
not,
|
|
13
|
+
or
|
|
14
|
+
} from "drizzle-orm";
|
|
15
|
+
var operatorMap = {
|
|
16
|
+
eq: (col, val) => eq(
|
|
17
|
+
col,
|
|
18
|
+
val ?? ""
|
|
19
|
+
),
|
|
20
|
+
neq: (col, val) => ne(
|
|
21
|
+
col,
|
|
22
|
+
val ?? ""
|
|
23
|
+
),
|
|
24
|
+
gt: (col, val) => gt(
|
|
25
|
+
col,
|
|
26
|
+
val ?? ""
|
|
27
|
+
),
|
|
28
|
+
gte: (col, val) => gte(
|
|
29
|
+
col,
|
|
30
|
+
val ?? ""
|
|
31
|
+
),
|
|
32
|
+
lt: (col, val) => lt(
|
|
33
|
+
col,
|
|
34
|
+
val ?? ""
|
|
35
|
+
),
|
|
36
|
+
lte: (col, val) => lte(
|
|
37
|
+
col,
|
|
38
|
+
val ?? ""
|
|
39
|
+
),
|
|
40
|
+
like: (col, val) => like(
|
|
41
|
+
col,
|
|
42
|
+
val ?? ""
|
|
43
|
+
),
|
|
44
|
+
ilike: (col, val) => ilike(
|
|
45
|
+
col,
|
|
46
|
+
val ?? ""
|
|
47
|
+
)
|
|
48
|
+
};
|
|
49
|
+
var entityList = ({
|
|
50
|
+
search = [],
|
|
51
|
+
filter,
|
|
52
|
+
booleanFilter,
|
|
53
|
+
orderByConfig = { column: "createdAt", direction: "desc" },
|
|
54
|
+
p = 1,
|
|
55
|
+
pp = 10,
|
|
56
|
+
tenantId,
|
|
57
|
+
entity,
|
|
58
|
+
skipTenantIdFilter = false
|
|
59
|
+
}) => {
|
|
60
|
+
const page = Number(p);
|
|
61
|
+
const pageSize = Number(pp);
|
|
62
|
+
const conditions = [];
|
|
63
|
+
if (tenantId && !skipTenantIdFilter && "tenantId" in entity) {
|
|
64
|
+
const tenantColumn = entity.tenantId;
|
|
65
|
+
conditions.push(eq(tenantColumn, tenantId));
|
|
66
|
+
}
|
|
67
|
+
if (search.length > 0) {
|
|
68
|
+
const searchConditions = search.map((column) => column);
|
|
69
|
+
const searchCondition = or(...searchConditions);
|
|
70
|
+
if (searchCondition) {
|
|
71
|
+
conditions.push(searchCondition);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (filter) {
|
|
75
|
+
conditions.push(
|
|
76
|
+
...filter.map((column) => {
|
|
77
|
+
const op = column.o ?? "eq";
|
|
78
|
+
const columnObj = entity[column.f];
|
|
79
|
+
if (!columnObj) {
|
|
80
|
+
throw new Error(`Column '${column.f}' not found on entity`);
|
|
81
|
+
}
|
|
82
|
+
if (op === "is") {
|
|
83
|
+
return isNull(columnObj);
|
|
84
|
+
}
|
|
85
|
+
if (op === "is_not") {
|
|
86
|
+
return not(isNull(columnObj));
|
|
87
|
+
}
|
|
88
|
+
const operatorFn = operatorMap[op];
|
|
89
|
+
if (!operatorFn) {
|
|
90
|
+
throw new Error(`Unsupported operator: ${op}`);
|
|
91
|
+
}
|
|
92
|
+
return operatorFn(columnObj, column.v);
|
|
93
|
+
})
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
if (booleanFilter) {
|
|
97
|
+
conditions.push(eq(booleanFilter.column, booleanFilter.value));
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
conditions,
|
|
101
|
+
orderByConfig,
|
|
102
|
+
offset: (page - 1) * pageSize,
|
|
103
|
+
limit: pageSize
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
var entityResponse = (result) => {
|
|
107
|
+
const total = result.length > 0 ? result[0].totalCount : 0;
|
|
108
|
+
const data = result.map((item) => {
|
|
109
|
+
const { totalCount, ...rest } = item;
|
|
110
|
+
return rest;
|
|
111
|
+
});
|
|
112
|
+
return {
|
|
113
|
+
data,
|
|
114
|
+
total
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
export {
|
|
118
|
+
entityList,
|
|
119
|
+
entityResponse
|
|
120
|
+
};
|
|
121
|
+
//# sourceMappingURL=entity-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/entity/entity-list.ts"],"sourcesContent":["import type {\n Column,\n ColumnBaseConfig,\n ColumnDataType,\n SQLWrapper,\n} from 'drizzle-orm';\nimport {\n eq,\n gt,\n gte,\n ilike,\n isNull,\n like,\n lt,\n lte,\n ne,\n not,\n or,\n type SQL,\n} from 'drizzle-orm';\nimport type { EntityListRequest } from './entity-list-request';\n\ntype FilterOperator =\n | 'eq'\n | 'neq'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'like'\n | 'ilike'\n | 'is'\n | 'is_not';\n\nconst operatorMap: Partial<\n Record<\n FilterOperator,\n (\n column:\n | Column<ColumnBaseConfig<ColumnDataType, string>, object, object>\n | SQLWrapper,\n value?: string,\n ) => SQLWrapper | SQL\n >\n> = {\n eq: (col, val) =>\n eq(\n col as Column<ColumnBaseConfig<ColumnDataType, string>, object, object>,\n val ?? '',\n ),\n neq: (col, val) =>\n ne(\n col as Column<ColumnBaseConfig<ColumnDataType, string>, object, object>,\n val ?? '',\n ),\n gt: (col, val) =>\n gt(\n col as Column<ColumnBaseConfig<ColumnDataType, string>, object, object>,\n val ?? '',\n ),\n gte: (col, val) =>\n gte(\n col as Column<ColumnBaseConfig<ColumnDataType, string>, object, object>,\n val ?? '',\n ),\n lt: (col, val) =>\n lt(\n col as Column<ColumnBaseConfig<ColumnDataType, string>, object, object>,\n val ?? '',\n ),\n lte: (col, val) =>\n lte(\n col as Column<ColumnBaseConfig<ColumnDataType, string>, object, object>,\n val ?? '',\n ),\n like: (col, val) =>\n like(\n col as Column<ColumnBaseConfig<ColumnDataType, string>, object, object>,\n val ?? '',\n ),\n ilike: (col, val) =>\n ilike(\n col as Column<ColumnBaseConfig<ColumnDataType, string>, object, object>,\n val ?? '',\n ),\n};\n\ntype EntityListParams<T> = {\n search?: SQLWrapper[];\n filter?: EntityListRequest['f'];\n booleanFilter?: {\n column: Column<ColumnBaseConfig<ColumnDataType, string>, object, object>;\n value: boolean;\n };\n orderByConfig?: {\n column: string | SQLWrapper;\n direction: 'asc' | 'desc';\n };\n p?: number;\n pp?: number;\n tenantId?: string;\n entity: T;\n skipTenantIdFilter?: boolean;\n};\n\nexport const entityList = <T extends Record<string, unknown>>({\n search = [],\n filter,\n booleanFilter,\n orderByConfig = { column: 'createdAt', direction: 'desc' },\n p = 1,\n pp = 10,\n tenantId,\n entity,\n skipTenantIdFilter = false,\n}: EntityListParams<T>) => {\n const page = Number(p);\n const pageSize = Number(pp);\n const conditions: (SQL | SQLWrapper)[] = [];\n\n if (tenantId && !skipTenantIdFilter && 'tenantId' in entity) {\n const tenantColumn = (\n entity as unknown as {\n tenantId: Column<\n ColumnBaseConfig<ColumnDataType, string>,\n object,\n object\n >;\n }\n ).tenantId;\n conditions.push(eq(tenantColumn, tenantId));\n }\n\n if (search.length > 0) {\n const searchConditions = search.map((column) => column);\n const searchCondition = or(...searchConditions);\n if (searchCondition) {\n conditions.push(searchCondition);\n }\n }\n\n if (filter) {\n conditions.push(\n ...filter.map((column) => {\n const op = (column.o ?? 'eq') as FilterOperator;\n const columnObj = (\n entity as Record<\n string,\n Column<ColumnBaseConfig<ColumnDataType, string>, object, object>\n >\n )[column.f];\n\n if (!columnObj) {\n throw new Error(`Column '${column.f}' not found on entity`);\n }\n\n if (op === 'is') {\n return isNull(columnObj);\n }\n if (op === 'is_not') {\n return not(isNull(columnObj));\n }\n\n const operatorFn = operatorMap[op];\n if (!operatorFn) {\n throw new Error(`Unsupported operator: ${op}`);\n }\n\n return operatorFn(columnObj, column.v);\n }),\n );\n }\n\n if (booleanFilter) {\n conditions.push(eq(booleanFilter.column, booleanFilter.value));\n }\n\n return {\n conditions,\n orderByConfig,\n offset: (page - 1) * pageSize,\n limit: pageSize,\n };\n};\n\nexport const entityResponse = <T extends { totalCount: number }>(\n result: T[],\n): { data: Omit<T, 'totalCount'>[]; total: number } => {\n const total = result.length > 0 ? result[0].totalCount : 0;\n\n const data = result.map((item) => {\n // biome-ignore lint/correctness/noUnusedVariables: intentionally destructuring to remove totalCount\n const { totalCount, ...rest } = item;\n return rest;\n }) as Omit<T, 'totalCount'>[];\n\n return {\n data,\n total,\n };\n};\n"],"mappings":";AAMA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAeP,IAAM,cAUF;AAAA,EACF,IAAI,CAAC,KAAK,QACR;AAAA,IACE;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EACF,KAAK,CAAC,KAAK,QACT;AAAA,IACE;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EACF,IAAI,CAAC,KAAK,QACR;AAAA,IACE;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EACF,KAAK,CAAC,KAAK,QACT;AAAA,IACE;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EACF,IAAI,CAAC,KAAK,QACR;AAAA,IACE;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EACF,KAAK,CAAC,KAAK,QACT;AAAA,IACE;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EACF,MAAM,CAAC,KAAK,QACV;AAAA,IACE;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EACF,OAAO,CAAC,KAAK,QACX;AAAA,IACE;AAAA,IACA,OAAO;AAAA,EACT;AACJ;AAoBO,IAAM,aAAa,CAAoC;AAAA,EAC5D,SAAS,CAAC;AAAA,EACV;AAAA,EACA;AAAA,EACA,gBAAgB,EAAE,QAAQ,aAAa,WAAW,OAAO;AAAA,EACzD,IAAI;AAAA,EACJ,KAAK;AAAA,EACL;AAAA,EACA;AAAA,EACA,qBAAqB;AACvB,MAA2B;AACzB,QAAM,OAAO,OAAO,CAAC;AACrB,QAAM,WAAW,OAAO,EAAE;AAC1B,QAAM,aAAmC,CAAC;AAE1C,MAAI,YAAY,CAAC,sBAAsB,cAAc,QAAQ;AAC3D,UAAM,eACJ,OAOA;AACF,eAAW,KAAK,GAAG,cAAc,QAAQ,CAAC;AAAA,EAC5C;AAEA,MAAI,OAAO,SAAS,GAAG;AACrB,UAAM,mBAAmB,OAAO,IAAI,CAAC,WAAW,MAAM;AACtD,UAAM,kBAAkB,GAAG,GAAG,gBAAgB;AAC9C,QAAI,iBAAiB;AACnB,iBAAW,KAAK,eAAe;AAAA,IACjC;AAAA,EACF;AAEA,MAAI,QAAQ;AACV,eAAW;AAAA,MACT,GAAG,OAAO,IAAI,CAAC,WAAW;AACxB,cAAM,KAAM,OAAO,KAAK;AACxB,cAAM,YACJ,OAIA,OAAO,CAAC;AAEV,YAAI,CAAC,WAAW;AACd,gBAAM,IAAI,MAAM,WAAW,OAAO,CAAC,uBAAuB;AAAA,QAC5D;AAEA,YAAI,OAAO,MAAM;AACf,iBAAO,OAAO,SAAS;AAAA,QACzB;AACA,YAAI,OAAO,UAAU;AACnB,iBAAO,IAAI,OAAO,SAAS,CAAC;AAAA,QAC9B;AAEA,cAAM,aAAa,YAAY,EAAE;AACjC,YAAI,CAAC,YAAY;AACf,gBAAM,IAAI,MAAM,yBAAyB,EAAE,EAAE;AAAA,QAC/C;AAEA,eAAO,WAAW,WAAW,OAAO,CAAC;AAAA,MACvC,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,eAAe;AACjB,eAAW,KAAK,GAAG,cAAc,QAAQ,cAAc,KAAK,CAAC;AAAA,EAC/D;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,SAAS,OAAO,KAAK;AAAA,IACrB,OAAO;AAAA,EACT;AACF;AAEO,IAAM,iBAAiB,CAC5B,WACqD;AACrD,QAAM,QAAQ,OAAO,SAAS,IAAI,OAAO,CAAC,EAAE,aAAa;AAEzD,QAAM,OAAO,OAAO,IAAI,CAAC,SAAS;AAEhC,UAAM,EAAE,YAAY,GAAG,KAAK,IAAI;AAChC,WAAO;AAAA,EACT,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses rows from a query using COUNT(*) OVER() window function
|
|
3
|
+
* Returns clean data without totalCount and extracts total
|
|
4
|
+
*/
|
|
5
|
+
declare const entityPaginatedRows: <T extends {
|
|
6
|
+
totalCount: number;
|
|
7
|
+
}>(rows: T[]) => {
|
|
8
|
+
data: Omit<T, "totalCount">[];
|
|
9
|
+
total: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export { entityPaginatedRows };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// src/entity/entity-pagination.ts
|
|
2
|
+
var entityPaginatedRows = (rows) => {
|
|
3
|
+
const total = rows[0]?.totalCount ?? 0;
|
|
4
|
+
const data = rows.map(({ totalCount: _, ...rest }) => rest);
|
|
5
|
+
return { data, total };
|
|
6
|
+
};
|
|
7
|
+
export {
|
|
8
|
+
entityPaginatedRows
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=entity-pagination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/entity/entity-pagination.ts"],"sourcesContent":["/**\n * Parses rows from a query using COUNT(*) OVER() window function\n * Returns clean data without totalCount and extracts total\n */\nexport const entityPaginatedRows = <T extends { totalCount: number }>(\n rows: T[],\n): { data: Omit<T, 'totalCount'>[]; total: number } => {\n const total = rows[0]?.totalCount ?? 0;\n const data = rows.map(({ totalCount: _, ...rest }) => rest) as Omit<\n T,\n 'totalCount'\n >[];\n return { data, total };\n};\n"],"mappings":";AAIO,IAAM,sBAAsB,CACjC,SACqD;AACrD,QAAM,QAAQ,KAAK,CAAC,GAAG,cAAc;AACrC,QAAM,OAAO,KAAK,IAAI,CAAC,EAAE,YAAY,GAAG,GAAG,KAAK,MAAM,IAAI;AAI1D,SAAO,EAAE,MAAM,MAAM;AACvB;","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { entityFilterCondition } from './entity/entity-filter-condition.js';
|
|
2
|
+
export { entityList, entityResponse } from './entity/entity-list.js';
|
|
3
|
+
export { EntityListRequest } from './entity/entity-list-request.js';
|
|
4
|
+
export { entityListRequestSchema } from './entity/entity-list-request-schema.js';
|
|
5
|
+
export { EntityListResponse } from './entity/entity-list-response.js';
|
|
6
|
+
export { entityPaginatedRows } from './entity/entity-pagination.js';
|
|
7
|
+
export { default as dayjs } from 'dayjs';
|
|
8
|
+
export { default as logger } from './utility/logger.js';
|
|
9
|
+
import 'drizzle-orm';
|
|
10
|
+
import 'zod';
|