@mesob/common 0.0.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/.turbo/turbo-check-types.log +5 -0
- package/package.json +25 -0
- package/src/entity/entity-filter-condition.ts +79 -0
- package/src/entity/entity-list-request-schema.ts +94 -0
- package/src/entity/entity-list-request.ts +27 -0
- package/src/entity/entity-list-response.ts +4 -0
- package/src/entity/entity-list.ts +201 -0
- package/src/entity/entity-pagination.ts +14 -0
- package/src/index.ts +11 -0
- package/src/lib/dayjs/index.ts +27 -0
- package/src/types.ts +26 -0
- package/src/utility/logger.ts +56 -0
- package/tsconfig.json +17 -0
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mesob/common",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./src/index.ts",
|
|
6
|
+
"types": "./src/index.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.ts",
|
|
9
|
+
"./logger": "./src/utility/logger.ts",
|
|
10
|
+
"./dayjs": "./src/lib/dayjs/index.ts"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"dayjs": "^1.11.13",
|
|
14
|
+
"drizzle-orm": "^0.44.4",
|
|
15
|
+
"zod": "^4.1.12"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/node": "^20",
|
|
19
|
+
"typescript": "^5.7.2"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"lint": "biome check --write .",
|
|
23
|
+
"check-types": "tsc --noEmit"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { SQL, SQLWrapper } from 'drizzle-orm';
|
|
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
|
+
import type { EntityListRequest } from './entity-list-request';
|
|
15
|
+
|
|
16
|
+
type FilterOperator =
|
|
17
|
+
| 'eq'
|
|
18
|
+
| 'neq'
|
|
19
|
+
| 'gt'
|
|
20
|
+
| 'gte'
|
|
21
|
+
| 'lt'
|
|
22
|
+
| 'lte'
|
|
23
|
+
| 'like'
|
|
24
|
+
| 'ilike'
|
|
25
|
+
| 'is'
|
|
26
|
+
| 'is_not';
|
|
27
|
+
|
|
28
|
+
type Column = SQLWrapper | SQL;
|
|
29
|
+
|
|
30
|
+
const operatorMap: Record<
|
|
31
|
+
Exclude<FilterOperator, 'is' | 'is_not'>,
|
|
32
|
+
(col: Column, val: string) => SQL
|
|
33
|
+
> = {
|
|
34
|
+
eq: (col, val) => eq(col as any, val),
|
|
35
|
+
neq: (col, val) => ne(col as any, val),
|
|
36
|
+
gt: (col, val) => gt(col as any, val),
|
|
37
|
+
gte: (col, val) => gte(col as any, val),
|
|
38
|
+
lt: (col, val) => lt(col as any, val),
|
|
39
|
+
lte: (col, val) => lte(col as any, val),
|
|
40
|
+
like: (col, val) => like(col as any, val),
|
|
41
|
+
ilike: (col, val) => ilike(col as any, val),
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const buildCondition = (
|
|
45
|
+
column: Column,
|
|
46
|
+
value: string,
|
|
47
|
+
operator: FilterOperator = 'eq',
|
|
48
|
+
): SQL | undefined => {
|
|
49
|
+
if (operator === 'is') {
|
|
50
|
+
return isNull(column as any);
|
|
51
|
+
}
|
|
52
|
+
if (operator === 'is_not') {
|
|
53
|
+
return not(isNull(column as any));
|
|
54
|
+
}
|
|
55
|
+
const fn = operatorMap[operator];
|
|
56
|
+
return fn ? fn(column, value) : undefined;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const entityFilterCondition = <T extends Record<string, Column>>(
|
|
60
|
+
filters: EntityListRequest['f'],
|
|
61
|
+
columnMap: T,
|
|
62
|
+
): SQL[] => {
|
|
63
|
+
if (!filters) {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const conditions: SQL[] = [];
|
|
68
|
+
for (const filter of filters) {
|
|
69
|
+
const col = columnMap[filter.f as keyof T];
|
|
70
|
+
if (!col) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const condition = buildCondition(col, filter.v, filter.o ?? 'eq');
|
|
74
|
+
if (condition) {
|
|
75
|
+
conditions.push(condition);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return conditions;
|
|
79
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export const entityListRequestSchema = z
|
|
4
|
+
.object({
|
|
5
|
+
s: z.string().optional().describe('Search term'),
|
|
6
|
+
l: z.coerce
|
|
7
|
+
.number()
|
|
8
|
+
.min(1)
|
|
9
|
+
.max(100)
|
|
10
|
+
.optional()
|
|
11
|
+
.describe('Limit (per page)'),
|
|
12
|
+
f: z
|
|
13
|
+
.union([
|
|
14
|
+
z.array(
|
|
15
|
+
z.object({
|
|
16
|
+
f: z.string().describe('Field name'),
|
|
17
|
+
v: z.string().describe('Field value'),
|
|
18
|
+
o: z
|
|
19
|
+
.enum([
|
|
20
|
+
'eq',
|
|
21
|
+
'neq',
|
|
22
|
+
'gt',
|
|
23
|
+
'gte',
|
|
24
|
+
'lt',
|
|
25
|
+
'lte',
|
|
26
|
+
'like',
|
|
27
|
+
'ilike',
|
|
28
|
+
'is',
|
|
29
|
+
'is_not',
|
|
30
|
+
])
|
|
31
|
+
.optional()
|
|
32
|
+
.default('eq')
|
|
33
|
+
.describe('Filter operator'),
|
|
34
|
+
}),
|
|
35
|
+
),
|
|
36
|
+
z.string().transform((str, ctx) => {
|
|
37
|
+
try {
|
|
38
|
+
return JSON.parse(str) as Array<{
|
|
39
|
+
f: string;
|
|
40
|
+
v: string;
|
|
41
|
+
o?:
|
|
42
|
+
| 'eq'
|
|
43
|
+
| 'neq'
|
|
44
|
+
| 'gt'
|
|
45
|
+
| 'gte'
|
|
46
|
+
| 'lt'
|
|
47
|
+
| 'lte'
|
|
48
|
+
| 'like'
|
|
49
|
+
| 'ilike'
|
|
50
|
+
| 'is'
|
|
51
|
+
| 'is_not';
|
|
52
|
+
}>;
|
|
53
|
+
} catch {
|
|
54
|
+
ctx.addIssue({
|
|
55
|
+
code: z.ZodIssueCode.custom,
|
|
56
|
+
message: 'Invalid JSON string for filter',
|
|
57
|
+
});
|
|
58
|
+
return z.NEVER;
|
|
59
|
+
}
|
|
60
|
+
}),
|
|
61
|
+
])
|
|
62
|
+
.optional()
|
|
63
|
+
.describe('Filters'),
|
|
64
|
+
o: z
|
|
65
|
+
.union([
|
|
66
|
+
z.object({
|
|
67
|
+
f: z.string().describe('Order field'),
|
|
68
|
+
d: z
|
|
69
|
+
.enum(['asc', 'desc'])
|
|
70
|
+
.default('desc')
|
|
71
|
+
.describe('Order direction'),
|
|
72
|
+
}),
|
|
73
|
+
z.string().transform((str, ctx) => {
|
|
74
|
+
try {
|
|
75
|
+
const parsed = JSON.parse(str) as { f: string; d?: 'asc' | 'desc' };
|
|
76
|
+
return {
|
|
77
|
+
f: parsed.f,
|
|
78
|
+
d: parsed.d || 'desc',
|
|
79
|
+
};
|
|
80
|
+
} catch {
|
|
81
|
+
ctx.addIssue({
|
|
82
|
+
code: z.ZodIssueCode.custom,
|
|
83
|
+
message: 'Invalid JSON string for order',
|
|
84
|
+
});
|
|
85
|
+
return z.NEVER;
|
|
86
|
+
}
|
|
87
|
+
}),
|
|
88
|
+
])
|
|
89
|
+
.optional()
|
|
90
|
+
.describe('Ordering'),
|
|
91
|
+
p: z.coerce.number().min(1).optional().describe('Page number'),
|
|
92
|
+
pp: z.coerce.number().min(1).max(100).optional().describe('Per page'),
|
|
93
|
+
})
|
|
94
|
+
.strict();
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type EntityListRequest = {
|
|
2
|
+
s?: string; // search
|
|
3
|
+
l?: number; // local
|
|
4
|
+
f?: Array<{
|
|
5
|
+
// filter
|
|
6
|
+
f: string;
|
|
7
|
+
v: string;
|
|
8
|
+
o?:
|
|
9
|
+
| 'eq'
|
|
10
|
+
| 'neq'
|
|
11
|
+
| 'gt'
|
|
12
|
+
| 'gte'
|
|
13
|
+
| 'lt'
|
|
14
|
+
| 'lte'
|
|
15
|
+
| 'like'
|
|
16
|
+
| 'ilike'
|
|
17
|
+
| 'is'
|
|
18
|
+
| 'is_not';
|
|
19
|
+
}>;
|
|
20
|
+
o?: {
|
|
21
|
+
// order
|
|
22
|
+
f: string;
|
|
23
|
+
d: 'asc' | 'desc';
|
|
24
|
+
};
|
|
25
|
+
p?: number; // page
|
|
26
|
+
pp?: number; // per page
|
|
27
|
+
};
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Column,
|
|
3
|
+
ColumnBaseConfig,
|
|
4
|
+
ColumnDataType,
|
|
5
|
+
SQLWrapper,
|
|
6
|
+
} from 'drizzle-orm';
|
|
7
|
+
import {
|
|
8
|
+
eq,
|
|
9
|
+
gt,
|
|
10
|
+
gte,
|
|
11
|
+
ilike,
|
|
12
|
+
isNull,
|
|
13
|
+
like,
|
|
14
|
+
lt,
|
|
15
|
+
lte,
|
|
16
|
+
ne,
|
|
17
|
+
not,
|
|
18
|
+
or,
|
|
19
|
+
type SQL,
|
|
20
|
+
} from 'drizzle-orm';
|
|
21
|
+
import type { EntityListRequest } from './entity-list-request';
|
|
22
|
+
|
|
23
|
+
type FilterOperator =
|
|
24
|
+
| 'eq'
|
|
25
|
+
| 'neq'
|
|
26
|
+
| 'gt'
|
|
27
|
+
| 'gte'
|
|
28
|
+
| 'lt'
|
|
29
|
+
| 'lte'
|
|
30
|
+
| 'like'
|
|
31
|
+
| 'ilike'
|
|
32
|
+
| 'is'
|
|
33
|
+
| 'is_not';
|
|
34
|
+
|
|
35
|
+
const operatorMap: Partial<
|
|
36
|
+
Record<
|
|
37
|
+
FilterOperator,
|
|
38
|
+
(
|
|
39
|
+
column:
|
|
40
|
+
| Column<ColumnBaseConfig<ColumnDataType, string>, object, object>
|
|
41
|
+
| SQLWrapper,
|
|
42
|
+
value?: string,
|
|
43
|
+
) => SQLWrapper | SQL
|
|
44
|
+
>
|
|
45
|
+
> = {
|
|
46
|
+
eq: (col, val) =>
|
|
47
|
+
eq(
|
|
48
|
+
col as Column<ColumnBaseConfig<ColumnDataType, string>, object, object>,
|
|
49
|
+
val ?? '',
|
|
50
|
+
),
|
|
51
|
+
neq: (col, val) =>
|
|
52
|
+
ne(
|
|
53
|
+
col as Column<ColumnBaseConfig<ColumnDataType, string>, object, object>,
|
|
54
|
+
val ?? '',
|
|
55
|
+
),
|
|
56
|
+
gt: (col, val) =>
|
|
57
|
+
gt(
|
|
58
|
+
col as Column<ColumnBaseConfig<ColumnDataType, string>, object, object>,
|
|
59
|
+
val ?? '',
|
|
60
|
+
),
|
|
61
|
+
gte: (col, val) =>
|
|
62
|
+
gte(
|
|
63
|
+
col as Column<ColumnBaseConfig<ColumnDataType, string>, object, object>,
|
|
64
|
+
val ?? '',
|
|
65
|
+
),
|
|
66
|
+
lt: (col, val) =>
|
|
67
|
+
lt(
|
|
68
|
+
col as Column<ColumnBaseConfig<ColumnDataType, string>, object, object>,
|
|
69
|
+
val ?? '',
|
|
70
|
+
),
|
|
71
|
+
lte: (col, val) =>
|
|
72
|
+
lte(
|
|
73
|
+
col as Column<ColumnBaseConfig<ColumnDataType, string>, object, object>,
|
|
74
|
+
val ?? '',
|
|
75
|
+
),
|
|
76
|
+
like: (col, val) =>
|
|
77
|
+
like(
|
|
78
|
+
col as Column<ColumnBaseConfig<ColumnDataType, string>, object, object>,
|
|
79
|
+
val ?? '',
|
|
80
|
+
),
|
|
81
|
+
ilike: (col, val) =>
|
|
82
|
+
ilike(
|
|
83
|
+
col as Column<ColumnBaseConfig<ColumnDataType, string>, object, object>,
|
|
84
|
+
val ?? '',
|
|
85
|
+
),
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
type EntityListParams<T> = {
|
|
89
|
+
search?: SQLWrapper[];
|
|
90
|
+
filter?: EntityListRequest['f'];
|
|
91
|
+
booleanFilter?: {
|
|
92
|
+
column: Column<ColumnBaseConfig<ColumnDataType, string>, object, object>;
|
|
93
|
+
value: boolean;
|
|
94
|
+
};
|
|
95
|
+
orderByConfig?: {
|
|
96
|
+
column: string | SQLWrapper;
|
|
97
|
+
direction: 'asc' | 'desc';
|
|
98
|
+
};
|
|
99
|
+
p?: number;
|
|
100
|
+
pp?: number;
|
|
101
|
+
tenantId?: string;
|
|
102
|
+
entity: T;
|
|
103
|
+
skipTenantIdFilter?: boolean;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export const entityList = <T extends Record<string, unknown>>({
|
|
107
|
+
search = [],
|
|
108
|
+
filter,
|
|
109
|
+
booleanFilter,
|
|
110
|
+
orderByConfig = { column: 'createdAt', direction: 'desc' },
|
|
111
|
+
p = 1,
|
|
112
|
+
pp = 10,
|
|
113
|
+
tenantId,
|
|
114
|
+
entity,
|
|
115
|
+
skipTenantIdFilter = false,
|
|
116
|
+
}: EntityListParams<T>) => {
|
|
117
|
+
const page = Number(p);
|
|
118
|
+
const pageSize = Number(pp);
|
|
119
|
+
const conditions: (SQL | SQLWrapper)[] = [];
|
|
120
|
+
|
|
121
|
+
if (tenantId && !skipTenantIdFilter && 'tenantId' in entity) {
|
|
122
|
+
const tenantColumn = (
|
|
123
|
+
entity as unknown as {
|
|
124
|
+
tenantId: Column<
|
|
125
|
+
ColumnBaseConfig<ColumnDataType, string>,
|
|
126
|
+
object,
|
|
127
|
+
object
|
|
128
|
+
>;
|
|
129
|
+
}
|
|
130
|
+
).tenantId;
|
|
131
|
+
conditions.push(eq(tenantColumn, tenantId));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (search.length > 0) {
|
|
135
|
+
const searchConditions = search.map((column) => column);
|
|
136
|
+
const searchCondition = or(...searchConditions);
|
|
137
|
+
if (searchCondition) {
|
|
138
|
+
conditions.push(searchCondition);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (filter) {
|
|
143
|
+
conditions.push(
|
|
144
|
+
...filter.map((column) => {
|
|
145
|
+
const op = (column.o ?? 'eq') as FilterOperator;
|
|
146
|
+
const columnObj = (
|
|
147
|
+
entity as Record<
|
|
148
|
+
string,
|
|
149
|
+
Column<ColumnBaseConfig<ColumnDataType, string>, object, object>
|
|
150
|
+
>
|
|
151
|
+
)[column.f];
|
|
152
|
+
|
|
153
|
+
if (!columnObj) {
|
|
154
|
+
throw new Error(`Column '${column.f}' not found on entity`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (op === 'is') {
|
|
158
|
+
return isNull(columnObj);
|
|
159
|
+
}
|
|
160
|
+
if (op === 'is_not') {
|
|
161
|
+
return not(isNull(columnObj));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const operatorFn = operatorMap[op];
|
|
165
|
+
if (!operatorFn) {
|
|
166
|
+
throw new Error(`Unsupported operator: ${op}`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return operatorFn(columnObj, column.v);
|
|
170
|
+
}),
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (booleanFilter) {
|
|
175
|
+
conditions.push(eq(booleanFilter.column, booleanFilter.value));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
conditions,
|
|
180
|
+
orderByConfig,
|
|
181
|
+
offset: (page - 1) * pageSize,
|
|
182
|
+
limit: pageSize,
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
export const entityResponse = <T extends { totalCount: number }>(
|
|
187
|
+
result: T[],
|
|
188
|
+
): { data: Omit<T, 'totalCount'>[]; total: number } => {
|
|
189
|
+
const total = result.length > 0 ? result[0].totalCount : 0;
|
|
190
|
+
|
|
191
|
+
const data = result.map((item) => {
|
|
192
|
+
// biome-ignore lint/correctness/noUnusedVariables: intentionally destructuring to remove totalCount
|
|
193
|
+
const { totalCount, ...rest } = item;
|
|
194
|
+
return rest;
|
|
195
|
+
}) as Omit<T, 'totalCount'>[];
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
data,
|
|
199
|
+
total,
|
|
200
|
+
};
|
|
201
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses rows from a query using COUNT(*) OVER() window function
|
|
3
|
+
* Returns clean data without totalCount and extracts total
|
|
4
|
+
*/
|
|
5
|
+
export const entityPaginatedRows = <T extends { totalCount: number }>(
|
|
6
|
+
rows: T[],
|
|
7
|
+
): { data: Omit<T, 'totalCount'>[]; total: number } => {
|
|
8
|
+
const total = rows[0]?.totalCount ?? 0;
|
|
9
|
+
const data = rows.map(({ totalCount: _, ...rest }) => rest) as Omit<
|
|
10
|
+
T,
|
|
11
|
+
'totalCount'
|
|
12
|
+
>[];
|
|
13
|
+
return { data, total };
|
|
14
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** biome-ignore-all lint/performance/noBarrelFile: <explanation> */
|
|
2
|
+
|
|
3
|
+
export { entityFilterCondition } from './entity/entity-filter-condition';
|
|
4
|
+
export { entityList, entityResponse } from './entity/entity-list';
|
|
5
|
+
export type { EntityListRequest } from './entity/entity-list-request';
|
|
6
|
+
export { entityListRequestSchema } from './entity/entity-list-request-schema';
|
|
7
|
+
export type { EntityListResponse } from './entity/entity-list-response';
|
|
8
|
+
export { entityPaginatedRows } from './entity/entity-pagination';
|
|
9
|
+
export { default as dayjs } from './lib/dayjs/index';
|
|
10
|
+
export { EmploymentType, VerificationStatus } from './types';
|
|
11
|
+
export { default as logger } from './utility/logger';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// biome-ignore lint/style/noExportedImports: this is a library
|
|
2
|
+
import dayjs from 'dayjs';
|
|
3
|
+
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
|
4
|
+
import duration from 'dayjs/plugin/duration';
|
|
5
|
+
import isBetween from 'dayjs/plugin/isBetween';
|
|
6
|
+
import isToday from 'dayjs/plugin/isToday';
|
|
7
|
+
import localizedFormat from 'dayjs/plugin/localizedFormat';
|
|
8
|
+
import minmax from 'dayjs/plugin/minMax';
|
|
9
|
+
import relativeTime from 'dayjs/plugin/relativeTime';
|
|
10
|
+
import timeZone from 'dayjs/plugin/timezone';
|
|
11
|
+
import toArray from 'dayjs/plugin/toArray';
|
|
12
|
+
import utc from 'dayjs/plugin/utc';
|
|
13
|
+
|
|
14
|
+
dayjs.extend(customParseFormat);
|
|
15
|
+
dayjs.extend(isBetween);
|
|
16
|
+
dayjs.extend(isToday);
|
|
17
|
+
dayjs.extend(localizedFormat);
|
|
18
|
+
dayjs.extend(relativeTime);
|
|
19
|
+
dayjs.extend(timeZone);
|
|
20
|
+
dayjs.extend(toArray);
|
|
21
|
+
dayjs.extend(utc);
|
|
22
|
+
dayjs.extend(minmax);
|
|
23
|
+
dayjs.extend(duration);
|
|
24
|
+
|
|
25
|
+
type _Dayjs = dayjs.Dayjs;
|
|
26
|
+
|
|
27
|
+
export default dayjs;
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export enum VerificationStatus {
|
|
2
|
+
PENDING = 'pending',
|
|
3
|
+
VERIFIED = 'verified',
|
|
4
|
+
DRAFT = 'draft',
|
|
5
|
+
PUBLISHED = 'published',
|
|
6
|
+
ARCHIVED = 'archived',
|
|
7
|
+
EXPIRED = 'expired',
|
|
8
|
+
MISMATCH = 'mismatch',
|
|
9
|
+
NOT_FOUND = 'not_found',
|
|
10
|
+
CLOSED = 'closed',
|
|
11
|
+
PAUSED = 'paused',
|
|
12
|
+
OPEN = 'open',
|
|
13
|
+
TOO_MANY_ATTEMPTS = 'too_many_attempts',
|
|
14
|
+
REQUIRES_VERIFICATION = 'requires_verification',
|
|
15
|
+
UNAUTHORIZED = 'unauthorized',
|
|
16
|
+
ACCESS_DENIED = 'access_denied',
|
|
17
|
+
HAS_NO_PASSWORD = 'has_no_password',
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export enum EmploymentType {
|
|
21
|
+
FULL_TIME = 'full_time',
|
|
22
|
+
PART_TIME = 'part_time',
|
|
23
|
+
CONTRACT = 'contract',
|
|
24
|
+
INTERNSHIP = 'internship',
|
|
25
|
+
TEMPORARY = 'temporary',
|
|
26
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** biome-ignore-all lint/complexity/noBannedTypes: <explanation> */
|
|
2
|
+
/** biome-ignore-all lint/suspicious/noEmptyBlockStatements: <explanation> */
|
|
3
|
+
/** biome-ignore-all lint/suspicious/noConsole: <explanation> */
|
|
4
|
+
|
|
5
|
+
const getLocalStorage = (): {
|
|
6
|
+
getItem: (key: string) => string | null;
|
|
7
|
+
} | null => {
|
|
8
|
+
try {
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
+
const win = globalThis as any;
|
|
11
|
+
return win?.window?.localStorage ?? null;
|
|
12
|
+
} catch {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
class LoggerService {
|
|
18
|
+
debugMode = false;
|
|
19
|
+
|
|
20
|
+
constructor() {
|
|
21
|
+
const storage = getLocalStorage();
|
|
22
|
+
if (storage) {
|
|
23
|
+
this.debugMode =
|
|
24
|
+
process.env.NODE_ENV === 'development'
|
|
25
|
+
? true
|
|
26
|
+
: JSON.parse(storage.getItem('jiret:debug') ?? 'false');
|
|
27
|
+
} else {
|
|
28
|
+
this.debugMode = true;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public get log(): Function {
|
|
33
|
+
return this.debugMode ? console.log.bind(console) : (): void => {};
|
|
34
|
+
}
|
|
35
|
+
public get debug(): any {
|
|
36
|
+
return this.debugMode ? console.debug.bind(console) : (): void => {};
|
|
37
|
+
}
|
|
38
|
+
public get info(): any {
|
|
39
|
+
return this.debugMode ? console.info.bind(console) : (): void => {};
|
|
40
|
+
}
|
|
41
|
+
public get warn(): any {
|
|
42
|
+
return this.debugMode ? console.warn.bind(console) : (): void => {};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public get error(): Function {
|
|
46
|
+
return this.debugMode ? console.error.bind(console) : (): void => {};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public get table(): Function {
|
|
50
|
+
return this.debugMode ? console.table.bind(console) : (): void => {};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const logger = new LoggerService();
|
|
55
|
+
|
|
56
|
+
export default logger;
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"module": "esnext",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true
|
|
14
|
+
},
|
|
15
|
+
"include": ["src"],
|
|
16
|
+
"exclude": ["node_modules", "dist"]
|
|
17
|
+
}
|