ngx-material-entity 15.1.2 → 15.1.4

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.
Files changed (107) hide show
  1. package/README.md +100 -0
  2. package/components/confirm-dialog/confirm-dialog.component.d.ts +1 -1
  3. package/components/edit-page/edit-page.component.d.ts +112 -0
  4. package/components/edit-page/page-edit-data.builder.d.ts +17 -0
  5. package/components/input/array/array-date-input/array-date-input.component.d.ts +1 -1
  6. package/components/input/array/array-date-range-input/array-date-range-input.component.d.ts +1 -1
  7. package/components/input/array/array-date-time-input/array-date-time-input.component.d.ts +1 -1
  8. package/components/input/array/array-table.class.d.ts +1 -1
  9. package/components/input/date/date-input/date-input.component.d.ts +1 -1
  10. package/components/input/date/date-time-input/date-time-input.component.d.ts +2 -2
  11. package/components/input/file/file-default-input/file-default-input.component.d.ts +1 -1
  12. package/components/input/file/file-image-input/file-image-input.component.d.ts +1 -1
  13. package/components/input/file/file-input/file-input.component.d.ts +3 -3
  14. package/components/input/input.component.d.ts +3 -3
  15. package/components/input/relations/references-many-input/references-many-input.component.d.ts +1 -1
  16. package/components/input/string/string-password-input/string-password-input.component.d.ts +1 -1
  17. package/components/table/create-dialog/create-entity-dialog-data.builder.d.ts +3 -3
  18. package/components/table/create-dialog/create-entity-dialog-data.d.ts +1 -1
  19. package/components/table/create-dialog/create-entity-dialog.component.d.ts +4 -4
  20. package/components/table/edit-dialog/{edit-dialog-data.builder.d.ts → edit-data.builder.d.ts} +7 -7
  21. package/components/table/edit-dialog/{edit-entity-dialog-data.d.ts → edit-entity-data.d.ts} +5 -5
  22. package/components/table/edit-dialog/edit-entity-dialog.component.d.ts +6 -6
  23. package/components/table/edit-dialog/edit-entity.builder.d.ts +24 -0
  24. package/components/table/table-data.builder.d.ts +9 -7
  25. package/components/table/table-data.d.ts +18 -8
  26. package/components/table/table.component.d.ts +11 -7
  27. package/components/table/table.module.d.ts +4 -3
  28. package/decorators/boolean/boolean-decorator.data.d.ts +6 -2
  29. package/decorators/date/date-decorator-internal.data.d.ts +1 -1
  30. package/decorators/date/date-decorator.data.d.ts +1 -1
  31. package/decorators/number/number-decorator-internal.data.d.ts +1 -1
  32. package/decorators/number/number-decorator.data.d.ts +1 -1
  33. package/decorators/string/string-decorator-internal.data.d.ts +1 -1
  34. package/decorators/string/string-decorator.data.d.ts +1 -1
  35. package/esm2020/classes/entity.model.mjs +2 -2
  36. package/esm2020/components/confirm-dialog/confirm-dialog.component.mjs +4 -4
  37. package/esm2020/components/edit-page/edit-page.component.mjs +203 -0
  38. package/esm2020/components/edit-page/page-edit-data.builder.mjs +32 -0
  39. package/esm2020/components/input/array/array-date-input/array-date-input.component.mjs +4 -4
  40. package/esm2020/components/input/array/array-date-range-input/array-date-range-input.component.mjs +4 -4
  41. package/esm2020/components/input/array/array-date-time-input/array-date-time-input.component.mjs +4 -4
  42. package/esm2020/components/input/array/array-table.class.mjs +3 -3
  43. package/esm2020/components/input/base-input.component.mjs +2 -2
  44. package/esm2020/components/input/boolean/boolean-dropdown-input/boolean-dropdown-input.component.mjs +3 -3
  45. package/esm2020/components/input/date/date-input/date-input.component.mjs +2 -2
  46. package/esm2020/components/input/date/date-range-input/date-range-input.component.mjs +5 -5
  47. package/esm2020/components/input/date/date-time-input/date-time-input.component.mjs +5 -5
  48. package/esm2020/components/input/file/file-default-input/file-default-input.component.mjs +2 -2
  49. package/esm2020/components/input/file/file-image-input/file-image-input.component.mjs +3 -3
  50. package/esm2020/components/input/file/file-input/file-input.component.mjs +5 -5
  51. package/esm2020/components/input/input.component.mjs +6 -6
  52. package/esm2020/components/input/number/number-dropdown-input/number-dropdown-input.component.mjs +3 -3
  53. package/esm2020/components/input/relations/references-many-input/references-many-input.component.mjs +4 -4
  54. package/esm2020/components/input/string/string-dropdown-input/string-dropdown-input.component.mjs +3 -3
  55. package/esm2020/components/input/string/string-password-input/string-password-input.component.mjs +4 -4
  56. package/esm2020/components/table/create-dialog/create-entity-dialog-data.builder.mjs +2 -2
  57. package/esm2020/components/table/create-dialog/create-entity-dialog-data.mjs +1 -1
  58. package/esm2020/components/table/create-dialog/create-entity-dialog.component.mjs +5 -5
  59. package/esm2020/components/table/edit-dialog/edit-data.builder.mjs +41 -0
  60. package/esm2020/components/table/edit-dialog/edit-entity-data.mjs +2 -0
  61. package/esm2020/components/table/edit-dialog/edit-entity-dialog.component.mjs +16 -16
  62. package/esm2020/components/table/edit-dialog/edit-entity.builder.mjs +28 -0
  63. package/esm2020/components/table/table-data.builder.mjs +11 -8
  64. package/esm2020/components/table/table-data.mjs +1 -1
  65. package/esm2020/components/table/table.component.mjs +42 -29
  66. package/esm2020/components/table/table.module.mjs +5 -1
  67. package/esm2020/decorators/array/array-decorator-internal.data.mjs +2 -2
  68. package/esm2020/decorators/base/base-property.decorator.mjs +2 -2
  69. package/esm2020/decorators/boolean/boolean-decorator-internal.data.mjs +3 -3
  70. package/esm2020/decorators/boolean/boolean-decorator.data.mjs +1 -1
  71. package/esm2020/decorators/date/date-decorator-internal.data.mjs +2 -2
  72. package/esm2020/decorators/date/date-decorator.data.mjs +1 -1
  73. package/esm2020/decorators/date/date.decorator.mjs +2 -2
  74. package/esm2020/decorators/file/file.decorator.mjs +2 -2
  75. package/esm2020/decorators/number/number-decorator-internal.data.mjs +1 -1
  76. package/esm2020/decorators/number/number-decorator.data.mjs +1 -1
  77. package/esm2020/decorators/string/string-decorator-internal.data.mjs +1 -1
  78. package/esm2020/decorators/string/string-decorator.data.mjs +1 -1
  79. package/esm2020/decorators/string/string.decorator.mjs +2 -2
  80. package/esm2020/public-api.mjs +30 -26
  81. package/esm2020/services/entity.service.mjs +236 -0
  82. package/esm2020/services/unsaved-changes.guard.mjs +14 -0
  83. package/esm2020/utilities/date.utilities.mjs +158 -0
  84. package/esm2020/utilities/entity.utilities.mjs +828 -0
  85. package/esm2020/utilities/file.utilities.mjs +163 -0
  86. package/esm2020/utilities/selection.utilities.mjs +50 -0
  87. package/fesm2015/ngx-material-entity.mjs +898 -624
  88. package/fesm2015/ngx-material-entity.mjs.map +1 -1
  89. package/fesm2020/ngx-material-entity.mjs +870 -603
  90. package/fesm2020/ngx-material-entity.mjs.map +1 -1
  91. package/package.json +1 -1
  92. package/public-api.d.ts +27 -25
  93. package/{classes → services}/entity.service.d.ts +18 -1
  94. package/services/unsaved-changes.guard.d.ts +4 -0
  95. package/{classes → utilities}/date.utilities.d.ts +1 -1
  96. package/{classes → utilities}/entity.utilities.d.ts +1 -1
  97. package/components/table/edit-dialog/edit-entity-dialog.builder.d.ts +0 -24
  98. package/esm2020/classes/date.utilities.mjs +0 -158
  99. package/esm2020/classes/entity.service.mjs +0 -213
  100. package/esm2020/classes/entity.utilities.mjs +0 -824
  101. package/esm2020/classes/file.utilities.mjs +0 -163
  102. package/esm2020/classes/selection.utilities.mjs +0 -50
  103. package/esm2020/components/table/edit-dialog/edit-dialog-data.builder.mjs +0 -41
  104. package/esm2020/components/table/edit-dialog/edit-entity-dialog-data.mjs +0 -2
  105. package/esm2020/components/table/edit-dialog/edit-entity-dialog.builder.mjs +0 -28
  106. /package/{classes → utilities}/file.utilities.d.ts +0 -0
  107. /package/{classes → utilities}/selection.utilities.d.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ngx-material-entity",
3
- "version": "15.1.2",
3
+ "version": "15.1.4",
4
4
  "license": "MIT",
