zavadil-ts-common 1.0.0
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/.env-example +1 -0
- package/README.MD +16 -0
- package/bin/build +2 -0
- package/bin/build.cmd +2 -0
- package/bin/install +1 -0
- package/bin/install.cmd +1 -0
- package/bin/publish +2 -0
- package/bin/publish.cmd +2 -0
- package/dist/component/CancellablePromise.d.ts +11 -0
- package/dist/component/EventManager.d.ts +12 -0
- package/dist/component/OAuthRestClient.d.ts +58 -0
- package/dist/component/OAuthSessionManager.d.ts +23 -0
- package/dist/component/OAuthSubject.d.ts +7 -0
- package/dist/component/RestClient.d.ts +24 -0
- package/dist/component/UserAlerts.d.ts +19 -0
- package/dist/component/index.d.ts +7 -0
- package/dist/index.d.ts +215 -0
- package/dist/index.esm.js +2 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/type/Paging.d.ts +17 -0
- package/dist/type/UserAlert.d.ts +6 -0
- package/dist/type/index.d.ts +2 -0
- package/dist/util/ArrayUtil.d.ts +5 -0
- package/dist/util/AsyncUtil.d.ts +3 -0
- package/dist/util/ByteUtil.d.ts +3 -0
- package/dist/util/ObjectUtil.d.ts +5 -0
- package/dist/util/StringUtil.d.ts +14 -0
- package/dist/util/index.d.ts +5 -0
- package/docker-compose.yml +24 -0
- package/package.json +26 -0
- package/rollup.config.mjs +41 -0
- package/src/component/CancellablePromise.ts +38 -0
- package/src/component/EventManager.ts +30 -0
- package/src/component/OAuthRestClient.ts +92 -0
- package/src/component/OAuthSessionManager.ts +143 -0
- package/src/component/OAuthSubject.ts +25 -0
- package/src/component/RestClient.ts +153 -0
- package/src/component/UserAlerts.ts +73 -0
- package/src/component/index.ts +7 -0
- package/src/index.ts +3 -0
- package/src/type/Paging.ts +21 -0
- package/src/type/UserAlert.ts +6 -0
- package/src/type/index.ts +3 -0
- package/src/util/ArrayUtil.ts +20 -0
- package/src/util/AsyncUtil.ts +3 -0
- package/src/util/ByteUtil.ts +11 -0
- package/src/util/ObjectUtil.ts +21 -0
- package/src/util/StringUtil.ts +65 -0
- package/src/util/index.ts +5 -0
- package/tsconfig.json +29 -0
@@ -0,0 +1,153 @@
|
|
1
|
+
import { StringUtil } from "../util";
|
2
|
+
import {PagingRequest, SortingField, SortingRequest} from "../type";
|
3
|
+
|
4
|
+
export type RestClientHeaders = {};
|
5
|
+
|
6
|
+
export class RestClient {
|
7
|
+
|
8
|
+
private baseUrl: string;
|
9
|
+
|
10
|
+
constructor(baseUrl: string) {
|
11
|
+
this.baseUrl = baseUrl;
|
12
|
+
}
|
13
|
+
|
14
|
+
static sortingFieldToString(s: SortingField): string | undefined {
|
15
|
+
return s.desc ? `${s.name} DESC` : s.name;
|
16
|
+
}
|
17
|
+
|
18
|
+
static sortingRequestToString(s: SortingRequest): string | undefined {
|
19
|
+
return s.map((s: SortingField) => RestClient.sortingFieldToString(s)).join(',');
|
20
|
+
}
|
21
|
+
|
22
|
+
static pagingRequestToQueryParams(pr: PagingRequest): any {
|
23
|
+
const result: any = {
|
24
|
+
page: pr.page,
|
25
|
+
size: pr.size
|
26
|
+
}
|
27
|
+
if (pr.search) {
|
28
|
+
result.search = pr.search;
|
29
|
+
}
|
30
|
+
if (pr.sorting) {
|
31
|
+
result.sorting = RestClient.sortingRequestToString(pr.sorting);
|
32
|
+
}
|
33
|
+
return result;
|
34
|
+
}
|
35
|
+
|
36
|
+
/**
|
37
|
+
* Override this to customize http headers.
|
38
|
+
*/
|
39
|
+
getHeaders(): Promise<RestClientHeaders> {
|
40
|
+
return Promise.resolve(
|
41
|
+
{
|
42
|
+
'Content-Type': 'application/json'
|
43
|
+
}
|
44
|
+
);
|
45
|
+
}
|
46
|
+
|
47
|
+
getUrl(endpoint: string) {
|
48
|
+
return [StringUtil.trimSlashes(this.baseUrl), StringUtil.trimSlashes(endpoint)].join('/');
|
49
|
+
}
|
50
|
+
|
51
|
+
getRequestOptions(method: string = 'GET', data: object | null = null): Promise<any> {
|
52
|
+
return this.getHeaders()
|
53
|
+
.then(
|
54
|
+
(headers) => {
|
55
|
+
return {
|
56
|
+
method: method,
|
57
|
+
headers: headers,
|
58
|
+
body: data === null ? null : JSON.stringify(data)
|
59
|
+
};
|
60
|
+
}
|
61
|
+
);
|
62
|
+
}
|
63
|
+
|
64
|
+
processRequest(endpoint: string, requestOptions?: object): Promise<Response> {
|
65
|
+
return fetch(this.getUrl(endpoint), requestOptions)
|
66
|
+
.then((response) => {
|
67
|
+
if (!response.ok) {
|
68
|
+
const options = {cause: response.status};
|
69
|
+
if (response.headers.get('Content-Type') === 'application/json') {
|
70
|
+
return response
|
71
|
+
.json()
|
72
|
+
.then((json) => {
|
73
|
+
if (json.message) {
|
74
|
+
// @ts-ignore
|
75
|
+
throw new Error(json.message, options);
|
76
|
+
}
|
77
|
+
if (json.error) {
|
78
|
+
// @ts-ignore
|
79
|
+
throw new Error(json.error, options);
|
80
|
+
}
|
81
|
+
// @ts-ignore
|
82
|
+
throw new Error(response.statusText, options);
|
83
|
+
}, () => {
|
84
|
+
// @ts-ignore
|
85
|
+
throw new Error(response.statusText, options);
|
86
|
+
});
|
87
|
+
} else {
|
88
|
+
return response.text().then(
|
89
|
+
(t) => {
|
90
|
+
if (StringUtil.isEmpty(t)) {
|
91
|
+
// @ts-ignore
|
92
|
+
throw new Error(response.statusText, options);
|
93
|
+
} else {
|
94
|
+
// @ts-ignore
|
95
|
+
throw new Error(t, options);
|
96
|
+
}
|
97
|
+
},
|
98
|
+
() => {
|
99
|
+
// @ts-ignore
|
100
|
+
throw new Error(response.statusText, options);
|
101
|
+
}
|
102
|
+
);
|
103
|
+
}
|
104
|
+
}
|
105
|
+
return response;
|
106
|
+
});
|
107
|
+
}
|
108
|
+
|
109
|
+
processRequestJson(url: string, requestOptions?: object | undefined): Promise<any> {
|
110
|
+
return this.processRequest(url, requestOptions)
|
111
|
+
.then((response) => {
|
112
|
+
return response.json();
|
113
|
+
});
|
114
|
+
}
|
115
|
+
|
116
|
+
getJson(url: string, params?: any): Promise<any> {
|
117
|
+
if (params) {
|
118
|
+
const original = new URLSearchParams(params);
|
119
|
+
const cleaned = new URLSearchParams();
|
120
|
+
original.forEach((value, key) => {
|
121
|
+
if (value !== '' && value !== undefined && value !== "undefined")
|
122
|
+
cleaned.set(key, value);
|
123
|
+
});
|
124
|
+
url = `${url}?${cleaned.toString()}`;
|
125
|
+
}
|
126
|
+
return this.getRequestOptions().then(o => this.processRequestJson(url, o));
|
127
|
+
}
|
128
|
+
|
129
|
+
postJson(url: string, data: object | null = null): Promise<any> {
|
130
|
+
return this.getRequestOptions('POST', data).then(o => this.processRequestJson(url, o));
|
131
|
+
}
|
132
|
+
|
133
|
+
putJson(url: string, data: object | null = null): Promise<any> {
|
134
|
+
return this.getRequestOptions('PUT', data).then(o => this.processRequestJson(url, o));
|
135
|
+
}
|
136
|
+
|
137
|
+
get(url: string): Promise<Response> {
|
138
|
+
return this.getRequestOptions().then(o => this.processRequest(url, o));
|
139
|
+
}
|
140
|
+
|
141
|
+
del(url: string): Promise<Response> {
|
142
|
+
return this.getRequestOptions('DELETE').then(o => this.processRequest(url, o));
|
143
|
+
}
|
144
|
+
|
145
|
+
post(url: string, data: object | null = null): Promise<Response> {
|
146
|
+
return this.getRequestOptions('POST', data).then(o => this.processRequest(url, o));
|
147
|
+
}
|
148
|
+
|
149
|
+
put(url: string, data: object | null = null): Promise<Response> {
|
150
|
+
return this.getRequestOptions('PUT', data).then(o => this.processRequest(url, o));
|
151
|
+
}
|
152
|
+
|
153
|
+
}
|
@@ -0,0 +1,73 @@
|
|
1
|
+
import {UserAlert} from "../type";
|
2
|
+
import {EventManager, Func} from "./EventManager";
|
3
|
+
|
4
|
+
export class UserAlerts {
|
5
|
+
|
6
|
+
private lifetimeMs: number = 10000;
|
7
|
+
|
8
|
+
private em: EventManager;
|
9
|
+
|
10
|
+
public alerts: Array<UserAlert>;
|
11
|
+
|
12
|
+
constructor() {
|
13
|
+
this.em = new EventManager();
|
14
|
+
this.alerts = [];
|
15
|
+
setInterval(() => this.flushAlerts(), 1000)
|
16
|
+
}
|
17
|
+
|
18
|
+
flushAlerts() {
|
19
|
+
const now = new Date();
|
20
|
+
const threshold = now.getTime() - this.lifetimeMs;
|
21
|
+
this.alerts = this.alerts.filter((a) => a.time.getTime() > threshold);
|
22
|
+
this.triggerChange();
|
23
|
+
}
|
24
|
+
|
25
|
+
addOnChangeHandler(h: Func) {
|
26
|
+
this.em.addEventListener('change', h);
|
27
|
+
}
|
28
|
+
|
29
|
+
removeOnChangeHandler(h: Func) {
|
30
|
+
this.em.removeEventListener('change', h);
|
31
|
+
}
|
32
|
+
|
33
|
+
triggerChange() {
|
34
|
+
this.em.triggerEvent('change');
|
35
|
+
}
|
36
|
+
|
37
|
+
reset() {
|
38
|
+
this.alerts = [];
|
39
|
+
this.triggerChange();
|
40
|
+
}
|
41
|
+
|
42
|
+
remove(alert: UserAlert) {
|
43
|
+
this.alerts.splice(this.alerts.indexOf(alert), 1);
|
44
|
+
this.triggerChange();
|
45
|
+
};
|
46
|
+
|
47
|
+
add(alert: UserAlert) {
|
48
|
+
this.alerts.push(alert);
|
49
|
+
this.triggerChange();
|
50
|
+
}
|
51
|
+
|
52
|
+
custom(type: string, title: string, message: string) {
|
53
|
+
this.add({
|
54
|
+
time: new Date(),
|
55
|
+
type: type,
|
56
|
+
title: title,
|
57
|
+
message: message
|
58
|
+
});
|
59
|
+
}
|
60
|
+
|
61
|
+
err(message: string) {
|
62
|
+
this.custom('danger', 'Error', message);
|
63
|
+
}
|
64
|
+
|
65
|
+
warn(message: string) {
|
66
|
+
this.custom('warning', 'Warning', message);
|
67
|
+
}
|
68
|
+
|
69
|
+
info(message: string) {
|
70
|
+
this.custom('info', 'Warning', message);
|
71
|
+
}
|
72
|
+
|
73
|
+
}
|
package/src/index.ts
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
export type SortingField = {
|
2
|
+
name: string;
|
3
|
+
desc?: boolean;
|
4
|
+
};
|
5
|
+
|
6
|
+
export type SortingRequest = Array<SortingField>;
|
7
|
+
|
8
|
+
export type PagingRequest = {
|
9
|
+
page: number;
|
10
|
+
size: number;
|
11
|
+
search?: string | null;
|
12
|
+
sorting: SortingRequest;
|
13
|
+
};
|
14
|
+
|
15
|
+
export type Page<Type> = {
|
16
|
+
totalPages: number;
|
17
|
+
totalElements: number;
|
18
|
+
number: number;
|
19
|
+
content: Array<Type>;
|
20
|
+
};
|
21
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { ObjectUtil } from "./ObjectUtil";
|
2
|
+
|
3
|
+
export class ArrayUtil {
|
4
|
+
|
5
|
+
static isEmpty(arr?: Array<any> | null): boolean {
|
6
|
+
// @ts-ignore
|
7
|
+
return ObjectUtil.isEmpty(arr) || arr.length === 0;
|
8
|
+
}
|
9
|
+
|
10
|
+
static notEmpty(arr?: Array<any> | null): boolean {
|
11
|
+
return !ArrayUtil.isEmpty(arr);
|
12
|
+
}
|
13
|
+
|
14
|
+
static remove(arr?: Array<any> | null, element?: any): Array<any> {
|
15
|
+
if (ArrayUtil.isEmpty(arr)) return [];
|
16
|
+
// @ts-ignore
|
17
|
+
return arr?.filter(e => e !== element);
|
18
|
+
}
|
19
|
+
|
20
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
export class ByteUtil {
|
2
|
+
|
3
|
+
static formatByteSize(size?: number | null): string {
|
4
|
+
const n = Number(size);
|
5
|
+
if (n === null || Number.isNaN(n)) return '';
|
6
|
+
if (n === 0) return '0';
|
7
|
+
const l = Math.floor(Math.log(n) / Math.log(1024));
|
8
|
+
return +((n / Math.pow(1024, l)).toFixed(2)) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][l];
|
9
|
+
}
|
10
|
+
|
11
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
export class ObjectUtil {
|
2
|
+
|
3
|
+
static isEmpty(obj: any) {
|
4
|
+
return obj === undefined || obj === null;
|
5
|
+
}
|
6
|
+
|
7
|
+
static notEmpty(obj: any) {
|
8
|
+
return !ObjectUtil.isEmpty(obj);
|
9
|
+
}
|
10
|
+
|
11
|
+
static clone<T>(obj: T): T {
|
12
|
+
if (obj === null) {
|
13
|
+
throw new Error("Null cannot be cloned!");
|
14
|
+
}
|
15
|
+
if (typeof obj !== 'object') {
|
16
|
+
throw new Error("Not an object, cannot be cloned!");
|
17
|
+
}
|
18
|
+
return {...obj};
|
19
|
+
}
|
20
|
+
|
21
|
+
}
|
@@ -0,0 +1,65 @@
|
|
1
|
+
import { ObjectUtil } from "./ObjectUtil";
|
2
|
+
|
3
|
+
export class StringUtil extends ObjectUtil {
|
4
|
+
|
5
|
+
static isEmpty(str: string | null | undefined): boolean {
|
6
|
+
return ObjectUtil.isEmpty(str) || str?.trim().length === 0;
|
7
|
+
}
|
8
|
+
|
9
|
+
static notEmpty(str: string | null | undefined): boolean {
|
10
|
+
return !StringUtil.isEmpty(str);
|
11
|
+
}
|
12
|
+
|
13
|
+
static substr(str: string | null | undefined, start: number, length?: number): string {
|
14
|
+
if (this.isEmpty(str)) return '';
|
15
|
+
|
16
|
+
// @ts-ignore
|
17
|
+
return str.substring(start, length);
|
18
|
+
}
|
19
|
+
|
20
|
+
static replace(str: string | null | undefined, find?: null | string, replace?: string): string {
|
21
|
+
if (this.isEmpty(str) || this.isEmpty(find)) return '';
|
22
|
+
|
23
|
+
// @ts-ignore
|
24
|
+
return str.replace(find, String(replace));
|
25
|
+
}
|
26
|
+
|
27
|
+
static containsLineBreaks(str: string | null | undefined): boolean {
|
28
|
+
if (str === null || str === undefined || str.trim().length === 0) return false;
|
29
|
+
return str.includes("\n");
|
30
|
+
}
|
31
|
+
|
32
|
+
static trimSlashes(str: string | null): string {
|
33
|
+
if (this.isEmpty(str)) return '';
|
34
|
+
|
35
|
+
// @ts-ignore
|
36
|
+
return str.replace(/^\/|\/$/g, '');
|
37
|
+
}
|
38
|
+
|
39
|
+
static safeTruncate(str: string | null | undefined, len: number, ellipsis: string = ''): string {
|
40
|
+
if (StringUtil.isEmpty(str) || !str) return '';
|
41
|
+
if (str.length <= len) return String(str);
|
42
|
+
return str.substring(0, len - ellipsis.length) + ellipsis;
|
43
|
+
}
|
44
|
+
|
45
|
+
static ellipsis(str: string | null | undefined, len: number, ellipsis: string = '...'): string {
|
46
|
+
return StringUtil.safeTruncate(str, len, ellipsis);
|
47
|
+
}
|
48
|
+
|
49
|
+
static safeTrim(str: string | null | undefined): string {
|
50
|
+
if (StringUtil.isEmpty(str) || !str) return '';
|
51
|
+
return str.trim();
|
52
|
+
}
|
53
|
+
|
54
|
+
static toBigInt(str: string | null): bigint | null {
|
55
|
+
if (this.isEmpty(str)) return null;
|
56
|
+
|
57
|
+
// @ts-ignore
|
58
|
+
return BigInt(str);
|
59
|
+
}
|
60
|
+
|
61
|
+
static getNonEmpty(...args: Array<string | null | undefined>): string {
|
62
|
+
return args.find(a => StringUtil.notEmpty(a)) || "";
|
63
|
+
}
|
64
|
+
|
65
|
+
}
|
package/tsconfig.json
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
{
|
2
|
+
"compilerOptions": {
|
3
|
+
"moduleResolution": "node",
|
4
|
+
"target": "es5",
|
5
|
+
"module": "ESNext",
|
6
|
+
"lib": [
|
7
|
+
"es6",
|
8
|
+
"dom",
|
9
|
+
"es2020.bigint"
|
10
|
+
],
|
11
|
+
"outDir": "./dist",
|
12
|
+
"rootDir": "./src",
|
13
|
+
"declaration": true,
|
14
|
+
"strict": true,
|
15
|
+
"esModuleInterop": true,
|
16
|
+
"skipLibCheck": true
|
17
|
+
},
|
18
|
+
"include": [
|
19
|
+
"src",
|
20
|
+
"*.tsx",
|
21
|
+
"*.ts"
|
22
|
+
],
|
23
|
+
"exclude": [
|
24
|
+
"node_modules/**",
|
25
|
+
"dist",
|
26
|
+
"docker-compose.yml",
|
27
|
+
".env-example"
|
28
|
+
]
|
29
|
+
}
|