@verisoft/core 17.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/.eslintrc.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "extends": ["../../../.eslintrc.base.json"],
3
+ "ignorePatterns": ["!**/*"],
4
+ "overrides": [
5
+ {
6
+ "files": ["*.ts"],
7
+ "extends": [
8
+ "plugin:@nx/angular",
9
+ "plugin:@angular-eslint/template/process-inline-templates"
10
+ ],
11
+ "rules": {
12
+ "@angular-eslint/directive-selector": [
13
+ "error",
14
+ {
15
+ "type": "attribute",
16
+ "prefix": "v",
17
+ "style": "camelCase"
18
+ }
19
+ ],
20
+ "@angular-eslint/component-selector": [
21
+ "error",
22
+ {
23
+ "type": "element",
24
+ "prefix": "v",
25
+ "style": "kebab-case"
26
+ }
27
+ ]
28
+ }
29
+ },
30
+ {
31
+ "files": ["*.html"],
32
+ "extends": ["plugin:@nx/angular-template"],
33
+ "rules": {}
34
+ },
35
+ {
36
+ "files": ["*.json"],
37
+ "parser": "jsonc-eslint-parser",
38
+ "rules": {
39
+ "@nx/dependency-checks": "error"
40
+ }
41
+ }
42
+ ]
43
+ }
package/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # core
2
+
3
+ This library was generated with [Nx](https://nx.dev).
4
+
5
+ ## Running unit tests
6
+
7
+ Run `nx test core` to execute the unit tests.
package/jest.config.ts ADDED
@@ -0,0 +1,22 @@
1
+ /* eslint-disable */
2
+ export default {
3
+ displayName: 'core',
4
+ preset: '../../../jest.preset.js',
5
+ setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
6
+ coverageDirectory: '../../../coverage/src/libs/core',
7
+ transform: {
8
+ '^.+\\.(ts|mjs|js|html)$': [
9
+ 'jest-preset-angular',
10
+ {
11
+ tsconfig: '<rootDir>/tsconfig.spec.json',
12
+ stringifyContentPathRegex: '\\.(html|svg)$',
13
+ },
14
+ ],
15
+ },
16
+ transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
17
+ snapshotSerializers: [
18
+ 'jest-preset-angular/build/serializers/no-ng-attributes',
19
+ 'jest-preset-angular/build/serializers/ng-snapshot',
20
+ 'jest-preset-angular/build/serializers/html-comment',
21
+ ],
22
+ };
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "dest": "../../../dist/src/libs/core",
4
+ "lib": {
5
+ "entryFile": "src/index.ts"
6
+ }
7
+ }
package/package.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "@verisoft/core",
3
+ "version": "17.0.0",
4
+ "peerDependencies": {
5
+ "@angular/common": "^17.3.0",
6
+ "@angular/core": "^17.3.0",
7
+ "rxjs": "~7.8.0"
8
+ },
9
+ "dependencies": {},
10
+ "sideEffects": false
11
+ }
package/project.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "core",
3
+ "$schema": "../../../node_modules/nx/schemas/project-schema.json",
4
+ "sourceRoot": "src/libs/core/src",
5
+ "prefix": "lib",
6
+ "projectType": "library",
7
+ "tags": [],
8
+ "targets": {
9
+ "build": {
10
+ "executor": "@nx/angular:package",
11
+ "outputs": ["{workspaceRoot}/dist/{projectRoot}"],
12
+ "options": {
13
+ "project": "src/libs/core/ng-package.json"
14
+ },
15
+ "configurations": {
16
+ "production": {
17
+ "tsConfig": "src/libs/core/tsconfig.lib.prod.json"
18
+ },
19
+ "development": {
20
+ "tsConfig": "src/libs/core/tsconfig.lib.json"
21
+ }
22
+ },
23
+ "defaultConfiguration": "production"
24
+ },
25
+ "test": {
26
+ "executor": "@nx/jest:jest",
27
+ "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
28
+ "options": {
29
+ "jestConfig": "src/libs/core/jest.config.ts"
30
+ }
31
+ },
32
+ "lint": {
33
+ "executor": "@nx/eslint:lint"
34
+ }
35
+ }
36
+ }
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export * from './lib/base/models/base-http.models';
2
+ export * from './lib/base/models/all-item.datasource';
3
+ export * from './lib/models/lazy-load.model';
4
+
5
+ export * from './lib/services/base-http.service';
6
+
7
+ export * from './lib/utils/clear.utils';
8
+ export * from './lib/utils/keyOrFn.utils';
@@ -0,0 +1,5 @@
1
+ import { Observable } from 'rxjs';
2
+
3
+ export interface AllItemDatasource<T> {
4
+ getData$: () => Observable<T[]>
5
+ }
@@ -0,0 +1,96 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { HttpParams, HttpResponse } from '@angular/common/http';
3
+ import { InjectionToken } from '@angular/core';
4
+
5
+ export const BASE_URL_PATH = new InjectionToken("BASE_URL_PATH");
6
+
7
+ export function requestParamsToHttpParams<T>(
8
+ requestParams: RequestParams<T>,
9
+ httpParams: HttpParams = new HttpParams()
10
+ ): HttpParams {
11
+ httpParams = httpParams
12
+ .append('Limit', requestParams.size.toString())
13
+ .append('Offset', (requestParams.page * requestParams.size).toString());
14
+ if (requestParams.id != '' && requestParams.id != undefined) {
15
+ httpParams = httpParams.append('Id', requestParams.id as any);
16
+ }
17
+
18
+ httpParams = getFilter(requestParams, httpParams);
19
+ httpParams = getSort(requestParams, httpParams);
20
+
21
+ return httpParams;
22
+ }
23
+
24
+ function getFilter<T>(
25
+ requestParams: RequestParams<any>,
26
+ httpParams: HttpParams
27
+ ): HttpParams {
28
+ if (!requestParams.filter) {
29
+ return httpParams;
30
+ }
31
+ Object.keys(requestParams?.filter).forEach((key) => {
32
+ if (requestParams.filter?.[key as keyof Partial<T>]) {
33
+ httpParams = httpParams.append(
34
+ 'Filter.' + key,
35
+ requestParams.filter?.[key as keyof Partial<T>]
36
+ );
37
+ }
38
+ });
39
+ return httpParams;
40
+ }
41
+
42
+ function getSort(
43
+ requestParams: RequestParams<any>,
44
+ httpParams: HttpParams
45
+ ): HttpParams {
46
+ if (!requestParams.sort) {
47
+ return httpParams;
48
+ }
49
+
50
+ requestParams.sort?.forEach((sort) => {
51
+ httpParams = httpParams
52
+ .append('Sort.Field', sort.field)
53
+ .append('Sort.Direction', sort.direction === -1 ? 'Desc' : 'Asc');
54
+ });
55
+ return httpParams;
56
+ }
57
+
58
+ export function saveFile(response: HttpResponse<Blob>) {
59
+ const fileName = response.headers
60
+ .get('Content-Disposition')
61
+ ?.split(';')[1]
62
+ .split('=')[1];
63
+ const blob: Blob = response.body as Blob;
64
+ const a = document.createElement('a');
65
+ a.download = fileName ?? 'undefined';
66
+ a.href = window.URL.createObjectURL(blob);
67
+ a.click();
68
+ }
69
+
70
+ export declare interface Sort<T> {
71
+ field: string;
72
+ direction: number;
73
+ }
74
+
75
+ export interface RequestParams<T> {
76
+ page: number;
77
+ size: number;
78
+ id?: string;
79
+ filter?: Partial<T>;
80
+ sort?: Sort<T>[];
81
+ }
82
+
83
+ export interface Page<T> {
84
+ data: T[];
85
+ total: number;
86
+ size: number;
87
+ number: number;
88
+ }
89
+
90
+ export const DEFAULT_SEARCH_LIMIT = 50;
91
+
92
+ export const DEFAULT_SEARCH_PARAMS: RequestParams<any> = {
93
+ page: 0,
94
+ size: DEFAULT_SEARCH_LIMIT,
95
+ id: '',
96
+ };
@@ -0,0 +1,9 @@
1
+ import { RequestParams } from "./base-http.models";
2
+
3
+ export const DEFAULT_SEARCH_LIMIT = 50;
4
+
5
+ export const DEFAULT_SEARCH_PARAMS: RequestParams<any> = {
6
+ page: 0,
7
+ size: DEFAULT_SEARCH_LIMIT,
8
+ id: '',
9
+ };
@@ -0,0 +1,4 @@
1
+ export interface LazyLoad {
2
+ offset: number;
3
+ limit: number;
4
+ }
@@ -0,0 +1,104 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { HttpClient } from '@angular/common/http';
3
+ import { Inject, Injectable } from '@angular/core';
4
+ import { map, Observable } from 'rxjs';
5
+ import {
6
+ BASE_URL_PATH,
7
+ Page,
8
+ RequestParams,
9
+ requestParamsToHttpParams,
10
+ } from '../base/models/base-http.models';
11
+ import { DEFAULT_SEARCH_PARAMS } from '../base/models/table-datasource.models';
12
+ import { LazyLoad } from '../models/lazy-load.model';
13
+ import { ClearUtils } from '../utils/clear.utils';
14
+
15
+ @Injectable({ providedIn: 'root' })
16
+ export abstract class BaseHttpService<T, TKey = number> {
17
+ basePath = '';
18
+ entityName!: string;
19
+ constructor(
20
+ readonly http: HttpClient,
21
+ @Inject(BASE_URL_PATH) basePath: string
22
+ ) {
23
+ this.basePath = basePath;
24
+ }
25
+ fetchList(requestParams: RequestParams<T>): Observable<Page<T>> {
26
+ const params = requestParamsToHttpParams<T>(requestParams);
27
+ return this.http
28
+ .get<Page<T>>(this.basePath + this.entityName, { params })
29
+ .pipe(
30
+ map((response: Page<T>) => {
31
+ response.size = requestParams.size;
32
+ return response;
33
+ })
34
+ );
35
+ }
36
+
37
+ getData$(
38
+ entityName: keyof T,
39
+ searchTerm?: string | undefined,
40
+ lazyLoad?: LazyLoad
41
+ ): Observable<T[]> {
42
+ const filter: Partial<T> = { [entityName]: searchTerm } as Partial<T>;
43
+ const params = lazyLoad
44
+ ? requestParamsToHttpParams<T>({
45
+ ...DEFAULT_SEARCH_PARAMS,
46
+ page: Math.round(lazyLoad.offset / lazyLoad.limit),
47
+ size: lazyLoad.limit,
48
+ filter,
49
+ })
50
+ : requestParamsToHttpParams<T>({
51
+ ...DEFAULT_SEARCH_PARAMS,
52
+ filter,
53
+ });
54
+
55
+ return this.http.get<T[]>(this.basePath + this.entityName, { params });
56
+ }
57
+
58
+ get(id: TKey, url?: string): Observable<T> {
59
+ const newUrl = url ? `/${url}/${id}` : `/${id}`;
60
+ return this.http.get<T>(newUrl);
61
+ }
62
+
63
+ post(entity: Partial<T>, url?: string): Observable<T> {
64
+ const newUrl = url ? this.basePath + `/${url}` : this.basePath;
65
+ return this.http.post<T>(newUrl, entity);
66
+ }
67
+
68
+ put(id: TKey, entity: Partial<T>, url?: string): Observable<T> {
69
+ const newUrl = this.basePath + (url ? `/${url}/${id}` : `/${id}`);
70
+ return this.http.put<T>(newUrl, entity);
71
+ }
72
+
73
+ removeRange(entity: string[]) {
74
+ return this.http.delete(this.basePath + this.entityName, {
75
+ body: entity,
76
+ });
77
+ }
78
+
79
+ createParams<T>(requestParams: RequestParams<T>): any {
80
+ const sorter = this.createSorter(requestParams);
81
+ const filter = JSON.parse(JSON.stringify(requestParams.filter));
82
+ const transformedFilter = filter;
83
+ ClearUtils.recursiveObjectAttributesDeletation(transformedFilter);
84
+ return {
85
+ paging: {
86
+ page: requestParams.page,
87
+ size: requestParams.size,
88
+ },
89
+ ...(sorter && { sorting: sorter }),
90
+ ...(transformedFilter && { filter: transformedFilter }),
91
+ };
92
+ }
93
+
94
+ private createSorter<T>(requestParams: RequestParams<T>) {
95
+ if (requestParams?.sort?.length === 1) {
96
+ const sorter = requestParams.sort[0];
97
+ return {
98
+ sortField: sorter.field,
99
+ sortOrder: sorter.direction,
100
+ };
101
+ }
102
+ return null;
103
+ }
104
+ }
@@ -0,0 +1,53 @@
1
+ export class ClearUtils {
2
+
3
+ static recursiveObjectAttributesTransformation(obj: any): void {
4
+ ClearUtils.recursiveObjectAttributesTraversal(
5
+ obj,
6
+ ClearUtils.transformEmptyStringToNullStringFn
7
+ );
8
+ }
9
+ static recursiveObjectAttributesDeletation(obj: any): void {
10
+ ClearUtils.recursiveObjectAttributesTraversal(
11
+ obj,
12
+ ClearUtils.deleteEmptyStringToNullStringFn
13
+ );
14
+ }
15
+
16
+ static transformEmptyStringToNullStringFn(obj: any, key: string) {
17
+ if (typeof obj[key] === 'string' && obj[key] === '') {
18
+ obj[key] = null;
19
+ }
20
+ }
21
+ static deleteEmptyStringToNullStringFn(obj: any, key: string) {
22
+ if (obj[key] === '' || obj[key] === null || obj[key] === undefined) {
23
+ delete obj[key]
24
+ }
25
+ }
26
+
27
+
28
+ static recursiveObjectAttributesTraversal(
29
+ obj: any,
30
+ transformationFn: (obj: any, key: string) => void
31
+ ) {
32
+ if (
33
+ obj === null ||
34
+ transformationFn === null ||
35
+ typeof transformationFn !== 'function'
36
+ ) {
37
+ return;
38
+ }
39
+
40
+ Object.keys(obj).forEach((key) => {
41
+ transformationFn(obj, key);
42
+
43
+ if (typeof obj[key] === 'object') {
44
+ this.recursiveObjectAttributesTraversal(obj[key], transformationFn);
45
+
46
+ if (!Object.keys(obj[key]).length) {
47
+ delete obj[key];
48
+ }
49
+ }
50
+ });
51
+ }
52
+
53
+ }
@@ -0,0 +1,15 @@
1
+ export function keyOrFn(keyOrFn: ((row: any) => string | undefined) | string, row: any){
2
+ if (keyOrFn instanceof Function) {
3
+ return keyOrFn(row);
4
+ }
5
+ else if (typeof keyOrFn === 'string') {
6
+ const value = row[keyOrFn];
7
+ if (value){
8
+ return value;
9
+ }
10
+ }
11
+ else if (typeof keyOrFn === 'boolean') {
12
+ return keyOrFn;
13
+ }
14
+ return '';
15
+ }
@@ -0,0 +1,8 @@
1
+ // @ts-expect-error https://thymikee.github.io/jest-preset-angular/docs/getting-started/test-environment
2
+ globalThis.ngJest = {
3
+ testEnvironmentOptions: {
4
+ errorOnUnknownElements: true,
5
+ errorOnUnknownProperties: true,
6
+ },
7
+ };
8
+ import 'jest-preset-angular/setup-jest';
package/tsconfig.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2022",
4
+ "useDefineForClassFields": false,
5
+ "forceConsistentCasingInFileNames": true,
6
+ "strict": true,
7
+ "noImplicitOverride": true,
8
+ "noPropertyAccessFromIndexSignature": true,
9
+ "noImplicitReturns": true,
10
+ "noFallthroughCasesInSwitch": true
11
+ },
12
+ "files": [],
13
+ "include": [],
14
+ "references": [
15
+ {
16
+ "path": "./tsconfig.lib.json"
17
+ },
18
+ {
19
+ "path": "./tsconfig.spec.json"
20
+ }
21
+ ],
22
+ "extends": "../../../tsconfig.base.json",
23
+ "angularCompilerOptions": {
24
+ "enableI18nLegacyMessageIdFormat": false,
25
+ "strictInjectionParameters": true,
26
+ "strictInputAccessModifiers": true,
27
+ "strictTemplates": true
28
+ }
29
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../../dist/out-tsc",
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "inlineSources": true,
8
+ "types": []
9
+ },
10
+ "exclude": [
11
+ "src/**/*.spec.ts",
12
+ "src/test-setup.ts",
13
+ "jest.config.ts",
14
+ "src/**/*.test.ts"
15
+ ],
16
+ "include": ["src/**/*.ts"]
17
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "./tsconfig.lib.json",
3
+ "compilerOptions": {
4
+ "declarationMap": false
5
+ },
6
+ "angularCompilerOptions": {
7
+ "compilationMode": "partial"
8
+ }
9
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../../dist/out-tsc",
5
+ "module": "commonjs",
6
+ "target": "es2016",
7
+ "types": ["jest", "node"]
8
+ },
9
+ "files": ["src/test-setup.ts"],
10
+ "include": [
11
+ "jest.config.ts",
12
+ "src/**/*.test.ts",
13
+ "src/**/*.spec.ts",
14
+ "src/**/*.d.ts"
15
+ ]
16
+ }