5
5
  "keywords": [
6
6
  "angular",
package/public-api.d.ts CHANGED
@@ -3,44 +3,46 @@
3
3
  */
4
4
  import 'reflect-metadata';
5
5
  export * from './classes/entity.model';
6
- export * from './classes/entity.service';
7
- export * from './classes/entity.utilities';
8
- export * from './classes/date.utilities';
9
- export * from './classes/file.utilities';
10
6
  export * from './components/confirm-dialog/confirm-dialog-data';
11
7
  export * from './components/confirm-dialog/confirm-dialog.component';
12
8
  export * from './components/confirm-dialog/confirm-dialog.module';
13
- export * from './components/input/input.module';
9
+ export * from './components/edit-page/edit-page.component';
10
+ export * from './components/get-validation-error-message.function';
11
+ export * from './components/input/base-input.component';
14
12
  export * from './components/input/input.component';
15
- export * from './components/table/table-data';
16
- export * from './components/table/table.component';
17
- export * from './components/table/table.module';
13
+ export * from './components/input/input.module';
18
14
  export * from './components/table/create-dialog/create-entity-dialog-data';
19
- export * from './components/table/create-dialog/create-entity-dialog.module';
20
15
  export * from './components/table/create-dialog/create-entity-dialog.component';
21
- export * from './components/table/edit-dialog/edit-entity-dialog-data';
22
- export * from './components/table/edit-dialog/edit-entity-dialog.module';
16
+ export * from './components/table/create-dialog/create-entity-dialog.module';
17
+ export * from './components/table/edit-dialog/edit-entity-data';
23
18
  export * from './components/table/edit-dialog/edit-entity-dialog.component';
24
- export * from './components/get-validation-error-message.function';
25
- export * from './components/input/base-input.component';
26
- export * from './decorators/array/array.decorator';
19
+ export * from './components/table/edit-dialog/edit-entity-dialog.module';
20
+ export * from './components/table/table-data';
21
+ export * from './components/table/table.component';
22
+ export * from './components/table/table.module';
27
23
  export * from './decorators/array/array-decorator.data';
24
+ export * from './decorators/array/array.decorator';
28
25
  export * from './decorators/base/decorator-types.enum';
29
26
  export * from './decorators/base/dropdown-value.interface';
30
27
  export { Col, Position } from './decorators/base/property-decorator.data';
31
- export * from './decorators/boolean/boolean.decorator';
32
28
  export * from './decorators/boolean/boolean-decorator.data';
33
- export * from './decorators/date/date.decorator';
29
+ export * from './decorators/boolean/boolean.decorator';
30
+ export * from './decorators/custom/custom-decorator.data';
31
+ export * from './decorators/custom/custom.decorator';
34
32
  export * from './decorators/date/date-decorator.data';
35
- export * from './decorators/number/number.decorator';
33
+ export * from './decorators/date/date.decorator';
34
+ export * from './decorators/file/file-decorator.data';
35
+ export * from './decorators/file/file.decorator';
36
36
  export * from './decorators/number/number-decorator.data';
37
- export * from './decorators/object/object.decorator';
37
+ export * from './decorators/number/number.decorator';
38
38
  export * from './decorators/object/object-decorator.data';
39
- export * from './decorators/string/string.decorator';
40
- export * from './decorators/string/string-decorator.data';
41
- export * from './decorators/references-many/references-many.decorator';
39
+ export * from './decorators/object/object.decorator';
42
40
  export * from './decorators/references-many/references-many-decorator.data';
43
- export * from './decorators/file/file.decorator';
44
- export * from './decorators/file/file-decorator.data';
45
- export * from './decorators/custom/custom.decorator';
46
- export * from './decorators/custom/custom-decorator.data';
41
+ export * from './decorators/references-many/references-many.decorator';
42
+ export * from './decorators/string/string-decorator.data';
43
+ export * from './decorators/string/string.decorator';
44
+ export * from './services/entity.service';
45
+ export * from './services/unsaved-changes.guard';
46
+ export * from './utilities/date.utilities';
47
+ export * from './utilities/entity.utilities';
48
+ export * from './utilities/file.utilities';
@@ -1,6 +1,6 @@
1
1
  import { HttpClient } from '@angular/common/http';
2
2
  import { BehaviorSubject } from 'rxjs';
3
- import { BaseEntityType } from './entity.model';
3
+ import { BaseEntityType } from '../classes/entity.model';
4
4
  /**
5
5
  * A generic EntityService class.
6
6
  * Offers basic CRUD-functionality.
@@ -22,6 +22,10 @@ export declare abstract class EntityService<EntityType extends BaseEntityType<En
22
22
  * Delete Sends a DEL-Request to baseUrl/{id}.
23
23
  */
24
24
  abstract readonly baseUrl: string;
25
+ /**
26
+ * The route segment that comes before the id when editing an entity in a separate page.
27
+ */
28
+ readonly editBaseRoute: string;
25
29
  /**
26
30
  * The key which holds the id value.
27
31
  *
@@ -33,12 +37,18 @@ export declare abstract class EntityService<EntityType extends BaseEntityType<En
33
37
  * Can be subscribed to when you want to do a specific thing whenever the entities change.
34
38
  */
35
39
  readonly entitiesSubject: BehaviorSubject<EntityType[]>;
40
+ /**
41
+ * A subject of all the entity values.
42
+ * Can be subscribed to when you want to do a specific thing whenever the entities change.
43
+ */
44
+ protected readonly READ_EXPIRATION_IN_MS: number;
36
45
  /**
37
46
  * Gets the entities in an array from the internal entitiesSubject.
38
47
  *
39
48
  * @returns The current entities in form of an array.
40
49
  */
41
50
  get entities(): EntityType[];
51
+ lastRead?: Date;
42
52
  constructor(http: HttpClient);
43
53
  /**
44
54
  * Creates a new Entity and pushes it to the entities array.
@@ -72,6 +82,13 @@ export declare abstract class EntityService<EntityType extends BaseEntityType<En
72
82
  * @returns A Promise of all received Entities.
73
83
  */
74
84
  read(): Promise<EntityType[]>;
85
+ /**
86
+ * Tries to find an entity with the given id.
87
+ *
88
+ * @param id - The id of the entity to find.
89
+ * @returns The found entity.
90
+ */
91
+ findById(id: EntityType[keyof EntityType]): Promise<EntityType>;
75
92
  /**
76
93
  * Updates a specific Entity.
77
94
  *
@@ -0,0 +1,4 @@
1
+ import { UrlTree } from '@angular/router';
2
+ import { Observable } from 'rxjs';
3
+ import { NgxMatEntityEditPageComponent } from '../components/edit-page/edit-page.component';
4
+ export declare function UnsavedChangesGuard(component: NgxMatEntityEditPageComponent<any>): Observable<boolean | UrlTree>;
@@ -57,7 +57,7 @@ export declare abstract class DateUtilities {
57
57
  * @param filter - A filter function to do more specific time filtering. This could be e.g. The removal of lunch breaks.
58
58
  * @returns All valid dropdown values for the datetime property.
59
59
  */
60
- static getValidTimesForDropdown(times: DropdownValue<Time>[], date?: Date, min?: (date?: Date) => Time, max?: (date?: Date) => Time, filter?: ((time: Time) => boolean) | (() => boolean)): DropdownValue<Time>[];
60
+ static getValidTimesForDropdown(times: DropdownValue<Time | undefined>[], date?: Date, min?: (date?: Date) => Time, max?: (date?: Date) => Time, filter?: ((time: Time) => boolean) | (() => boolean)): DropdownValue<Time | undefined>[];
61
61
  /**
62
62
  * Checks if the time object has processable hours and minutes properties.
63
63
  * Doesn't check custom validators like min/max from the metadata configuration.
@@ -1,6 +1,6 @@
1
+ import { BaseEntityType } from '../classes/entity.model';
1
2
  import { DecoratorType, DecoratorTypes } from '../decorators/base/decorator-types.enum';
2
3
  import { PropertyDecoratorConfigInternal } from '../decorators/base/property-decorator-internal.data';
3
- import { BaseEntityType } from './entity.model';
4
4
  /**
5
5
  * Contains HelperMethods around handling Entities and their property-metadata.
6
6
  */
@@ -1,24 +0,0 @@
1
- import { EntityService } from '../../../classes/entity.service';
2
- import { HttpClient } from '@angular/common/http';
3
- import { EditEntityDialogData } from './edit-entity-dialog-data';
4
- import { EditDialogDataInternal } from './edit-dialog-data.builder';
5
- import { BaseBuilder } from '../../../classes/base.builder';
6
- import { BaseEntityType } from '../../../classes/entity.model';
7
- /**
8
- * The internal EditEntityDialogData. Requires all default values the user can leave out.
9
- */
10
- export declare class EditEntityDialogDataInternal<EntityType extends BaseEntityType<EntityType>> implements EditEntityDialogData<EntityType> {
11
- entity: EntityType;
12
- EntityServiceClass: new (httpClient: HttpClient) => EntityService<EntityType>;
13
- editDialogData: EditDialogDataInternal<EntityType>;
14
- allowUpdate: (entity: EntityType) => boolean;
15
- allowDelete: (entity: EntityType) => boolean;
16
- constructor(entity: EntityType, EntityServiceClass: new (httpClient: HttpClient) => EntityService<EntityType>, editDialogData: EditDialogDataInternal<EntityType>, allowUpdate: (entity: EntityType) => boolean, allowDelete: (entity: EntityType) => boolean);
17
- }
18
- /**
19
- * The Builder for the EditEntityDialogData. Sets default values.
20
- */
21
- export declare class EditEntityDialogDataBuilder<EntityType extends BaseEntityType<EntityType>> extends BaseBuilder<EditEntityDialogDataInternal<EntityType>, EditEntityDialogData<EntityType>> {
22
- constructor(data: EditEntityDialogData<EntityType>);
23
- protected generateBaseData(data: EditEntityDialogData<EntityType>): EditEntityDialogDataInternal<EntityType>;
24
- }
@@ -1,158 +0,0 @@
1
- import { LodashUtilities } from '../encapsulation/lodash.utilities';
2
- const DAY_IN_MS = 1000 * 60 * 60 * 24;
3
- /**
4
- * Contains Helper Functions for handling date properties.
5
- */
6
- export class DateUtilities {
7
- /**
8
- * Gets the given value as a date value.
9
- *
10
- * @param value - The value to get as a date.
11
- * @returns The given value as a date.
12
- */
13
- static asDate(value) {
14
- return value;
15
- }
16
- /**
17
- * Gets the default times used by the DateTime picker when nothing is specified by the user.
18
- *
19
- * @param format - The time format. Defaults to 24.
20
- * @param minuteSteps - The steps from one time value to the next. Defaults to 30.
21
- * @returns Times in the 24 hour format from 0:00 until 23:30 in 30 minute steps.
22
- */
23
- static getDefaultTimes(format = 24, minuteSteps = 30) {
24
- const res = [{ displayName: '-', value: undefined }];
25
- for (let hour = 0; hour < 24; hour++) {
26
- for (let minute = 0; minute < 60; minute += minuteSteps) {
27
- res.push(DateUtilities.getTimeDropdownValue(format, hour, minute));
28
- }
29
- }
30
- return res;
31
- }
32
- static getTimeDropdownValue(format, hour, minute) {
33
- const displayHour = DateUtilities.getFormattedHour(format, LodashUtilities.cloneDeep(hour));
34
- const displayMinute = DateUtilities.getFormattedMinute(format, hour, minute);
35
- return {
36
- displayName: `${displayHour}:${displayMinute}`,
37
- value: {
38
- hours: hour,
39
- minutes: minute
40
- }
41
- };
42
- }
43
- static getFormattedHour(format, hour) {
44
- if (format === 12 && hour > 12) {
45
- hour -= 12;
46
- }
47
- return hour;
48
- }
49
- static getFormattedMinute(format, hour, minute) {
50
- let res = `${minute}`;
51
- if (format === 12) {
52
- if (hour > 12) {
53
- res = `${minute} PM`;
54
- }
55
- else {
56
- res = `${minute} AM`;
57
- }
58
- }
59
- if (minute.toString().length === 1) {
60
- res = '0'.concat(res);
61
- }
62
- return res;
63
- }
64
- /**
65
- * Gets the Time object from the given date.
66
- *
67
- * @param value - The date to get the time object from.
68
- * @returns The Time object build from the date value.
69
- */
70
- static getTimeFromDate(value) {
71
- if (!value) {
72
- return undefined;
73
- }
74
- else {
75
- return {
76
- hours: new Date(value).getHours(),
77
- minutes: new Date(value).getMinutes()
78
- };
79
- }
80
- }
81
- /**
82
- * Gets the dates between the two given gates. Does additional filtering based on the provided DateRange metadata.
83
- *
84
- * @param startDate - The start date.
85
- * @param endDate - The end date.
86
- * @param filter - The custom filter from the metadata.
87
- * @returns All dates between the two provided dates. Includes start and end date.
88
- */
89
- static getDatesBetween(startDate, endDate, filter) {
90
- const res = [];
91
- while (startDate.getFullYear() < endDate.getFullYear()
92
- || startDate.getMonth() < endDate.getMonth()
93
- || startDate.getDate() <= endDate.getDate()) {
94
- res.push(new Date(startDate));
95
- startDate.setTime(startDate.getTime() + DAY_IN_MS);
96
- }
97
- if (filter) {
98
- return res.filter(d => filter(d));
99
- }
100
- else {
101
- return res;
102
- }
103
- }
104
- /**
105
- * Get all valid times for the dropdown of a datetime property.
106
- *
107
- * @param times - All given times to filter.
108
- * @param date - The date of the datetime.
109
- * @param min - The function that defines the minimum time.
110
- * @param max - The function that defines the maximum time.
111
- * @param filter - A filter function to do more specific time filtering. This could be e.g. The removal of lunch breaks.
112
- * @returns All valid dropdown values for the datetime property.
113
- */
114
- static getValidTimesForDropdown(times, date, min, max, filter) {
115
- if (min) {
116
- const minTime = min(date);
117
- times = times.filter(t => !t.value
118
- || t.value.hours > minTime.hours
119
- || (t.value.hours === minTime.hours
120
- && t.value.minutes >= minTime.minutes));
121
- }
122
- if (max) {
123
- const maxTime = max(date);
124
- times = times.filter(t => !t.value
125
- || t.value.hours < maxTime.hours
126
- || (t.value.hours === maxTime.hours
127
- && t.value.minutes <= maxTime.minutes));
128
- }
129
- if (filter) {
130
- times = times.filter(t => !t.value || filter(t.value));
131
- }
132
- return times;
133
- }
134
- /**
135
- * Checks if the time object has processable hours and minutes properties.
136
- * Doesn't check custom validators like min/max from the metadata configuration.
137
- *
138
- * @param time - The time to check.
139
- * @returns Whether or not the time object is unprocessable.
140
- */
141
- static timeIsUnprocessable(time) {
142
- if (!time
143
- || time.hours == null
144
- || typeof time.hours !== 'number'
145
- || Number.isNaN(time.hours)
146
- || time.minutes == null
147
- || typeof time.minutes !== 'number'
148
- || Number.isNaN(time.minutes)) {
149
- return true;
150
- }
151
- return false;
152
- }
153
- }
154
- /**
155
- * The default filter function to user when none was provided by the user.
156
- */
157
- DateUtilities.defaultDateFilter = () => true;
158
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS51dGlsaXRpZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtbWF0ZXJpYWwtZW50aXR5L3NyYy9jbGFzc2VzL2RhdGUudXRpbGl0aWVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUdwRSxNQUFNLFNBQVMsR0FBVyxJQUFJLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFPOUM7O0dBRUc7QUFDSCxNQUFNLE9BQWdCLGFBQWE7SUFPL0I7Ozs7O09BS0c7SUFDSCxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQWM7UUFDeEIsT0FBTyxLQUFhLENBQUM7SUFDekIsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILE1BQU0sQ0FBQyxlQUFlLENBQUMsU0FBa0IsRUFBRSxFQUFFLGNBQTJCLEVBQUU7UUFDdEUsTUFBTSxHQUFHLEdBQTBCLENBQUMsRUFBRSxXQUFXLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxTQUE0QixFQUFFLENBQUMsQ0FBQztRQUMvRixLQUFLLElBQUksSUFBSSxHQUFXLENBQUMsRUFBRSxJQUFJLEdBQUcsRUFBRSxFQUFFLElBQUksRUFBRSxFQUFFO1lBQzFDLEtBQUssSUFBSSxNQUFNLEdBQVcsQ0FBQyxFQUFFLE1BQU0sR0FBRyxFQUFFLEVBQUUsTUFBTSxJQUFJLFdBQVcsRUFBRTtnQkFDN0QsR0FBRyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsb0JBQW9CLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO2FBQ3RFO1NBQ0o7UUFDRCxPQUFPLEdBQUcsQ0FBQztJQUNmLENBQUM7SUFFTyxNQUFNLENBQUMsb0JBQW9CLENBQUMsTUFBZSxFQUFFLElBQVksRUFBRSxNQUFjO1FBQzdFLE1BQU0sV0FBVyxHQUFXLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxN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LENBQUM7ZUFDeEIsSUFBSSxDQUFDLE9BQU8sSUFBSSxJQUFJO2VBQ3BCLE9BQU8sSUFBSSxDQUFDLE9BQU8sS0FBSyxRQUFRO2VBQ2hDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUMvQjtZQUNFLE9BQU8sSUFBSSxDQUFDO1NBQ2Y7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDOztBQXJMRDs7R0FFRztBQUNJLCtCQUFpQixHQUEwQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBUaW1lIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IERhdGVGaWx0ZXJGbiB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2RhdGVwaWNrZXInO1xuaW1wb3J0IHsgTG9kYXNoVXRpbGl0aWVzIH0gZnJvbSAnLi4vZW5jYXBzdWxhdGlvbi9sb2Rhc2gudXRpbGl0aWVzJztcbmltcG9ydCB7IERyb3Bkb3duVmFsdWUgfSBmcm9tICcuLi9kZWNvcmF0b3JzL2Jhc2UvZHJvcGRvd24tdmFsdWUuaW50ZXJmYWNlJztcblxuY29uc3QgREFZX0lOX01TOiBudW1iZXIgPSAxMDAwICogNjAgKiA2MCAqIDI0O1xuXG4vKipcbiAqIFZhbGlkIHN0ZXBzIGZyb20gb25lIHRpbWUgdmFsdWUgdG8gdGhlIG5leHQuIE5lZWRzIHRvIGJlIGFibGUgdG8gZGl2aWRlIDYwIG1pbnV0ZXMgd2l0aG91dCByZW1haW5kZXIuXG4gKi9cbnR5cGUgTWludXRlU3RlcHMgPSAxIHwgMiB8IDMgfCA0IHwgNSB8IDYgfCAxMCB8IDEyIHwgMTUgfCAyMCB8IDMwIHwgNjA7XG5cbi8qKlxuICogQ29udGFpbnMgSGVscGVyIEZ1bmN0aW9ucyBmb3IgaGFuZGxpbmcgZGF0ZSBwcm9wZXJ0aWVzLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgRGF0ZVV0aWxpdGllcyB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZGVmYXVsdCBmaWx0ZXIgZnVuY3Rpb24gdG8gdXNlciB3aGVuIG5vbmUgd2FzIHByb3ZpZGVkIGJ5IHRoZSB1c2VyLlxuICAgICAqL1xuICAgIHN0YXRpYyBkZWZhdWx0RGF0ZUZpbHRlcjogRGF0ZUZpbHRlckZuPERhdGUgfCBudWxsIHwgdW5kZWZpbmVkPiA9ICgpID0+IHRydWU7XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBnaXZlbiB2YWx1ZSBhcyBhIGRhdGUgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gZ2V0IGFzIGEgZGF0ZS5cbiAgICAgKiBAcmV0dXJucyBUaGUgZ2l2ZW4gdmFsdWUgYXMgYSBkYXRlLlxuICAgICAqL1xuICAgIHN0YXRpYyBhc0RhdGUodmFsdWU6IHVua25vd24pOiBEYXRlIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlIGFzIERhdGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgZGVmYXVsdCB0aW1lcyB1c2VkIGJ5IHRoZSBEYXRlVGltZSBwaWNrZXIgd2hlbiBub3RoaW5nIGlzIHNwZWNpZmllZCBieSB0aGUgdXNlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBmb3JtYXQgLSBUaGUgdGltZSBmb3JtYXQuIERlZmF1bHRzIHRvIDI0LlxuICAgICAqIEBwYXJhbSBtaW51dGVTdGVwcyAtIFRoZSBzdGVwcyBmcm9tIG9uZSB0aW1lIHZhbHVlIHRvIHRoZSBuZXh0LiBEZWZhdWx0cyB0byAzMC5cbiAgICAgKiBAcmV0dXJucyBUaW1lcyBpbiB0aGUgMjQgaG91ciBmb3JtYXQgZnJvbSAwOjAwIHVudGlsIDIzOjMwIGluIDMwIG1pbnV0ZSBzdGVwcy5cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0RGVmYXVsdFRpbWVzKGZvcm1hdDogMTIgfCAyNCA9IDI0LCBtaW51dGVTdGVwczogTWludXRlU3RlcHMgPSAzMCk6IERyb3Bkb3duVmFsdWU8VGltZT5bXSB7XG4gICAgICAgIGNvbnN0IHJlczogRHJvcGRvd25WYWx1ZTxUaW1lPltdID0gW3sgZGlzcGxheU5hbWU6ICctJywgdmFsdWU6IHVuZGVmaW5lZCBhcyB1bmtub3duIGFzIFRpbWUgfV07XG4gICAgICAgIGZvciAobGV0IGhvdXI6IG51bWJlciA9IDA7IGhvdXIgPCAyNDsgaG91cisrKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBtaW51dGU6IG51bWJlciA9IDA7IG1pbnV0ZSA8IDYwOyBtaW51dGUgKz0gbWludXRlU3RlcHMpIHtcbiAgICAgICAgICAgICAgICByZXMucHVzaChEYXRlVXRpbGl0aWVzLmdldFRpbWVEcm9wZG93blZhbHVlKGZvcm1hdCwgaG91ciwgbWludXRlKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBnZXRUaW1lRHJvcGRvd25WYWx1ZShmb3JtYXQ6IDEyIHwgMjQsIGhvdXI6IG51bWJlciwgbWludXRlOiBudW1iZXIpOiBEcm9wZG93blZhbHVlPFRpbWU+IHtcbiAgICAgICAgY29uc3QgZGlzcGxheUhvdXI6IG51bWJlciA9IERhdGVVdGlsaXRpZXMuZ2V0Rm9ybWF0dGVkSG91cihmb3JtYXQsIExvZGFzaFV0aWxpdGllcy5jbG9uZURlZXAoaG91cikpO1xuICAgICAgICBjb25zdCBkaXNwbGF5TWludXRlOiBzdHJpbmcgPSBEYXRlVXRpbGl0aWVzLmdldEZvcm1hdHRlZE1pbnV0ZShmb3JtYXQsIGhvdXIsIG1pbnV0ZSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBkaXNwbGF5TmFtZTogYCR7ZGlzcGxheUhvdXJ9OiR7ZGlzcGxheU1pbnV0ZX1gLFxuICAgICAgICAgICAgdmFsdWU6IHtcbiAgICAgICAgICAgICAgICBob3VyczogaG91cixcbiAgICAgICAgICAgICAgICBtaW51dGVzOiBtaW51dGVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBnZXRGb3JtYXR0ZWRIb3VyKGZvcm1hdDogMTIgfCAyNCwgaG91cjogbnVtYmVyKTogbnVtYmVyIHtcbiAgICAgICAgaWYgKGZvcm1hdCA9PT0gMTIgJiYgaG91ciA+IDEyKSB7XG4gICAgICAgICAgICBob3VyIC09IDEyO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBob3VyO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGdldEZvcm1hdHRlZE1pbnV0ZShmb3JtYXQ6IDEyIHwgMjQsIGhvdXI6IG51bWJlciwgbWludXRlOiBudW1iZXIpOiBzdHJpbmcge1xuICAgICAgICBsZXQgcmVzOiBzdHJpbmcgPSBgJHttaW51dGV9YDtcbiAgICAgICAgaWYgKGZvcm1hdCA9PT0gMTIpIHtcbiAgICAgICAgICAgIGlmIChob3VyID4gMTIpIHtcbiAgICAgICAgICAgICAgICByZXMgPSBgJHttaW51dGV9IFBNYDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlcyA9IGAke21pbnV0ZX0gQU1gO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChtaW51dGUudG9TdHJpbmcoKS5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIHJlcyA9ICcwJy5jb25jYXQocmVzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIFRpbWUgb2JqZWN0IGZyb20gdGhlIGdpdmVuIGRhdGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgZGF0ZSB0byBnZXQgdGhlIHRpbWUgb2JqZWN0IGZyb20uXG4gICAgICogQHJldHVybnMgVGhlIFRpbWUgb2JqZWN0IGJ1aWxkIGZyb20gdGhlIGRhdGUgdmFsdWUuXG4gICAgICovXG4gICAgc3RhdGljIGdldFRpbWVGcm9tRGF0ZSh2YWx1ZT86IERhdGUpOiBUaW1lIHwgdW5kZWZpbmVkIHtcbiAgICAgICAgaWYgKCF2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgaG91cnM6IG5ldyBEYXRlKHZhbHVlKS5nZXRIb3VycygpLFxuICAgICAgICAgICAgICAgIG1pbnV0ZXM6IG5ldyBEYXRlKHZhbHVlKS5nZXRNaW51dGVzKClcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBkYXRlcyBiZXR3ZWVuIHRoZSB0d28gZ2l2ZW4gZ2F0ZXMuIERvZXMgYWRkaXRpb25hbCBmaWx0ZXJpbmcgYmFzZWQgb24gdGhlIHByb3ZpZGVkIERhdGVSYW5nZSBtZXRhZGF0YS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBzdGFydERhdGUgLSBUaGUgc3RhcnQgZGF0ZS5cbiAgICAgKiBAcGFyYW0gZW5kRGF0ZSAtIFRoZSBlbmQgZGF0ZS5cbiAgICAgKiBAcGFyYW0gZmlsdGVyIC0gVGhlIGN1c3RvbSBmaWx0ZXIgZnJvbSB0aGUgbWV0YWRhdGEuXG4gICAgICogQHJldHVybnMgQWxsIGRhdGVzIGJldHdlZW4gdGhlIHR3byBwcm92aWRlZCBkYXRlcy4gSW5jbHVkZXMgc3RhcnQgYW5kIGVuZCBkYXRlLlxuICAgICAqL1xuICAgIHN0YXRpYyBnZXREYXRlc0JldHdlZW4oXG4gICAgICAgIHN0YXJ0RGF0ZTogRGF0ZSxcbiAgICAgICAgZW5kRGF0ZTogRGF0ZSxcbiAgICAgICAgZmlsdGVyPzogRGF0ZUZpbHRlckZuPERhdGU+XG4gICAgKTogRGF0ZVtdIHtcbiAgICAgICAgY29uc3QgcmVzOiBEYXRlW10gPSBbXTtcbiAgICAgICAgd2hpbGUgKFxuICAgICAgICAgICAgc3RhcnREYXRlLmdldEZ1bGxZZWFyKCkgPCBlbmREYXRlLmdldEZ1bGxZZWFyKClcbiAgICAgICAgICAgIHx8IHN0YXJ0RGF0ZS5nZXRNb250aCgpIDwgZW5kRGF0ZS5nZXRNb250aCgpXG4gICAgICAgICAgICB8fCBzdGFydERhdGUuZ2V0RGF0ZSgpIDw9IGVuZERhdGUuZ2V0RGF0ZSgpXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmVzLnB1c2gobmV3IERhdGUoc3RhcnREYXRlKSk7XG4gICAgICAgICAgICBzdGFydERhdGUuc2V0VGltZShzdGFydERhdGUuZ2V0VGltZSgpICsgREFZX0lOX01TKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZmlsdGVyKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzLmZpbHRlcihkID0+IGZpbHRlcihkKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCB2YWxpZCB0aW1lcyBmb3IgdGhlIGRyb3Bkb3duIG9mIGEgZGF0ZXRpbWUgcHJvcGVydHkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdGltZXMgLSBBbGwgZ2l2ZW4gdGltZXMgdG8gZmlsdGVyLlxuICAgICAqIEBwYXJhbSBkYXRlIC0gVGhlIGRhdGUgb2YgdGhlIGRhdGV0aW1lLlxuICAgICAqIEBwYXJhbSBtaW4gLSBUaGUgZnVuY3Rpb24gdGhhdCBkZWZpbmVzIHRoZSBtaW5pbXVtIHRpbWUuXG4gICAgICogQHBhcmFtIG1heCAtIFRoZSBmdW5jdGlvbiB0aGF0IGRlZmluZXMgdGhlIG1heGltdW0gdGltZS5cbiAgICAgKiBAcGFyYW0gZmlsdGVyIC0gQSBmaWx0ZXIgZnVuY3Rpb24gdG8gZG8gbW9yZSBzcGVjaWZpYyB0aW1lIGZpbHRlcmluZy4gVGhpcyBjb3VsZCBiZSBlLmcuIFRoZSByZW1vdmFsIG9mIGx1bmNoIGJyZWFrcy5cbiAgICAgKiBAcmV0dXJucyBBbGwgdmFsaWQgZHJvcGRvd24gdmFsdWVzIGZvciB0aGUgZGF0ZXRpbWUgcHJvcGVydHkuXG4gICAgICovXG4gICAgc3RhdGljIGdldFZhbGlkVGltZXNGb3JEcm9wZG93bihcbiAgICAgICAgdGltZXM6IERyb3Bkb3duVmFsdWU8VGltZT5bXSxcbiAgICAgICAgZGF0ZT86IERhdGUsXG4gICAgICAgIG1pbj86IChkYXRlPzogRGF0ZSkgPT4gVGltZSxcbiAgICAgICAgbWF4PzogKGRhdGU/OiBEYXRlKSA9PiBUaW1lLFxuICAgICAgICBmaWx0ZXI/OiAoKHRpbWU6IFRpbWUpID0+IGJvb2xlYW4pIHwgKCgpID0+IGJvb2xlYW4pXG4gICAgKTogRHJvcGRvd25WYWx1ZTxUaW1lPltdIHtcbiAgICAgICAgaWYgKG1pbikge1xuICAgICAgICAgICAgY29uc3QgbWluVGltZTogVGltZSA9IG1pbihkYXRlKTtcbiAgICAgICAgICAgIHRpbWVzID0gdGltZXMuZmlsdGVyKHQgPT5cbiAgICAgICAgICAgICAgICAhKHQudmFsdWUgYXMgVGltZSB8IHVuZGVmaW5lZClcbiAgICAgICAgICAgICAgICB8fCB0LnZhbHVlLmhvdXJzID4gbWluVGltZS5ob3Vyc1xuICAgICAgICAgICAgICAgIHx8IChcbiAgICAgICAgICAgICAgICAgICAgdC52YWx1ZS5ob3VycyA9PT0gbWluVGltZS5ob3Vyc1xuICAgICAgICAgICAgICAgICAgICAmJiB0LnZhbHVlLm1pbnV0ZXMgPj0gbWluVGltZS5taW51dGVzXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWF4KSB7XG4gICAgICAgICAgICBjb25zdCBtYXhUaW1lOiBUaW1lID0gbWF4KGRhdGUpO1xuICAgICAgICAgICAgdGltZXMgPSB0aW1lcy5maWx0ZXIodCA9PlxuICAgICAgICAgICAgICAgICEodC52YWx1ZSBhcyBUaW1lIHwgdW5kZWZpbmVkKVxuICAgICAgICAgICAgICAgIHx8IHQudmFsdWUuaG91cnMgPCBtYXhUaW1lLmhvdXJzXG4gICAgICAgICAgICAgICAgfHwgKFxuICAgICAgICAgICAgICAgICAgICB0LnZhbHVlLmhvdXJzID09PSBtYXhUaW1lLmhvdXJzXG4gICAgICAgICAgICAgICAgICAgICYmIHQudmFsdWUubWludXRlcyA8PSBtYXhUaW1lLm1pbnV0ZXNcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmaWx0ZXIpIHtcbiAgICAgICAgICAgIHRpbWVzID0gdGltZXMuZmlsdGVyKHQgPT4gISh0LnZhbHVlIGFzIFRpbWUgfCB1bmRlZmluZWQpIHx8IGZpbHRlcih0LnZhbHVlKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGltZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIHRoZSB0aW1lIG9iamVjdCBoYXMgcHJvY2Vzc2FibGUgaG91cnMgYW5kIG1pbnV0ZXMgcHJvcGVydGllcy5cbiAgICAgKiBEb2Vzbid0IGNoZWNrIGN1c3RvbSB2YWxpZGF0b3JzIGxpa2UgbWluL21heCBmcm9tIHRoZSBtZXRhZGF0YSBjb25maWd1cmF0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIHRpbWUgLSBUaGUgdGltZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyBXaGV0aGVyIG9yIG5vdCB0aGUgdGltZSBvYmplY3QgaXMgdW5wcm9jZXNzYWJsZS5cbiAgICAgKi9cbiAgICBzdGF0aWMgdGltZUlzVW5wcm9jZXNzYWJsZSh0aW1lPzogVGltZSk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICAhdGltZVxuICAgICAgICAgICAgfHwgdGltZS5ob3VycyA9PSBudWxsXG4gICAgICAgICAgICB8fCB0eXBlb2YgdGltZS5ob3VycyAhPT0gJ251bWJlcidcbiAgICAgICAgICAgIHx8IE51bWJlci5pc05hTih0aW1lLmhvdXJzKVxuICAgICAgICAgICAgfHwgdGltZS5taW51dGVzID09IG51bGxcbiAgICAgICAgICAgIHx8IHR5cGVvZiB0aW1lLm1pbnV0ZXMgIT09ICdudW1iZXInXG4gICAgICAgICAgICB8fCBOdW1iZXIuaXNOYU4odGltZS5taW51dGVzKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG59Il19
@@ -1,213 +0,0 @@
1
- import { BehaviorSubject, firstValueFrom } from 'rxjs';
2
- import { EntityUtilities } from './entity.utilities';
3
- import { LodashUtilities } from '../encapsulation/lodash.utilities';
4
- import { DecoratorTypes } from '../decorators/base/decorator-types.enum';
5
- import { FileUtilities } from './file.utilities';
6
- /**
7
- * A generic EntityService class.
8
- * Offers basic CRUD-functionality.
9
- * You should create a service for every Entity you have.
10
- * If you extend from this you need to make sure that the extended Service can be injected.
11
- */
12
- export class EntityService {
13
- constructor(http) {
14
- this.http = http;
15
- /**
16
- * The key which holds the id value.
17
- *
18
- * @default 'id'
19
- */
20
- this.idKey = 'id';
21
- /**
22
- * A subject of all the entity values.
23
- * Can be subscribed to when you want to do a specific thing whenever the entities change.
24
- */
25
- this.entitiesSubject = new BehaviorSubject([]);
26
- }
27
- /**
28
- * Gets the entities in an array from the internal entitiesSubject.
29
- *
30
- * @returns The current entities in form of an array.
31
- */
32
- get entities() {
33
- return this.entitiesSubject.value;
34
- }
35
- /**
36
- * Creates a new Entity and pushes it to the entities array.
37
- *
38
- * @param entity - The data of the entity to create.
39
- * All values that should be omitted will be removed from it inside this method.
40
- * @returns A Promise of the created entity.
41
- */
42
- async create(entity) {
43
- const body = LodashUtilities.omit(entity, EntityUtilities.getOmitForCreate(entity));
44
- const filePropertyKeys = EntityUtilities.getFileProperties(entity);
45
- if (!filePropertyKeys.length) {
46
- return await this.createWithJson(body);
47
- }
48
- else {
49
- return await this.createWithFormData(body, filePropertyKeys, entity);
50
- }
51
- }
52
- // TODO: Find a way to use blobs with jest
53
- /* istanbul ignore next */
54
- /**
55
- * Creates the entity with form data when the entity contains files in contrast to creating it with a normal json body.
56
- * All file values are stored inside their respective property key and their name.
57
- * Form data is able to handle setting multiple files to the same key.
58
- *
59
- * @param body - The body Of the request.
60
- * @param filePropertyKeys - All property keys that are files and need to be added to the form data.
61
- * @param entity - The entity to create. This is needed in addition to the body because the body doesn't contain any metadata.
62
- * @returns The created entity from the server.
63
- */
64
- async createWithFormData(body, filePropertyKeys, entity) {
65
- const formData = new FormData();
66
- formData.append('body', JSON.stringify(LodashUtilities.omit(body, filePropertyKeys)));
67
- for (const key of filePropertyKeys) {
68
- if (EntityUtilities.getPropertyMetadata(entity, key, DecoratorTypes.FILE_DEFAULT).multiple) {
69
- const fileDataValues = body[key];
70
- for (const value of fileDataValues) {
71
- formData.append(key, (await FileUtilities.getFileData(value)).file, value.name);
72
- }
73
- }
74
- else {
75
- const fileData = body[key];
76
- formData.append(key, (await FileUtilities.getFileData(fileData)).file, fileData.name);
77
- }
78
- }
79
- const e = await firstValueFrom(this.http.post(this.baseUrl, formData));
80
- if (!e) {
81
- throw new Error(`
82
- The created entity was not returned in the response.
83
- If you want to provide a logic that allows that
84
- you need to override the create methods of this class.
85
- `);
86
- }
87
- this.entities.push(e);
88
- this.entitiesSubject.next(this.entities);
89
- return e;
90
- }
91
- /**
92
- * Creates the entity with a normal json body in contrast to creating it with form data when the entity contains files.
93
- *
94
- * @param body - The body Of the request.
95
- * @returns The created entity from the server.
96
- */
97
- async createWithJson(body) {
98
- const e = await firstValueFrom(this.http.post(this.baseUrl, body));
99
- if (!e) {
100
- throw new Error(`
101
- The created entity was not returned in the response.
102
- If you want to provide a logic that allows that
103
- you need to override the create methods of this class.
104
- `);
105
- }
106
- this.entities.push(e);
107
- this.entitiesSubject.next(this.entities);
108
- return e;
109
- }
110
- /**
111
- * Gets all existing entities and pushes them to the entities array.
112
- *
113
- * @returns A Promise of all received Entities.
114
- */
115
- async read() {
116
- const e = await firstValueFrom(this.http.get(this.baseUrl));
117
- this.entitiesSubject.next(e);
118
- return e;
119
- }
120
- /**
121
- * Updates a specific Entity.
122
- *
123
- * @param entity - The updated Entity
124
- * All values that should be omitted will be removed from it inside this method.
125
- * @param entityPriorChanges - The current Entity.
126
- * It Is used to get changed values and only update them instead of sending the whole entity data.
127
- */
128
- async update(entity, entityPriorChanges) {
129
- const body = LodashUtilities.omit(await EntityUtilities.difference(entity, entityPriorChanges), EntityUtilities.getOmitForUpdate(entity));
130
- const filePropertyKeys = EntityUtilities.getFileProperties(entityPriorChanges);
131
- if (!filePropertyKeys.length) {
132
- await this.updateWithJson(body, entityPriorChanges[this.idKey]);
133
- }
134
- else {
135
- await this.updateWithFormData(body, filePropertyKeys, entity, entityPriorChanges[this.idKey]);
136
- }
137
- }
138
- // TODO: Find a way to use blobs with jest
139
- /* istanbul ignore next */
140
- /**
141
- * Updates the entity with form data when the entity contains files in contrast to creating it with a normal json body.
142
- * All file values are stored inside their respective property key and their name.
143
- * Form data is able to handle setting multiple files to the same key.
144
- *
145
- * @param body - The request body. Already contains only properties that have changed.
146
- * @param filePropertyKeys - The keys of all properties which are files and need to separately be appended to the form data.
147
- * @param entity - The original entity. Is needed to get the metadata of all the files.
148
- * @param id - The id of the entity to update.
149
- */
150
- async updateWithFormData(body, filePropertyKeys, entity, id) {
151
- const formData = new FormData();
152
- formData.append('body', JSON.stringify(LodashUtilities.omitBy(body, LodashUtilities.isNil)));
153
- for (const key of filePropertyKeys) {
154
- if (EntityUtilities.getPropertyMetadata(entity, key, DecoratorTypes.FILE_DEFAULT).multiple) {
155
- const fileDataValues = body[key];
156
- for (const value of fileDataValues) {
157
- formData.append(key, (await FileUtilities.getFileData(value)).file, value.name);
158
- }
159
- }
160
- else {
161
- const fileData = body[key];
162
- formData.append(key, (await FileUtilities.getFileData(fileData)).file, fileData.name);
163
- }
164
- }
165
- const updatedEntity = await firstValueFrom(this.http.patch(`${this.baseUrl}/${id}`, formData));
166
- if (!updatedEntity) {
167
- // eslint-disable-next-line no-console
168
- console.warn('The updated entity was not returned in the response. Applying the changes from the request body.');
169
- for (const key in body) {
170
- this.entities[this.entities.findIndex(e => e[this.idKey] === id)][key]
171
- = body[key];
172
- }
173
- this.entitiesSubject.next(this.entities);
174
- return;
175
- }
176
- this.entities[this.entities.findIndex(e => e[this.idKey] === id)] = updatedEntity;
177
- this.entitiesSubject.next(this.entities);
178
- }
179
- /**
180
- * Updates the entity with a normal json body in contrast to updating it with form data when the entity contains files.
181
- *
182
- * @param body - The body of the Request. Has already removed all unnecessary values.
183
- * @param id - The id of the entity to update.
184
- */
185
- async updateWithJson(body, id) {
186
- const updatedEntity = await firstValueFrom(this.http.patch(`${this.baseUrl}/${id}`, LodashUtilities.omitBy(body, LodashUtilities.isNil)));
187
- if (!updatedEntity) {
188
- // eslint-disable-next-line no-console
189
- console.warn('The updated entity was not returned in the response. Applying the changes from the request body.');
190
- const foundEntity = this.entities[this.entities.findIndex(e => e[this.idKey] === id)];
191
- for (const key in body) {
192
- foundEntity[key]
193
- = body[key];
194
- }
195
- this.entitiesSubject.next(this.entities);
196
- return;
197
- }
198
- this.entities[this.entities.findIndex(e => e[this.idKey] === id)] = updatedEntity;
199
- this.entitiesSubject.next(this.entities);
200
- }
201
- /**
202
- * Deletes a specific Entity.
203
- *
204
- * @param entity - The entity to delete.
205
- */
206
- async delete(entity) {
207
- await firstValueFrom(this.http.delete(`${this.baseUrl}/${entity[this.idKey]}`));
208
- // the == comparison instead of === is to catch ids that are numbers.
209
- this.entities.splice(this.entities.findIndex(e => e[this.idKey] === entity[this.idKey]), 1);
210
- this.entitiesSubject.next(this.entities);
211
- }
212
- }
213
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtbWF0ZXJpYWwtZW50aXR5L3NyYy9jbGFzc2VzL2VudGl0eS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxlQUFlLEVBQUUsY0FBYyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3ZELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDcEUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBRXpFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUdqRDs7Ozs7R0FLRztBQUNILE1BQU0sT0FBZ0IsYUFBYTtJQW9DL0IsWUFBNkIsSUFBZ0I7UUFBaEIsU0FBSSxHQUFKLElBQUksQ0FBWTtRQXRCN0M7Ozs7V0FJRztRQUNNLFVBQUssR0FBcUIsSUFBd0IsQ0FBQztRQUU1RDs7O1dBR0c7UUFDTSxvQkFBZSxHQUFrQyxJQUFJLGVBQWUsQ0FBZSxFQUFFLENBQUMsQ0FBQztJQVdoRCxDQUFDO0lBVGpEOzs7O09BSUc7SUFDSCxJQUFJLFFBQVE7UUFDUixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDO0lBQ3RDLENBQUM7SUFJRDs7Ozs7O09BTUc7SUFDSCxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQWtCO1FBQzNCLE1BQU0sSUFBSSxHQUF3QixlQUFlLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxlQUFlLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLENBQXdCLENBQUM7UUFDaEksTUFBTSxnQkFBZ0IsR0FBeUIsZUFBZSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3pGLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUU7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LE9BQU87U0FDVjtRQUNELElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLEdBQUcsYUFBYSxDQUFDO1FBQ2xGLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBa0I7UUFDM0IsTUFBTSxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDdEYscUVBQXFFO1FBQ3JFLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDNUYsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzdDLENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIGZpcnN0VmFsdWVGcm9tIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBFbnRpdHlVdGlsaXRpZXMgfSBmcm9tICcuL2VudGl0eS51dGlsaXRpZXMnO1xuaW1wb3J0IHsgTG9kYXNoVXRpbGl0aWVzIH0gZnJvbSAnLi4vZW5jYXBzdWxhdGlvbi9sb2Rhc2gudXRpbGl0aWVzJztcbmltcG9ydCB7IERlY29yYXRvclR5cGVzIH0gZnJvbSAnLi4vZGVjb3JhdG9ycy9iYXNlL2RlY29yYXRvci10eXBlcy5lbnVtJztcbmltcG9ydCB7IEZpbGVEYXRhIH0gZnJvbSAnLi4vZGVjb3JhdG9ycy9maWxlL2ZpbGUtZGVjb3JhdG9yLmRhdGEnO1xuaW1wb3J0IHsgRmlsZVV0aWxpdGllcyB9IGZyb20gJy4vZmlsZS51dGlsaXRpZXMnO1xuaW1wb3J0IHsgQmFzZUVudGl0eVR5cGUgfSBmcm9tICcuL2VudGl0eS5tb2RlbCc7XG5cbi8qKlxuICogQSBnZW5lcmljIEVudGl0eVNlcnZpY2UgY2xhc3MuXG4gKiBPZmZlcnMgYmFzaWMgQ1JVRC1mdW5jdGlvbmFsaXR5LlxuICogWW91IHNob3VsZCBjcmVhdGUgYSBzZXJ2aWNlIGZvciBldmVyeSBFbnRpdHkgeW91IGhhdmUuXG4gKiBJZiB5b3UgZXh0ZW5kIGZyb20gdGhpcyB5b3UgbmVlZCB0byBtYWtlIHN1cmUgdGhhdCB0aGUgZXh0ZW5kZWQgU2VydmljZSBjYW4gYmUgaW5qZWN0ZWQuXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBFbnRpdHlTZXJ2aWNlPEVudGl0eVR5cGUgZXh0ZW5kcyBCYXNlRW50aXR5VHlwZTxFbnRpdHlUeXBlPj4ge1xuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIHVybCB1c2VkIGZvciBhcGkgcmVxdWVzdHMuIElmIHUgd2FudCB0byBoYXZlIG1vcmUgY29udHJvbCBvdmVyIHRoaXMsXG4gICAgICogeW91IGNhbiBvdmVycmlkZSB0aGUgY3JlYXRlLCByZWFkLCB1cGRhdGUgYW5kIGRlbGV0ZSBtZXRob2RzLlxuICAgICAqXG4gICAgICogQ3JlYXRlIFNlbmRzIGEgUE9TVC1SZXF1ZXN0IHRvIGJhc2VVcmwuXG4gICAgICpcbiAgICAgKiBSZWFkIFNlbmRzIGEgR0VULVJlcXVlc3QgdG8gYmFzZVVybC5cbiAgICAgKlxuICAgICAqIFVwZGF0ZSBTZW5kcyBhIFBBVENILVJlcXVlc3QgdG8gYmFzZVVybC97aWR9LlxuICAgICAqXG4gICAgICogRGVsZXRlIFNlbmRzIGEgREVMLVJlcXVlc3QgdG8gYmFzZVVybC97aWR9LlxuICAgICAqL1xuICAgIGFic3RyYWN0IHJlYWRvbmx5IGJhc2VVcmw6IHN0cmluZztcbiAgICAvKipcbiAgICAgKiBUaGUga2V5IHdoaWNoIGhvbGRzIHRoZSBpZCB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBkZWZhdWx0ICdpZCdcbiAgICAgKi9cbiAgICByZWFkb25seSBpZEtleToga2V5b2YgRW50aXR5VHlwZSA9ICdpZCcgYXMga2V5b2YgRW50aXR5VHlwZTtcblxuICAgIC8qKlxuICAgICAqIEEgc3ViamVjdCBvZiBhbGwgdGhlIGVudGl0eSB2YWx1ZXMuXG4gICAgICogQ2FuIGJlIHN1YnNjcmliZWQgdG8gd2hlbiB5b3Ugd2FudCB0byBkbyBhIHNwZWNpZmljIHRoaW5nIHdoZW5ldmVyIHRoZSBlbnRpdGllcyBjaGFuZ2UuXG4gICAgICovXG4gICAgcmVhZG9ubHkgZW50aXRpZXNTdWJqZWN0OiBCZWhhdmlvclN1YmplY3Q8RW50aXR5VHlwZVtdPiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8RW50aXR5VHlwZVtdPihbXSk7XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBlbnRpdGllcyBpbiBhbiBhcnJheSBmcm9tIHRoZSBpbnRlcm5hbCBlbnRpdGllc1N1YmplY3QuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgY3VycmVudCBlbnRpdGllcyBpbiBmb3JtIG9mIGFuIGFycmF5LlxuICAgICAqL1xuICAgIGdldCBlbnRpdGllcygpOiBFbnRpdHlUeXBlW10ge1xuICAgICAgICByZXR1cm4gdGhpcy5lbnRpdGllc1N1YmplY3QudmFsdWU7XG4gICAgfVxuXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBodHRwOiBIdHRwQ2xpZW50KSB7fVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBFbnRpdHkgYW5kIHB1c2hlcyBpdCB0byB0aGUgZW50aXRpZXMgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gVGhlIGRhdGEgb2YgdGhlIGVudGl0eSB0byBjcmVhdGUuXG4gICAgICogQWxsIHZhbHVlcyB0aGF0IHNob3VsZCBiZSBvbWl0dGVkIHdpbGwgYmUgcmVtb3ZlZCBmcm9tIGl0IGluc2lkZSB0aGlzIG1ldGhvZC5cbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2Ugb2YgdGhlIGNyZWF0ZWQgZW50aXR5LlxuICAgICAqL1xuICAgIGFzeW5jIGNyZWF0ZShlbnRpdHk6IEVudGl0eVR5cGUpOiBQcm9taXNlPEVudGl0eVR5cGU+IHtcbiAgICAgICAgY29uc3QgYm9keTogUGFydGlhbDxFbnRpdHlUeXBlPiA9IExvZGFzaFV0aWxpdGllcy5vbWl0KGVudGl0eSwgRW50aXR5VXRpbGl0aWVzLmdldE9taXRGb3JDcmVhdGUoZW50aXR5KSkgYXMgUGFydGlhbDxFbnRpdHlUeXBlPjtcbiAgICAgICAgY29uc3QgZmlsZVByb3BlcnR5S2V5czogKGtleW9mIEVudGl0eVR5cGUpW10gPSBFbnRpdHlVdGlsaXRpZXMuZ2V0RmlsZVByb3BlcnRpZXMoZW50aXR5KTtcbiAgICAgICAgaWYgKCFmaWxlUHJvcGVydHlLZXlzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuY3JlYXRlV2l0aEpzb24oYm9keSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5jcmVhdGVXaXRoRm9ybURhdGEoYm9keSwgZmlsZVByb3BlcnR5S2V5cywgZW50aXR5KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRPRE86IEZpbmQgYSB3YXkgdG8gdXNlIGJsb2JzIHdpdGggamVzdFxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyB0aGUgZW50aXR5IHdpdGggZm9ybSBkYXRhIHdoZW4gdGhlIGVudGl0eSBjb250YWlucyBmaWxlcyBpbiBjb250cmFzdCB0byBjcmVhdGluZyBpdCB3aXRoIGEgbm9ybWFsIGpzb24gYm9keS5cbiAgICAgKiBBbGwgZmlsZSB2YWx1ZXMgYXJlIHN0b3JlZCBpbnNpZGUgdGhlaXIgcmVzcGVjdGl2ZSBwcm9wZXJ0eSBrZXkgYW5kIHRoZWlyIG5hbWUuXG4gICAgICogRm9ybSBkYXRhIGlzIGFibGUgdG8gaGFuZGxlIHNldHRpbmcgbXVsdGlwbGUgZmlsZXMgdG8gdGhlIHNhbWUga2V5LlxuICAgICAqXG4gICAgICogQHBhcmFtIGJvZHkgLSBUaGUgYm9keSBPZiB0aGUgcmVxdWVzdC5cbiAgICAgKiBAcGFyYW0gZmlsZVByb3BlcnR5S2V5cyAtIEFsbCBwcm9wZXJ0eSBrZXlzIHRoYXQgYXJlIGZpbGVzIGFuZCBuZWVkIHRvIGJlIGFkZGVkIHRvIHRoZSBmb3JtIGRhdGEuXG4gICAgICogQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgdG8gY3JlYXRlLiBUaGlzIGlzIG5lZWRlZCBpbiBhZGRpdGlvbiB0byB0aGUgYm9keSBiZWNhdXNlIHRoZSBib2R5IGRvZXNuJ3QgY29udGFpbiBhbnkgbWV0YWRhdGEuXG4gICAgICogQHJldHVybnMgVGhlIGNyZWF0ZWQgZW50aXR5IGZyb20gdGhlIHNlcnZlci5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgYXN5bmMgY3JlYXRlV2l0aEZvcm1EYXRhKFxuICAgICAgICBib2R5OiBQYXJ0aWFsPEVudGl0eVR5cGU+LFxuICAgICAgICBmaWxlUHJvcGVydHlLZXlzOiAoa2V5b2YgRW50aXR5VHlwZSlbXSxcbiAgICAgICAgZW50aXR5OiBFbnRpdHlUeXBlXG4gICAgKTogUHJvbWlzZTxFbnRpdHlUeXBlPiB7XG4gICAgICAgIGNvbnN0IGZvcm1EYXRhOiBGb3JtRGF0YSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICBmb3JtRGF0YS5hcHBlbmQoJ2JvZHknLCBKU09OLnN0cmluZ2lmeShMb2Rhc2hVdGlsaXRpZXMub21pdChib2R5LCBmaWxlUHJvcGVydHlLZXlzKSkpO1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBmaWxlUHJvcGVydHlLZXlzKSB7XG4gICAgICAgICAgICBpZiAoRW50aXR5VXRpbGl0aWVzLmdldFByb3BlcnR5TWV0YWRhdGEoZW50aXR5LCBrZXksIERlY29yYXRvclR5cGVzLkZJTEVfREVGQVVMVCkubXVsdGlwbGUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmaWxlRGF0YVZhbHVlczogRmlsZURhdGFbXSA9IGJvZHlba2V5XSBhcyBGaWxlRGF0YVtdO1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgdmFsdWUgb2YgZmlsZURhdGFWYWx1ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9ybURhdGEuYXBwZW5kKGtleSBhcyBzdHJpbmcsIChhd2FpdCBGaWxlVXRpbGl0aWVzLmdldEZpbGVEYXRhKHZhbHVlKSkuZmlsZSwgdmFsdWUubmFtZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZmlsZURhdGE6IEZpbGVEYXRhID0gYm9keVtrZXldIGFzIEZpbGVEYXRhO1xuICAgICAgICAgICAgICAgIGZvcm1EYXRhLmFwcGVuZChrZXkgYXMgc3RyaW5nLCAoYXdhaXQgRmlsZVV0aWxpdGllcy5nZXRGaWxlRGF0YShmaWxlRGF0YSkpLmZpbGUsIGZpbGVEYXRhLm5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGU6IEVudGl0eVR5cGUgfCB1bmRlZmluZWQgPSBhd2FpdCBmaXJzdFZhbHVlRnJvbSh0aGlzLmh0dHAucG9zdDxFbnRpdHlUeXBlIHwgdW5kZWZpbmVkPih0aGlzLmJhc2VVcmwsIGZvcm1EYXRhKSk7XG4gICAgICAgIGlmICghZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBcbiAgICAgICAgICAgICAgICBUaGUgY3JlYXRlZCBlbnRpdHkgd2FzIG5vdCByZXR1cm5lZCBpbiB0aGUgcmVzcG9uc2UuXG4gICAgICAgICAgICAgICAgSWYgeW91IHdhbnQgdG8gcHJvdmlkZSBhIGxvZ2ljIHRoYXQgYWxsb3dzIHRoYXRcbiAgICAgICAgICAgICAgICB5b3UgbmVlZCB0byBvdmVycmlkZSB0aGUgY3JlYXRlIG1ldGhvZHMgb2YgdGhpcyBjbGFzcy5cbiAgICAgICAgICAgIGApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZW50aXRpZXMucHVzaChlKTtcbiAgICAgICAgdGhpcy5lbnRpdGllc1N1YmplY3QubmV4dCh0aGlzLmVudGl0aWVzKTtcbiAgICAgICAgcmV0dXJuIGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyB0aGUgZW50aXR5IHdpdGggYSBub3JtYWwganNvbiBib2R5IGluIGNvbnRyYXN0IHRvIGNyZWF0aW5nIGl0IHdpdGggZm9ybSBkYXRhIHdoZW4gdGhlIGVudGl0eSBjb250YWlucyBmaWxlcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBib2R5IC0gVGhlIGJvZHkgT2YgdGhlIHJlcXVlc3QuXG4gICAgICogQHJldHVybnMgVGhlIGNyZWF0ZWQgZW50aXR5IGZyb20gdGhlIHNlcnZlci5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgYXN5bmMgY3JlYXRlV2l0aEpzb24oYm9keTogUGFydGlhbDxFbnRpdHlUeXBlPik6IFByb21pc2U8RW50aXR5VHlwZT4ge1xuICAgICAgICBjb25zdCBlOiBFbnRpdHlUeXBlIHwgdW5kZWZpbmVkID0gYXdhaXQgZmlyc3RWYWx1ZUZyb20odGhpcy5odHRwLnBvc3Q8RW50aXR5VHlwZSB8IHVuZGVmaW5lZD4odGhpcy5iYXNlVXJsLCBib2R5KSk7XG4gICAgICAgIGlmICghZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBcbiAgICAgICAgICAgICAgICBUaGUgY3JlYXRlZCBlbnRpdHkgd2FzIG5vdCByZXR1cm5lZCBpbiB0aGUgcmVzcG9uc2UuXG4gICAgICAgICAgICAgICAgSWYgeW91IHdhbnQgdG8gcHJvdmlkZSBhIGxvZ2ljIHRoYXQgYWxsb3dzIHRoYXRcbiAgICAgICAgICAgICAgICB5b3UgbmVlZCB0byBvdmVycmlkZSB0aGUgY3JlYXRlIG1ldGhvZHMgb2YgdGhpcyBjbGFzcy5cbiAgICAgICAgICAgIGApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZW50aXRpZXMucHVzaChlKTtcbiAgICAgICAgdGhpcy5lbnRpdGllc1N1YmplY3QubmV4dCh0aGlzLmVudGl0aWVzKTtcbiAgICAgICAgcmV0dXJuIGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhbGwgZXhpc3RpbmcgZW50aXRpZXMgYW5kIHB1c2hlcyB0aGVtIHRvIHRoZSBlbnRpdGllcyBhcnJheS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEEgUHJvbWlzZSBvZiBhbGwgcmVjZWl2ZWQgRW50aXRpZXMuXG4gICAgICovXG4gICAgYXN5bmMgcmVhZCgpOiBQcm9taXNlPEVudGl0eVR5cGVbXT4ge1xuICAgICAgICBjb25zdCBlOiBFbnRpdHlUeXBlW10gPSBhd2FpdCBmaXJzdFZhbHVlRnJvbSh0aGlzLmh0dHAuZ2V0PEVudGl0eVR5cGVbXT4odGhpcy5iYXNlVXJsKSk7XG4gICAgICAgIHRoaXMuZW50aXRpZXNTdWJqZWN0Lm5leHQoZSk7XG4gICAgICAgIHJldHVybiBlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZXMgYSBzcGVjaWZpYyBFbnRpdHkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW50aXR5IC0gVGhlIHVwZGF0ZWQgRW50aXR5XG4gICAgICogQWxsIHZhbHVlcyB0aGF0IHNob3VsZCBiZSBvbWl0dGVkIHdpbGwgYmUgcmVtb3ZlZCBmcm9tIGl0IGluc2lkZSB0aGlzIG1ldGhvZC5cbiAgICAgKiBAcGFyYW0gZW50aXR5UHJpb3JDaGFuZ2VzIC0gVGhlIGN1cnJlbnQgRW50aXR5LlxuICAgICAqIEl0IElzIHVzZWQgdG8gZ2V0IGNoYW5nZWQgdmFsdWVzIGFuZCBvbmx5IHVwZGF0ZSB0aGVtIGluc3RlYWQgb2Ygc2VuZGluZyB0aGUgd2hvbGUgZW50aXR5IGRhdGEuXG4gICAgICovXG4gICAgYXN5bmMgdXBkYXRlKGVudGl0eTogRW50aXR5VHlwZSwgZW50aXR5UHJpb3JDaGFuZ2VzOiBFbnRpdHlUeXBlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGJvZHk6IFBhcnRpYWw8RW50aXR5VHlwZT4gPSBMb2Rhc2hVdGlsaXRpZXMub21pdChcbiAgICAgICAgICAgIGF3YWl0IEVudGl0eVV0aWxpdGllcy5kaWZmZXJlbmNlKGVudGl0eSwgZW50aXR5UHJpb3JDaGFuZ2VzKSxcbiAgICAgICAgICAgIEVudGl0eVV0aWxpdGllcy5nZXRPbWl0Rm9yVXBkYXRlKGVudGl0eSlcbiAgICAgICAgKSBhcyB1bmtub3duIGFzIFBhcnRpYWw8RW50aXR5VHlwZT47XG4gICAgICAgIGNvbnN0IGZpbGVQcm9wZXJ0eUtleXM6IChrZXlvZiBFbnRpdHlUeXBlKVtdID0gRW50aXR5VXRpbGl0aWVzLmdldEZpbGVQcm9wZXJ0aWVzKGVudGl0eVByaW9yQ2hhbmdlcyk7XG4gICAgICAgIGlmICghZmlsZVByb3BlcnR5S2V5cy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMudXBkYXRlV2l0aEpzb24oYm9keSwgZW50aXR5UHJpb3JDaGFuZ2VzW3RoaXMuaWRLZXldKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMudXBkYXRlV2l0aEZvcm1EYXRhKGJvZHksIGZpbGVQcm9wZXJ0eUtleXMsIGVudGl0eSwgZW50aXR5UHJpb3JDaGFuZ2VzW3RoaXMuaWRLZXldKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRPRE86IEZpbmQgYSB3YXkgdG8gdXNlIGJsb2JzIHdpdGggamVzdFxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUgZW50aXR5IHdpdGggZm9ybSBkYXRhIHdoZW4gdGhlIGVudGl0eSBjb250YWlucyBmaWxlcyBpbiBjb250cmFzdCB0byBjcmVhdGluZyBpdCB3aXRoIGEgbm9ybWFsIGpzb24gYm9keS5cbiAgICAgKiBBbGwgZmlsZSB2YWx1ZXMgYXJlIHN0b3JlZCBpbnNpZGUgdGhlaXIgcmVzcGVjdGl2ZSBwcm9wZXJ0eSBrZXkgYW5kIHRoZWlyIG5hbWUuXG4gICAgICogRm9ybSBkYXRhIGlzIGFibGUgdG8gaGFuZGxlIHNldHRpbmcgbXVsdGlwbGUgZmlsZXMgdG8gdGhlIHNhbWUga2V5LlxuICAgICAqXG4gICAgICogQHBhcmFtIGJvZHkgLSBUaGUgcmVxdWVzdCBib2R5LiBBbHJlYWR5IGNvbnRhaW5zIG9ubHkgcHJvcGVydGllcyB0aGF0IGhhdmUgY2hhbmdlZC5cbiAgICAgKiBAcGFyYW0gZmlsZVByb3BlcnR5S2V5cyAtIFRoZSBrZXlzIG9mIGFsbCBwcm9wZXJ0aWVzIHdoaWNoIGFyZSBmaWxlcyBhbmQgbmVlZCB0byBzZXBhcmF0ZWx5IGJlIGFwcGVuZGVkIHRvIHRoZSBmb3JtIGRhdGEuXG4gICAgICogQHBhcmFtIGVudGl0eSAtIFRoZSBvcmlnaW5hbCBlbnRpdHkuIElzIG5lZWRlZCB0byBnZXQgdGhlIG1ldGFkYXRhIG9mIGFsbCB0aGUgZmlsZXMuXG4gICAgICogQHBhcmFtIGlkIC0gVGhlIGlkIG9mIHRoZSBlbnRpdHkgdG8gdXBkYXRlLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBhc3luYyB1cGRhdGVXaXRoRm9ybURhdGEoXG4gICAgICAgIGJvZHk6IFBhcnRpYWw8RW50aXR5VHlwZT4sXG4gICAgICAgIGZpbGVQcm9wZXJ0eUtleXM6IChrZXlvZiBFbnRpdHlUeXBlKVtdLFxuICAgICAgICBlbnRpdHk6IEVudGl0eVR5cGUsXG4gICAgICAgIGlkOiBFbnRpdHlUeXBlW2tleW9mIEVudGl0eVR5cGVdXG4gICAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGZvcm1EYXRhOiBGb3JtRGF0YSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICBmb3JtRGF0YS5hcHBlbmQoJ2JvZHknLCBKU09OLnN0cmluZ2lmeShMb2Rhc2hVdGlsaXRpZXMub21pdEJ5KGJvZHksIExvZGFzaFV0aWxpdGllcy5pc05pbCkpKTtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgZmlsZVByb3BlcnR5S2V5cykge1xuICAgICAgICAgICAgaWYgKEVudGl0eVV0aWxpdGllcy5nZXRQcm9wZXJ0eU1ldGFkYXRhKGVudGl0eSwga2V5LCBEZWNvcmF0b3JUeXBlcy5GSUxFX0RFRkFVTFQpLm11bHRpcGxlKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZmlsZURhdGFWYWx1ZXM6IEZpbGVEYXRhW10gPSBib2R5W2tleV0gYXMgRmlsZURhdGFbXTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHZhbHVlIG9mIGZpbGVEYXRhVmFsdWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvcm1EYXRhLmFwcGVuZChrZXkgYXMgc3RyaW5nLCAoYXdhaXQgRmlsZVV0aWxpdGllcy5nZXRGaWxlRGF0YSh2YWx1ZSkpLmZpbGUsIHZhbHVlLm5hbWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpbGVEYXRhOiBGaWxlRGF0YSA9IGJvZHlba2V5XSBhcyBGaWxlRGF0YTtcbiAgICAgICAgICAgICAgICBmb3JtRGF0YS5hcHBlbmQoa2V5IGFzIHN0cmluZywgKGF3YWl0IEZpbGVVdGlsaXRpZXMuZ2V0RmlsZURhdGEoZmlsZURhdGEpKS5maWxlLCBmaWxlRGF0YS5uYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCB1cGRhdGVkRW50aXR5OiBFbnRpdHlUeXBlIHwgdW5kZWZpbmVkID0gYXdhaXQgZmlyc3RWYWx1ZUZyb20oXG4gICAgICAgICAgICB0aGlzLmh0dHAucGF0Y2g8RW50aXR5VHlwZSB8IHVuZGVmaW5lZD4oYCR7dGhpcy5iYXNlVXJsfS8ke2lkfWAsIGZvcm1EYXRhKVxuICAgICAgICApO1xuICAgICAgICBpZiAoIXVwZGF0ZWRFbnRpdHkpIHtcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1RoZSB1cGRhdGVkIGVudGl0eSB3YXMgbm90IHJldHVybmVkIGluIHRoZSByZXNwb25zZS4gQXBwbHlpbmcgdGhlIGNoYW5nZXMgZnJvbSB0aGUgcmVxdWVzdCBib2R5LicpO1xuICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gYm9keSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW50aXRpZXNbdGhpcy5lbnRpdGllcy5maW5kSW5kZXgoZSA9PiBlW3RoaXMuaWRLZXldID09PSBpZCldW2tleV1cbiAgICAgICAgICAgICAgICAgICAgPSBib2R5W2tleV0gYXMgRW50aXR5VHlwZVtFeHRyYWN0PGtleW9mIEVudGl0eVR5cGUsIHN0cmluZz5dO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5lbnRpdGllc1N1YmplY3QubmV4dCh0aGlzLmVudGl0aWVzKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmVudGl0aWVzW3RoaXMuZW50aXRpZXMuZmluZEluZGV4KGUgPT4gZVt0aGlzLmlkS2V5XSA9PT0gaWQpXSA9IHVwZGF0ZWRFbnRpdHk7XG4gICAgICAgIHRoaXMuZW50aXRpZXNTdWJqZWN0Lm5leHQodGhpcy5lbnRpdGllcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUgZW50aXR5IHdpdGggYSBub3JtYWwganNvbiBib2R5IGluIGNvbnRyYXN0IHRvIHVwZGF0aW5nIGl0IHdpdGggZm9ybSBkYXRhIHdoZW4gdGhlIGVudGl0eSBjb250YWlucyBmaWxlcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBib2R5IC0gVGhlIGJvZHkgb2YgdGhlIFJlcXVlc3QuIEhhcyBhbHJlYWR5IHJlbW92ZWQgYWxsIHVubmVjZXNzYXJ5IHZhbHVlcy5cbiAgICAgKiBAcGFyYW0gaWQgLSBUaGUgaWQgb2YgdGhlIGVudGl0eSB0byB1cGRhdGUuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGFzeW5jIHVwZGF0ZVdpdGhKc29uKGJvZHk6IFBhcnRpYWw8RW50aXR5VHlwZT4sIGlkOiBFbnRpdHlUeXBlW2tleW9mIEVudGl0eVR5cGVdKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHVwZGF0ZWRFbnRpdHk6IEVudGl0eVR5cGUgfCB1bmRlZmluZWQgPSBhd2FpdCBmaXJzdFZhbHVlRnJvbShcbiAgICAgICAgICAgIHRoaXMuaHR0cC5wYXRjaDxFbnRpdHlUeXBlIHwgdW5kZWZpbmVkPihcbiAgICAgICAgICAgICAgICBgJHt0aGlzLmJhc2VVcmx9LyR7aWR9YCxcbiAgICAgICAgICAgICAgICBMb2Rhc2hVdGlsaXRpZXMub21pdEJ5KGJvZHksIExvZGFzaFV0aWxpdGllcy5pc05pbClcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKCF1cGRhdGVkRW50aXR5KSB7XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdUaGUgdXBkYXRlZCBlbnRpdHkgd2FzIG5vdCByZXR1cm5lZCBpbiB0aGUgcmVzcG9uc2UuIEFwcGx5aW5nIHRoZSBjaGFuZ2VzIGZyb20gdGhlIHJlcXVlc3QgYm9keS4nKTtcbiAgICAgICAgICAgIGNvbnN0IGZvdW5kRW50aXR5OiBFbnRpdHlUeXBlID0gdGhpcy5lbnRpdGllc1t0aGlzLmVudGl0aWVzLmZpbmRJbmRleChlID0+IGVbdGhpcy5pZEtleV0gPT09IGlkKV07XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBib2R5KSB7XG4gICAgICAgICAgICAgICAgZm91bmRFbnRpdHlba2V5XVxuICAgICAgICAgICAgICAgICAgICA9IGJvZHlba2V5XSBhcyBFbnRpdHlUeXBlW0V4dHJhY3Q8a2V5b2YgRW50aXR5VHlwZSwgc3RyaW5nPl07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmVudGl0aWVzU3ViamVjdC5uZXh0KHRoaXMuZW50aXRpZXMpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZW50aXRpZXNbdGhpcy5lbnRpdGllcy5maW5kSW5kZXgoZSA9PiBlW3RoaXMuaWRLZXldID09PSBpZCldID0gdXBkYXRlZEVudGl0eTtcbiAgICAgICAgdGhpcy5lbnRpdGllc1N1YmplY3QubmV4dCh0aGlzLmVudGl0aWVzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZWxldGVzIGEgc3BlY2lmaWMgRW50aXR5LlxuICAgICAqXG4gICAgICogQHBhcmFtIGVudGl0eSAtIFRoZSBlbnRpdHkgdG8gZGVsZXRlLlxuICAgICAqL1xuICAgIGFzeW5jIGRlbGV0ZShlbnRpdHk6IEVudGl0eVR5cGUpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgZmlyc3RWYWx1ZUZyb20odGhpcy5odHRwLmRlbGV0ZTx2b2lkPihgJHt0aGlzLmJhc2VVcmx9LyR7ZW50aXR5W3RoaXMuaWRLZXldfWApKTtcbiAgICAgICAgLy8gdGhlID09IGNvbXBhcmlzb24gaW5zdGVhZCBvZiA9PT0gaXMgdG8gY2F0Y2ggaWRzIHRoYXQgYXJlIG51bWJlcnMuXG4gICAgICAgIHRoaXMuZW50aXRpZXMuc3BsaWNlKHRoaXMuZW50aXRpZXMuZmluZEluZGV4KGUgPT4gZVt0aGlzLmlkS2V5XSA9PT0gZW50aXR5W3RoaXMuaWRLZXldKSwgMSk7XG4gICAgICAgIHRoaXMuZW50aXRpZXNTdWJqZWN0Lm5leHQodGhpcy5lbnRpdGllcyk7XG4gICAgfVxufSJdfQ==