ngx-dynamic-entity 1.3.0 → 1.4.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.
Files changed (91) hide show
  1. package/README.md +14 -0
  2. package/fesm2022/ngx-dynamic-entity.mjs +228 -150
  3. package/fesm2022/ngx-dynamic-entity.mjs.map +1 -1
  4. package/package.json +6 -7
  5. package/types/ngx-dynamic-entity.d.ts +1719 -0
  6. package/esm2022/lib/field-types/array-field.component.mjs +0 -168
  7. package/esm2022/lib/field-types/boolean-field.component.mjs +0 -101
  8. package/esm2022/lib/field-types/checkbox-field.component.mjs +0 -82
  9. package/esm2022/lib/field-types/currency-field.component.mjs +0 -102
  10. package/esm2022/lib/field-types/date-field.component.mjs +0 -91
  11. package/esm2022/lib/field-types/date-time-field.component.mjs +0 -138
  12. package/esm2022/lib/field-types/dropdown-field.component.mjs +0 -176
  13. package/esm2022/lib/field-types/email-field.component.mjs +0 -102
  14. package/esm2022/lib/field-types/entity-ref-field.component.mjs +0 -195
  15. package/esm2022/lib/field-types/field-component.contract.mjs +0 -2
  16. package/esm2022/lib/field-types/file-field.component.mjs +0 -157
  17. package/esm2022/lib/field-types/group-field.component.mjs +0 -89
  18. package/esm2022/lib/field-types/image-field.component.mjs +0 -169
  19. package/esm2022/lib/field-types/month-year-field.component.mjs +0 -152
  20. package/esm2022/lib/field-types/multi-select-field.component.mjs +0 -146
  21. package/esm2022/lib/field-types/number-field.component.mjs +0 -112
  22. package/esm2022/lib/field-types/password-field.component.mjs +0 -110
  23. package/esm2022/lib/field-types/radio-field.component.mjs +0 -153
  24. package/esm2022/lib/field-types/text-field.component.mjs +0 -121
  25. package/esm2022/lib/field-types/textarea-field.component.mjs +0 -85
  26. package/esm2022/lib/field-types/time-field.component.mjs +0 -96
  27. package/esm2022/lib/form/dynamic-field/dynamic-field.component.mjs +0 -152
  28. package/esm2022/lib/form/dynamic-form.component.mjs +0 -899
  29. package/esm2022/lib/form/dynamic-record-form.component.mjs +0 -531
  30. package/esm2022/lib/providers/provide-field-types.mjs +0 -75
  31. package/esm2022/lib/providers/provide-ngx-dynamic-entity.mjs +0 -27
  32. package/esm2022/lib/services/cascade-data.service.mjs +0 -129
  33. package/esm2022/lib/services/config-source.service.mjs +0 -67
  34. package/esm2022/lib/services/entity-ref-cache.mjs +0 -20
  35. package/esm2022/lib/services/entity-ref-registry.service.mjs +0 -31
  36. package/esm2022/lib/services/entity-ref-selection.service.mjs +0 -27
  37. package/esm2022/lib/services/entity-reference.service.mjs +0 -168
  38. package/esm2022/lib/services/field-registry.service.mjs +0 -55
  39. package/esm2022/lib/services/file-upload.service.mjs +0 -89
  40. package/esm2022/lib/services/hook-registry.service.mjs +0 -26
  41. package/esm2022/lib/services/lookup-registry.service.mjs +0 -246
  42. package/esm2022/lib/services/rbac.service.mjs +0 -46
  43. package/esm2022/lib/services/rules-evaluation.service.mjs +0 -27
  44. package/esm2022/lib/services/validation-messages.service.mjs +0 -56
  45. package/esm2022/lib/services/validator-registry.service.mjs +0 -99
  46. package/esm2022/lib/tokens/injection-tokens.mjs +0 -126
  47. package/esm2022/ngx-dynamic-entity.mjs +0 -5
  48. package/esm2022/public-api.mjs +0 -58
  49. package/index.d.ts +0 -5
  50. package/lib/field-types/array-field.component.d.ts +0 -28
  51. package/lib/field-types/boolean-field.component.d.ts +0 -18
  52. package/lib/field-types/checkbox-field.component.d.ts +0 -13
  53. package/lib/field-types/currency-field.component.d.ts +0 -17
  54. package/lib/field-types/date-field.component.d.ts +0 -15
  55. package/lib/field-types/date-time-field.component.d.ts +0 -30
  56. package/lib/field-types/dropdown-field.component.d.ts +0 -34
  57. package/lib/field-types/email-field.component.d.ts +0 -15
  58. package/lib/field-types/entity-ref-field.component.d.ts +0 -49
  59. package/lib/field-types/field-component.contract.d.ts +0 -49
  60. package/lib/field-types/file-field.component.d.ts +0 -25
  61. package/lib/field-types/group-field.component.d.ts +0 -17
  62. package/lib/field-types/image-field.component.d.ts +0 -30
  63. package/lib/field-types/month-year-field.component.d.ts +0 -28
  64. package/lib/field-types/multi-select-field.component.d.ts +0 -27
  65. package/lib/field-types/number-field.component.d.ts +0 -16
  66. package/lib/field-types/password-field.component.d.ts +0 -17
  67. package/lib/field-types/radio-field.component.d.ts +0 -33
  68. package/lib/field-types/text-field.component.d.ts +0 -23
  69. package/lib/field-types/textarea-field.component.d.ts +0 -14
  70. package/lib/field-types/time-field.component.d.ts +0 -27
  71. package/lib/form/dynamic-field/dynamic-field.component.d.ts +0 -78
  72. package/lib/form/dynamic-form.component.d.ts +0 -293
  73. package/lib/form/dynamic-record-form.component.d.ts +0 -199
  74. package/lib/providers/provide-field-types.d.ts +0 -24
  75. package/lib/providers/provide-ngx-dynamic-entity.d.ts +0 -56
  76. package/lib/services/cascade-data.service.d.ts +0 -45
  77. package/lib/services/config-source.service.d.ts +0 -14
  78. package/lib/services/entity-ref-cache.d.ts +0 -27
  79. package/lib/services/entity-ref-registry.service.d.ts +0 -21
  80. package/lib/services/entity-ref-selection.service.d.ts +0 -24
  81. package/lib/services/entity-reference.service.d.ts +0 -49
  82. package/lib/services/field-registry.service.d.ts +0 -32
  83. package/lib/services/file-upload.service.d.ts +0 -27
  84. package/lib/services/hook-registry.service.d.ts +0 -12
  85. package/lib/services/lookup-registry.service.d.ts +0 -94
  86. package/lib/services/rbac.service.d.ts +0 -27
  87. package/lib/services/rules-evaluation.service.d.ts +0 -17
  88. package/lib/services/validation-messages.service.d.ts +0 -43
  89. package/lib/services/validator-registry.service.d.ts +0 -32
  90. package/lib/tokens/injection-tokens.d.ts +0 -134
  91. package/public-api.d.ts +0 -42
@@ -1,246 +0,0 @@
1
- import { Injectable, inject } from '@angular/core';
2
- import { lookupValuesToOptions, normalizeLookupValues, resolveLabel } from '@dynamic-entity/core';
3
- import { LOOKUP_REGISTRY } from '../tokens/injection-tokens';
4
- import * as i0 from "@angular/core";
5
- /** Cache-key field separator. Kept out of template literals so it stays visible in source. */
6
- const SEP = '|';
7
- /**
8
- * LookupRegistryService — the cache in front of consumer-registered master lists.
9
- *
10
- * Three layers, deliberately the same shape as `EntityReferenceService`, because the problem is
11
- * the same: one list is typically used by many fields across many entities.
12
- * 1. **options** — resolved `DropdownOption[]` per (list name, lang).
13
- * 2. **in-flight** — the pending Promise, so N fields on one list trigger one load, not N.
14
- * 3. **labels** — synchronous value → text (parity plan §6.2). This is not a nicety: since
15
- * `viewMode` defaults to true a record opens read-only, so rendering a stored value as
16
- * text is the *first* thing a `listName` field has to do. An async-only registry would
17
- * paint the raw stored value and then flip, on every record open.
18
- *
19
- * A failed load rejects and caches nothing, so one transient error does not serve an empty
20
- * list forever — the same fix made for entity references in phase 5.
21
- */
22
- export class LookupRegistryService {
23
- registry = inject(LOOKUP_REGISTRY, { optional: true }) ?? new Map();
24
- /** `listName|lang` -> resolved options. */
25
- options = new Map();
26
- /** `listName|lang` -> normalised values, so a consumer can reach `code` / `isSystemDefined`. */
27
- values = new Map();
28
- /** Loads in progress, keyed as above. */
29
- inFlight = new Map();
30
- /** `listName|lang|text` -> display text, for the synchronous read-only path. */
31
- labels = new Map();
32
- has(listName) {
33
- return this.registry.has(listName);
34
- }
35
- /**
36
- * Options for a named list, from cache when present.
37
- * Concurrent callers with the same key share one load.
38
- */
39
- async load(listName, lang = 'en') {
40
- const key = this.cacheKey(listName, lang);
41
- const cached = this.options.get(key);
42
- if (cached)
43
- return cached;
44
- const pending = this.inFlight.get(key);
45
- if (pending)
46
- return pending;
47
- const source = this.registry.get(listName);
48
- if (source === undefined)
49
- return [];
50
- const load = this.invoke(source, lang).then(raw => {
51
- const values = normalizeLookupValues(raw);
52
- const options = lookupValuesToOptions(values);
53
- this.values.set(key, values);
54
- this.options.set(key, options);
55
- this.rememberLabels(listName, lang, options);
56
- return options;
57
- });
58
- // Only the `.then` above writes to the cache, and a rejection skips it: the caller still
59
- // gets an empty list, but the next call retries instead of reading a poisoned entry.
60
- const guarded = load
61
- .catch(() => [])
62
- .finally(() => this.inFlight.delete(key));
63
- this.inFlight.set(key, guarded);
64
- return guarded;
65
- }
66
- /** Cached options without triggering a load. `undefined` when not loaded. */
67
- peek(listName, lang = 'en') {
68
- return this.options.get(this.cacheKey(listName, lang));
69
- }
70
- /**
71
- * Cached list values, carrying `_id`, `code`, `isSystemDefined` and `from`.
72
- * The library never reads those; this is the seam for a consumer that needs them.
73
- */
74
- valuesFor(listName, lang = 'en') {
75
- return this.values.get(this.cacheKey(listName, lang));
76
- }
77
- /**
78
- * Display text for a stored value, synchronously. `undefined` when the list has not loaded
79
- * or holds no matching value — the caller keeps its own fallback, which is the stored text.
80
- *
81
- * Every language of an option is indexed, so a record saved under one language renders in
82
- * another: a value stored as `'Aktiv'` resolves to `'Active'` under `lang: 'en'`.
83
- */
84
- labelFor(listName, value, lang = 'en') {
85
- if (!listName || value === null || value === undefined || value === '')
86
- return undefined;
87
- for (const text of this.candidateTexts(value, lang)) {
88
- const hit = this.labels.get(this.labelKey(listName, lang, text));
89
- if (hit)
90
- return hit;
91
- }
92
- return undefined;
93
- }
94
- // ─── Field-level resolution — inline options win, else `listName` ────────────
95
- /** True when this field's options have to come from the registry. */
96
- needsResolve(field) {
97
- return !!field?.listName && !field.options?.length;
98
- }
99
- /**
100
- * The options to render right now, without awaiting: inline options, else whatever the
101
- * registry already holds. Empty on a cold miss — pair with `resolveOptions`.
102
- */
103
- optionsFor(field, lang = 'en') {
104
- if (!field)
105
- return [];
106
- if (field.options?.length)
107
- return field.options;
108
- if (!field.listName)
109
- return [];
110
- return this.peek(field.listName, lang) ?? [];
111
- }
112
- /** The options for a field, loading the named list if needed. */
113
- resolveOptions(field, lang = 'en') {
114
- if (!this.needsResolve(field))
115
- return Promise.resolve(this.optionsFor(field, lang));
116
- return this.load(field.listName, lang);
117
- }
118
- /** Drop everything cached for one list, leaving other lists intact. */
119
- invalidate(listName) {
120
- const prefix = `${listName}${SEP}`;
121
- for (const map of [this.options, this.values, this.inFlight]) {
122
- for (const key of [...map.keys()]) {
123
- if (key.startsWith(prefix))
124
- map.delete(key);
125
- }
126
- }
127
- for (const key of [...this.labels.keys()]) {
128
- if (key.startsWith(prefix))
129
- this.labels.delete(key);
130
- }
131
- }
132
- clear() {
133
- this.options.clear();
134
- this.values.clear();
135
- this.inFlight.clear();
136
- this.labels.clear();
137
- }
138
- // ─── Internals ──────────────────────────────────────────────────────────────
139
- cacheKey(listName, lang) {
140
- return [listName, lang].join(SEP);
141
- }
142
- labelKey(listName, lang, text) {
143
- return [listName, lang, text].join(SEP);
144
- }
145
- /** Index an option under every language it carries, so any stored spelling finds it. */
146
- rememberLabels(listName, lang, options) {
147
- for (const option of options) {
148
- const display = resolveLabel(option, lang);
149
- if (!display)
150
- continue;
151
- for (const text of Object.values(option)) {
152
- if (typeof text === 'string' && text !== '') {
153
- this.labels.set(this.labelKey(listName, lang, text), display);
154
- }
155
- }
156
- }
157
- }
158
- /** The texts a stored value could have been indexed under. */
159
- candidateTexts(value, lang) {
160
- if (typeof value === 'object') {
161
- const texts = Object.values(value).filter((v) => typeof v === 'string' && v !== '');
162
- const resolved = resolveLabel(value, lang);
163
- return resolved ? [resolved, ...texts] : texts;
164
- }
165
- return [String(value)];
166
- }
167
- // ─── Source coercion (values | loader, array | Promise | Observable) ─────────
168
- invoke(source, lang) {
169
- let result;
170
- try {
171
- result = typeof source === 'function' ? source({ lang }) : source;
172
- }
173
- catch (err) {
174
- // Reject rather than resolve empty: `load` must be able to tell failure from an empty
175
- // list, or it would cache the failure.
176
- return Promise.reject(err);
177
- }
178
- return this.toPromise(result);
179
- }
180
- toPromise(result) {
181
- if (Array.isArray(result))
182
- return Promise.resolve(result);
183
- if (this.isSubscribable(result)) {
184
- // First emission wins, so a stream that stays open still resolves the load.
185
- return new Promise((resolve, reject) => {
186
- let settled = false;
187
- const settle = (fn) => {
188
- if (settled)
189
- return;
190
- settled = true;
191
- fn();
192
- };
193
- result.subscribe({
194
- next: value => settle(() => resolve(value ?? [])),
195
- error: err => settle(() => reject(err)),
196
- // Completing without emitting is a legitimate empty list, and is cached.
197
- complete: () => settle(() => resolve([])),
198
- });
199
- });
200
- }
201
- return Promise.resolve(result);
202
- }
203
- isSubscribable(value) {
204
- return (typeof value === 'object' &&
205
- value !== null &&
206
- typeof value.subscribe === 'function');
207
- }
208
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LookupRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
209
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LookupRegistryService, providedIn: 'root' });
210
- }
211
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LookupRegistryService, decorators: [{
212
- type: Injectable,
213
- args: [{ providedIn: 'root' }]
214
- }] });
215
- const hostLastConfig = new WeakMap();
216
- /**
217
- * Point a choice component's `options` signal at the right source (parity plan §6.3).
218
- *
219
- * Called from the `field` / `language` input setters of `dropdown`, `radio` and `multiSelect` —
220
- * the wiring is theirs, the decision is the service's, which is what keeps the field
221
- * five-input contract intact: options are never pushed in as a sixth input.
222
- *
223
- * Setters rather than `ngOnChanges` on purpose. `ngOnChanges` only fires for inputs Angular
224
- * itself sets, so a component whose `field` is assigned directly — which the field specs do,
225
- * and any consumer holding a `ComponentRef` may do — would render no options at all.
226
- *
227
- * Paints synchronously first (inline options, or a warm list), then fills in when a cold list
228
- * lands. The late result is dropped if the field or language changed while it was in flight.
229
- */
230
- export function refreshChoiceOptions(host, lookups) {
231
- const last = hostLastConfig.get(host);
232
- if (last && last.field === host.field && last.lang === host.language) {
233
- return;
234
- }
235
- hostLastConfig.set(host, { field: host.field, lang: host.language });
236
- host.options.set(lookups.optionsFor(host.field, host.language));
237
- if (!lookups.needsResolve(host.field))
238
- return;
239
- const listName = host.field?.listName;
240
- const lang = host.language;
241
- void lookups.resolveOptions(host.field, host.language).then(options => {
242
- if (host.field?.listName === listName && host.language === lang)
243
- host.options.set(options);
244
- });
245
- }
246
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9va3VwLXJlZ2lzdHJ5LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL2xvb2t1cC1yZWdpc3RyeS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUF1QixNQUFNLGVBQWUsQ0FBQztBQVd4RSxPQUFPLEVBQUUscUJBQXFCLEVBQUUscUJBQXFCLEVBQUUsWUFBWSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbEcsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDRCQUE0QixDQUFDOztBQUU3RCw4RkFBOEY7QUFDOUYsTUFBTSxHQUFHLEdBQUcsR0FBRyxDQUFDO0FBRWhCOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBRUgsTUFBTSxPQUFPLHFCQUFxQjtJQUNmLFFBQVEsR0FDdkIsTUFBTSxDQUFDLGVBQWUsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxJQUFJLElBQUksR0FBRyxFQUE0QixDQUFDO0lBRXJGLDJDQUEyQztJQUMxQixPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQTRCLENBQUM7SUFDL0QsZ0dBQWdHO0lBQy9FLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBNkIsQ0FBQztJQUMvRCx5Q0FBeUM7SUFDeEIsUUFBUSxHQUFHLElBQUksR0FBRyxFQUFxQyxDQUFDO0lBQ3pFLGdGQUFnRjtJQUMvRCxNQUFNLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7SUFFcEQsR0FBRyxDQUFDLFFBQWdCO1FBQ2xCLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBZ0IsRUFBRSxJQUFJLEdBQUcsSUFBSTtRQUN0QyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEs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QUFPO0lBRTlDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDO0lBQ3RDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDM0IsS0FBSyxPQUFPLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRTtRQUNwRSxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUUsUUFBUSxLQUFLLFFBQVEsSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLElBQUk7WUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM3RixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBpbmplY3QsIHR5cGUgV3JpdGFibGVTaWduYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB0eXBlIHtcbiAgRHJvcGRvd25PcHRpb24sXG4gIExvb2t1cExpc3RMb2FkZXIsXG4gIExvb2t1cExpc3RSZXN1bHQsXG4gIExvb2t1cExpc3RTb3VyY2UsXG4gIExvb2t1cExpc3RWYWx1ZSxcbiAgTmVzdGVkRmllbGRDb25maWcsXG4gIFJhd0xvb2t1cExpc3RWYWx1ZSxcbiAgU3Vic2NyaWJhYmxlLFxufSBmcm9tICdAZHluYW1pYy1lbnRpdHkvY29yZSc7XG5pbXBvcnQgeyBsb29rdXBWYWx1ZXNUb09wdGlvbnMsIG5vcm1hbGl6ZUxvb2t1cFZhbHVlcywgcmVzb2x2ZUxhYmVsIH0gZnJvbSAnQGR5bmFtaWMtZW50aXR5L2NvcmUnO1xuaW1wb3J0IHsgTE9PS1VQX1JFR0lTVFJZIH0gZnJvbSAnLi4vdG9rZW5zL2luamVjdGlvbi10b2tlbnMnO1xuXG4vKiogQ2FjaGUta2V5IGZpZWxkIHNlcGFyYXRvci4gS2VwdCBvdXQgb2YgdGVtcGxhdGUgbGl0ZXJhbHMgc28gaXQgc3RheXMgdmlzaWJsZSBpbiBzb3VyY2UuICovXG5jb25zdCBTRVAgPSAnfCc7XG5cbi8qKlxuICogTG9va3VwUmVnaXN0cnlTZXJ2aWNlIOKAlCB0aGUgY2FjaGUgaW4gZnJvbnQgb2YgY29uc3VtZXItcmVnaXN0ZXJlZCBtYXN0ZXIgbGlzdHMuXG4gKlxuICogVGhyZWUgbGF5ZXJzLCBkZWxpYmVyYXRlbHkgdGhlIHNhbWUgc2hhcGUgYXMgYEVudGl0eVJlZmVyZW5jZVNlcnZpY2VgLCBiZWNhdXNlIHRoZSBwcm9ibGVtIGlzXG4gKiB0aGUgc2FtZTogb25lIGxpc3QgaXMgdHlwaWNhbGx5IHVzZWQgYnkgbWFueSBmaWVsZHMgYWNyb3NzIG1hbnkgZW50aXRpZXMuXG4gKiAgMS4gKipvcHRpb25zKiog4oCUIHJlc29sdmVkIGBEcm9wZG93bk9wdGlvbltdYCBwZXIgKGxpc3QgbmFtZSwgbGFuZykuXG4gKiAgMi4gKippbi1mbGlnaHQqKiDigJQgdGhlIHBlbmRpbmcgUHJvbWlzZSwgc28gTiBmaWVsZHMgb24gb25lIGxpc3QgdHJpZ2dlciBvbmUgbG9hZCwgbm90IE4uXG4gKiAgMy4gKipsYWJlbHMqKiDigJQgc3luY2hyb25vdXMgdmFsdWUg4oaSIHRleHQgKHBhcml0eSBwbGFuIMKnNi4yKS4gVGhpcyBpcyBub3QgYSBuaWNldHk6IHNpbmNlXG4gKiAgICAgYHZpZXdNb2RlYCBkZWZhdWx0cyB0byB0cnVlIGEgcmVjb3JkIG9wZW5zIHJlYWQtb25seSwgc28gcmVuZGVyaW5nIGEgc3RvcmVkIHZhbHVlIGFzXG4gKiAgICAgdGV4dCBpcyB0aGUgKmZpcnN0KiB0aGluZyBhIGBsaXN0TmFtZWAgZmllbGQgaGFzIHRvIGRvLiBBbiBhc3luYy1vbmx5IHJlZ2lzdHJ5IHdvdWxkXG4gKiAgICAgcGFpbnQgdGhlIHJhdyBzdG9yZWQgdmFsdWUgYW5kIHRoZW4gZmxpcCwgb24gZXZlcnkgcmVjb3JkIG9wZW4uXG4gKlxuICogQSBmYWlsZWQgbG9hZCByZWplY3RzIGFuZCBjYWNoZXMgbm90aGluZywgc28gb25lIHRyYW5zaWVudCBlcnJvciBkb2VzIG5vdCBzZXJ2ZSBhbiBlbXB0eVxuICogbGlzdCBmb3JldmVyIOKAlCB0aGUgc2FtZSBmaXggbWFkZSBmb3IgZW50aXR5IHJlZmVyZW5jZXMgaW4gcGhhc2UgNS5cbiAqL1xuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcbmV4cG9ydCBjbGFzcyBMb29rdXBSZWdpc3RyeVNlcnZpY2Uge1xuICBwcml2YXRlIHJlYWRvbmx5IHJlZ2lzdHJ5ID1cbiAgICBpbmplY3QoTE9PS1VQX1JFR0lTVFJZLCB7IG9wdGlvbmFsOiB0cnVlIH0pID8/IG5ldyBNYXA8c3RyaW5nLCBMb29rdXBMaXN0U291cmNlPigpO1xuXG4gIC8qKiBgbGlzdE5hbWV8bGFuZ2AgLT4gcmVzb2x2ZWQgb3B0aW9ucy4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBvcHRpb25zID0gbmV3IE1hcDxzdHJpbmcsIERyb3Bkb3duT3B0aW9uW10+KCk7XG4gIC8qKiBgbGlzdE5hbWV8bGFuZ2AgLT4gbm9ybWFsaXNlZCB2YWx1ZXMsIHNvIGEgY29uc3VtZXIgY2FuIHJlYWNoIGBjb2RlYCAvIGBpc1N5c3RlbURlZmluZWRgLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHZhbHVlcyA9IG5ldyBNYXA8c3RyaW5nLCBMb29rdXBMaXN0VmFsdWVbXT4oKTtcbiAgLyoqIExvYWRzIGluIHByb2dyZXNzLCBrZXllZCBhcyBhYm92ZS4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBpbkZsaWdodCA9IG5ldyBNYXA8c3RyaW5nLCBQcm9taXNlPERyb3Bkb3duT3B0aW9uW10+PigpO1xuICAvKiogYGxpc3ROYW1lfGxhbmd8dGV4dGAgLT4gZGlzcGxheSB0ZXh0LCBmb3IgdGhlIHN5bmNocm9ub3VzIHJlYWQtb25seSBwYXRoLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGxhYmVscyA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG5cbiAgaGFzKGxpc3ROYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXMobGlzdE5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIE9wdGlvbnMgZm9yIGEgbmFtZWQgbGlzdCwgZnJvbSBjYWNoZSB3aGVuIHByZXNlbnQuXG4gICAqIENvbmN1cnJlbnQgY2FsbGVycyB3aXRoIHRoZSBzYW1lIGtleSBzaGFyZSBvbmUgbG9hZC5cbiAgICovXG4gIGFzeW5jIGxvYWQobGlzdE5hbWU6IHN0cmluZywgbGFuZyA9ICdlbicpOiBQcm9taXNlPERyb3Bkb3duT3B0aW9uW10+IHtcbiAgICBjb25zdCBrZXkgPSB0aGlzLmNhY2hlS2V5KGxpc3ROYW1lLCBsYW5nKTtcblxuICAgIGNvbnN0IGNhY2hlZCA9IHRoaXMub3B0aW9ucy5nZXQoa2V5KTtcbiAgICBpZiAoY2FjaGVkKSByZXR1cm4gY2FjaGVkO1xuXG4gICAgY29uc3QgcGVuZGluZyA9IHRoaXMuaW5GbGlnaHQuZ2V0KGtleSk7XG4gICAgaWYgKHBlbmRpbmcpIHJldHVybiBwZW5kaW5nO1xuXG4gICAgY29uc3Qgc291cmNlID0gdGhpcy5yZWdpc3RyeS5nZXQobGlzdE5hbWUpO1xuICAgIGlmIChzb3VyY2UgPT09IHVuZGVmaW5lZCkgcmV0dXJuIFtdO1xuXG4gICAgY29uc3QgbG9hZCA9IHRoaXMuaW52b2tlKHNvdXJjZSwgbGFuZykudGhlbihyYXcgPT4ge1xuICAgICAgY29uc3QgdmFsdWVzID0gbm9ybWFsaXplTG9va3VwVmFsdWVzKHJhdyk7XG4gICAgICBjb25zdCBvcHRpb25zID0gbG9va3VwVmFsdWVzVG9PcHRpb25zKHZhbHVlcyk7XG4gICAgICB0aGlzLnZhbHVlcy5zZXQoa2V5LCB2YWx1ZXMpO1xuICAgICAgdGhpcy5vcHRpb25zLnNldChrZXksIG9wdGlvbnMpO1xuICAgICAgdGhpcy5yZW1lbWJlckxhYmVscyhsaXN0TmFtZSwgbGFuZywgb3B0aW9ucyk7XG4gICAgICByZXR1cm4gb3B0aW9ucztcbiAgICB9KTtcblxuICAgIC8vIE9ubHkgdGhlIGAudGhlbmAgYWJvdmUgd3JpdGVzIHRvIHRoZSBjYWNoZSwgYW5kIGEgcmVqZWN0aW9uIHNraXBzIGl0OiB0aGUgY2FsbGVyIHN0aWxsXG4gICAgLy8gZ2V0cyBhbiBlbXB0eSBsaXN0LCBidXQgdGhlIG5leHQgY2FsbCByZXRyaWVzIGluc3RlYWQgb2YgcmVhZGluZyBhIHBvaXNvbmVkIGVudHJ5LlxuICAgIGNvbnN0IGd1YXJkZWQgPSBsb2FkXG4gICAgICAuY2F0Y2goKCkgPT4gW10gYXMgRHJvcGRvd25PcHRpb25bXSlcbiAgICAgIC5maW5hbGx5KCgpID0+IHRoaXMuaW5GbGlnaHQuZGVsZXRlKGtleSkpO1xuXG4gICAgdGhpcy5pbkZsaWdodC5zZXQoa2V5LCBndWFyZGVkKTtcbiAgICByZXR1cm4gZ3VhcmRlZDtcbiAgfVxuXG4gIC8qKiBDYWNoZWQgb3B0aW9ucyB3aXRob3V0IHRyaWdnZXJpbmcgYSBsb2FkLiBgdW5kZWZpbmVkYCB3aGVuIG5vdCBsb2FkZWQuICovXG4gIHBlZWsobGlzdE5hbWU6IHN0cmluZywgbGFuZyA9ICdlbicpOiBEcm9wZG93bk9wdGlvbltdIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmdldCh0aGlzLmNhY2hlS2V5KGxpc3ROYW1lLCBsYW5nKSk7XG4gIH1cblxuICAvKipcbiAgICogQ2FjaGVkIGxpc3QgdmFsdWVzLCBjYXJyeWluZyBgX2lkYCwgYGNvZGVgLCBgaXNTeXN0ZW1EZWZpbmVkYCBhbmQgYGZyb21gLlxuICAgKiBUaGUgbGlicmFyeSBuZXZlciByZWFkcyB0aG9zZTsgdGhpcyBpcyB0aGUgc2VhbSBmb3IgYSBjb25zdW1lciB0aGF0IG5lZWRzIHRoZW0uXG4gICAqL1xuICB2YWx1ZXNGb3IobGlzdE5hbWU6IHN0cmluZywgbGFuZyA9ICdlbicpOiBMb29rdXBMaXN0VmFsdWVbXSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzLmdldCh0aGlzLmNhY2hlS2V5KGxpc3ROYW1lLCBsYW5nKSk7XG4gIH1cblxuICAvKipcbiAgICogRGlzcGxheSB0ZXh0IGZvciBhIHN0b3JlZCB2YWx1ZSwgc3luY2hyb25vdXNseS4gYHVuZGVmaW5lZGAgd2hlbiB0aGUgbGlzdCBoYXMgbm90IGxvYWRlZFxuICAgKiBvciBob2xkcyBubyBtYXRjaGluZyB2YWx1ZSDigJQgdGhlIGNhbGxlciBrZWVwcyBpdHMgb3duIGZhbGxiYWNrLCB3aGljaCBpcyB0aGUgc3RvcmVkIHRleHQuXG4gICAqXG4gICAqIEV2ZXJ5IGxhbmd1YWdlIG9mIGFuIG9wdGlvbiBpcyBpbmRleGVkLCBzbyBhIHJlY29yZCBzYXZlZCB1bmRlciBvbmUgbGFuZ3VhZ2UgcmVuZGVycyBpblxuICAgKiBhbm90aGVyOiBhIHZhbHVlIHN0b3JlZCBhcyBgJ0FrdGl2J2AgcmVzb2x2ZXMgdG8gYCdBY3RpdmUnYCB1bmRlciBgbGFuZzogJ2VuJ2AuXG4gICAqL1xuICBsYWJlbEZvcihsaXN0TmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkLCB2YWx1ZTogdW5rbm93biwgbGFuZyA9ICdlbicpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGlmICghbGlzdE5hbWUgfHwgdmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gJycpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgZm9yIChjb25zdCB0ZXh0IG9mIHRoaXMuY2FuZGlkYXRlVGV4dHModmFsdWUsIGxhbmcpKSB7XG4gICAgICBjb25zdCBoaXQgPSB0aGlzLmxhYmVscy5nZXQodGhpcy5sYWJlbEtleShsaXN0TmFtZSwgbGFuZywgdGV4dCkpO1xuICAgICAgaWYgKGhpdCkgcmV0dXJuIGhpdDtcbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8vIOKUgOKUgOKUgCBGaWVsZC1sZXZlbCByZXNvbHV0aW9uIOKAlCBpbmxpbmUgb3B0aW9ucyB3aW4sIGVsc2UgYGxpc3ROYW1lYCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKiogVHJ1ZSB3aGVuIHRoaXMgZmllbGQncyBvcHRpb25zIGhhdmUgdG8gY29tZSBmcm9tIHRoZSByZWdpc3RyeS4gKi9cbiAgbmVlZHNSZXNvbHZlKGZpZWxkOiBOZXN0ZWRGaWVsZENvbmZpZyB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIWZpZWxkPy5saXN0TmFtZSAmJiAhZmllbGQub3B0aW9ucz8ubGVuZ3RoO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBvcHRpb25zIHRvIHJlbmRlciByaWdodCBub3csIHdpdGhvdXQgYXdhaXRpbmc6IGlubGluZSBvcHRpb25zLCBlbHNlIHdoYXRldmVyIHRoZVxuICAgKiByZWdpc3RyeSBhbHJlYWR5IGhvbGRzLiBFbXB0eSBvbiBhIGNvbGQgbWlzcyDigJQgcGFpciB3aXRoIGByZXNvbHZlT3B0aW9uc2AuXG4gICAqL1xuICBvcHRpb25zRm9yKGZpZWxkOiBOZXN0ZWRGaWVsZENvbmZpZyB8IHVuZGVmaW5lZCwgbGFuZyA9ICdlbicpOiBEcm9wZG93bk9wdGlvbltdIHtcbiAgICBpZiAoIWZpZWxkKSByZXR1cm4gW107XG4gICAgaWYgKGZpZWxkLm9wdGlvbnM/Lmxlbmd0aCkgcmV0dXJuIGZpZWxkLm9wdGlvbnM7XG4gICAgaWYgKCFmaWVsZC5saXN0TmFtZSkgcmV0dXJuIFtdO1xuICAgIHJldHVybiB0aGlzLnBlZWsoZmllbGQubGlzdE5hbWUsIGxhbmcpID8/IFtdO1xuICB9XG5cbiAgLyoqIFRoZSBvcHRpb25zIGZvciBhIGZpZWxkLCBsb2FkaW5nIHRoZSBuYW1lZCBsaXN0IGlmIG5lZWRlZC4gKi9cbiAgcmVzb2x2ZU9wdGlvbnMoZmllbGQ6IE5lc3RlZEZpZWxkQ29uZmlnIHwgdW5kZWZpbmVkLCBsYW5nID0gJ2VuJyk6IFByb21pc2U8RHJvcGRvd25PcHRpb25bXT4ge1xuICAgIGlmICghdGhpcy5uZWVkc1Jlc29sdmUoZmllbGQpKSByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMub3B0aW9uc0ZvcihmaWVsZCwgbGFuZykpO1xuICAgIHJldHVybiB0aGlzLmxvYWQoZmllbGQhLmxpc3ROYW1lISwgbGFuZyk7XG4gIH1cblxuICAvKiogRHJvcCBldmVyeXRoaW5nIGNhY2hlZCBmb3Igb25lIGxpc3QsIGxlYXZpbmcgb3RoZXIgbGlzdHMgaW50YWN0LiAqL1xuICBpbnZhbGlkYXRlKGxpc3ROYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBwcmVmaXggPSBgJHtsaXN0TmFtZX0ke1NFUH1gO1xuICAgIGZvciAoY29uc3QgbWFwIG9mIFt0aGlzLm9wdGlvbnMsIHRoaXMudmFsdWVzLCB0aGlzLmluRmxpZ2h0XSkge1xuICAgICAgZm9yIChjb25zdCBrZXkgb2YgWy4uLm1hcC5rZXlzKCldKSB7XG4gICAgICAgIGlmIChrZXkuc3RhcnRzV2l0aChwcmVmaXgpKSBtYXAuZGVsZXRlKGtleSk7XG4gICAgICB9XG4gICAgfVxuICAgIGZvciAoY29uc3Qga2V5IG9mIFsuLi50aGlzLmxhYmVscy5rZXlzKCldKSB7XG4gICAgICBpZiAoa2V5LnN0YXJ0c1dpdGgocHJlZml4KSkgdGhpcy5sYWJlbHMuZGVsZXRlKGtleSk7XG4gICAgfVxuICB9XG5cbiAgY2xlYXIoKTogdm9pZCB7XG4gICAgdGhpcy5vcHRpb25zLmNsZWFyKCk7XG4gICAgdGhpcy52YWx1ZXMuY2xlYXIoKTtcbiAgICB0aGlzLmluRmxpZ2h0LmNsZWFyKCk7XG4gICAgdGhpcy5sYWJlbHMuY2xlYXIoKTtcbiAgfVxuXG4gIC8vIOKUgOKUgOKUgCBJbnRlcm5hbHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJpdmF0ZSBjYWNoZUtleShsaXN0TmFtZTogc3RyaW5nLCBsYW5nOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBbbGlzdE5hbWUsIGxhbmddLmpvaW4oU0VQKTtcbiAgfVxuXG4gIHByaXZhdGUgbGFiZWxLZXkobGlzdE5hbWU6IHN0cmluZywgbGFuZzogc3RyaW5nLCB0ZXh0OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBbbGlzdE5hbWUsIGxhbmcsIHRleHRdLmpvaW4oU0VQKTtcbiAgfVxuXG4gIC8qKiBJbmRleCBhbiBvcHRpb24gdW5kZXIgZXZlcnkgbGFuZ3VhZ2UgaXQgY2Fycmllcywgc28gYW55IHN0b3JlZCBzcGVsbGluZyBmaW5kcyBpdC4gKi9cbiAgcHJpdmF0ZSByZW1lbWJlckxhYmVscyhsaXN0TmFtZTogc3RyaW5nLCBsYW5nOiBzdHJpbmcsIG9wdGlvbnM6IERyb3Bkb3duT3B0aW9uW10pOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IG9wdGlvbiBvZiBvcHRpb25zKSB7XG4gICAgICBjb25zdCBkaXNwbGF5ID0gcmVzb2x2ZUxhYmVsKG9wdGlvbiwgbGFuZyk7XG4gICAgICBpZiAoIWRpc3BsYXkpIGNvbnRpbnVlO1xuICAgICAgZm9yIChjb25zdCB0ZXh0IG9mIE9iamVjdC52YWx1ZXMob3B0aW9uKSkge1xuICAgICAgICBpZiAodHlwZW9mIHRleHQgPT09ICdzdHJpbmcnICYmIHRleHQgIT09ICcnKSB7XG4gICAgICAgICAgdGhpcy5sYWJlbHMuc2V0KHRoaXMubGFiZWxLZXkobGlzdE5hbWUsIGxhbmcsIHRleHQpLCBkaXNwbGF5KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKiBUaGUgdGV4dHMgYSBzdG9yZWQgdmFsdWUgY291bGQgaGF2ZSBiZWVuIGluZGV4ZWQgdW5kZXIuICovXG4gIHByaXZhdGUgY2FuZGlkYXRlVGV4dHModmFsdWU6IHVua25vd24sIGxhbmc6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgICAgY29uc3QgdGV4dHMgPSBPYmplY3QudmFsdWVzKHZhbHVlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KS5maWx0ZXIoXG4gICAgICAgICh2KTogdiBpcyBzdHJpbmcgPT4gdHlwZW9mIHYgPT09ICdzdHJpbmcnICYmIHYgIT09ICcnLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHJlc29sdmVkID0gcmVzb2x2ZUxhYmVsKHZhbHVlIGFzIFJlY29yZDxzdHJpbmcsIHN0cmluZz4sIGxhbmcpO1xuICAgICAgcmV0dXJuIHJlc29sdmVkID8gW3Jlc29sdmVkLCAuLi50ZXh0c10gOiB0ZXh0cztcbiAgICB9XG4gICAgcmV0dXJuIFtTdHJpbmcodmFsdWUpXTtcbiAgfVxuXG4gIC8vIOKUgOKUgOKUgCBTb3VyY2UgY29lcmNpb24gKHZhbHVlcyB8IGxvYWRlciwgYXJyYXkgfCBQcm9taXNlIHwgT2JzZXJ2YWJsZSkg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJpdmF0ZSBpbnZva2Uoc291cmNlOiBMb29rdXBMaXN0U291cmNlLCBsYW5nOiBzdHJpbmcpOiBQcm9taXNlPFJhd0xvb2t1cExpc3RWYWx1ZVtdPiB7XG4gICAgbGV0IHJlc3VsdDogTG9va3VwTGlzdFJlc3VsdDtcbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gdHlwZW9mIHNvdXJjZSA9PT0gJ2Z1bmN0aW9uJyA/IChzb3VyY2UgYXMgTG9va3VwTGlzdExvYWRlcikoeyBsYW5nIH0pIDogc291cmNlO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgLy8gUmVqZWN0IHJhdGhlciB0aGFuIHJlc29sdmUgZW1wdHk6IGBsb2FkYCBtdXN0IGJlIGFibGUgdG8gdGVsbCBmYWlsdXJlIGZyb20gYW4gZW1wdHlcbiAgICAgIC8vIGxpc3QsIG9yIGl0IHdvdWxkIGNhY2hlIHRoZSBmYWlsdXJlLlxuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnRvUHJvbWlzZShyZXN1bHQpO1xuICB9XG5cbiAgcHJpdmF0ZSB0b1Byb21pc2UocmVzdWx0OiBMb29rdXBMaXN0UmVzdWx0KTogUHJvbWlzZTxSYXdMb29rdXBMaXN0VmFsdWVbXT4ge1xuICAgIGlmIChBcnJheS5pc0FycmF5KHJlc3VsdCkpIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVzdWx0KTtcbiAgICBpZiAodGhpcy5pc1N1YnNjcmliYWJsZShyZXN1bHQpKSB7XG4gICAgICAvLyBGaXJzdCBlbWlzc2lvbiB3aW5zLCBzbyBhIHN0cmVhbSB0aGF0IHN0YXlzIG9wZW4gc3RpbGwgcmVzb2x2ZXMgdGhlIGxvYWQuXG4gICAgICByZXR1cm4gbmV3IFByb21pc2U8UmF3TG9va3VwTGlzdFZhbHVlW10+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgbGV0IHNldHRsZWQgPSBmYWxzZTtcbiAgICAgICAgY29uc3Qgc2V0dGxlID0gKGZuOiAoKSA9PiB2b2lkKSA9PiB7XG4gICAgICAgICAgaWYgKHNldHRsZWQpIHJldHVybjtcbiAgICAgICAgICBzZXR0bGVkID0gdHJ1ZTtcbiAgICAgICAgICBmbigpO1xuICAgICAgICB9O1xuICAgICAgICByZXN1bHQuc3Vic2NyaWJlKHtcbiAgICAgICAgICBuZXh0OiB2YWx1ZSA9PiBzZXR0bGUoKCkgPT4gcmVzb2x2ZSh2YWx1ZSA/PyBbXSkpLFxuICAgICAgICAgIGVycm9yOiBlcnIgPT4gc2V0dGxlKCgpID0+IHJlamVjdChlcnIpKSxcbiAgICAgICAgICAvLyBDb21wbGV0aW5nIHdpdGhvdXQgZW1pdHRpbmcgaXMgYSBsZWdpdGltYXRlIGVtcHR5IGxpc3QsIGFuZCBpcyBjYWNoZWQuXG4gICAgICAgICAgY29tcGxldGU6ICgpID0+IHNldHRsZSgoKSA9PiByZXNvbHZlKFtdKSksXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVzdWx0IGFzIFByb21pc2U8UmF3TG9va3VwTGlzdFZhbHVlW10+KTtcbiAgfVxuXG4gIHByaXZhdGUgaXNTdWJzY3JpYmFibGUodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBTdWJzY3JpYmFibGU8UmF3TG9va3VwTGlzdFZhbHVlW10+IHtcbiAgICByZXR1cm4gKFxuICAgICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJlxuICAgICAgdmFsdWUgIT09IG51bGwgJiZcbiAgICAgIHR5cGVvZiAodmFsdWUgYXMgU3Vic2NyaWJhYmxlPFJhd0xvb2t1cExpc3RWYWx1ZVtdPikuc3Vic2NyaWJlID09PSAnZnVuY3Rpb24nXG4gICAgKTtcbiAgfVxufVxuXG4vKiogQSBjaG9pY2UgZmllbGQgY29tcG9uZW50LCBhcyBmYXIgYXMgb3B0aW9uIHJlc29sdXRpb24gaXMgY29uY2VybmVkLiAqL1xuZXhwb3J0IGludGVyZmFjZSBDaG9pY2VPcHRpb25Ib3N0IHtcbiAgcmVhZG9ubHkgZmllbGQ6IE5lc3RlZEZpZWxkQ29uZmlnIHwgdW5kZWZpbmVkO1xuICByZWFkb25seSBsYW5ndWFnZTogc3RyaW5nO1xuICByZWFkb25seSBvcHRpb25zOiBXcml0YWJsZVNpZ25hbDxEcm9wZG93bk9wdGlvbltdPjtcbn1cblxuY29uc3QgaG9zdExhc3RDb25maWcgPSBuZXcgV2Vha01hcDxDaG9pY2VPcHRpb25Ib3N0LCB7IGZpZWxkPzogTmVzdGVkRmllbGRDb25maWc7IGxhbmc/OiBzdHJpbmcgfT4oKTtcblxuLyoqXG4gKiBQb2ludCBhIGNob2ljZSBjb21wb25lbnQncyBgb3B0aW9uc2Agc2lnbmFsIGF0IHRoZSByaWdodCBzb3VyY2UgKHBhcml0eSBwbGFuIMKnNi4zKS5cbiAqXG4gKiBDYWxsZWQgZnJvbSB0aGUgYGZpZWxkYCAvIGBsYW5ndWFnZWAgaW5wdXQgc2V0dGVycyBvZiBgZHJvcGRvd25gLCBgcmFkaW9gIGFuZCBgbXVsdGlTZWxlY3RgIOKAlFxuICogdGhlIHdpcmluZyBpcyB0aGVpcnMsIHRoZSBkZWNpc2lvbiBpcyB0aGUgc2VydmljZSdzLCB3aGljaCBpcyB3aGF0IGtlZXBzIHRoZSBmaWVsZFxuICogZml2ZS1pbnB1dCBjb250cmFjdCBpbnRhY3Q6IG9wdGlvbnMgYXJlIG5ldmVyIHB1c2hlZCBpbiBhcyBhIHNpeHRoIGlucHV0LlxuICpcbiAqIFNldHRlcnMgcmF0aGVyIHRoYW4gYG5nT25DaGFuZ2VzYCBvbiBwdXJwb3NlLiBgbmdPbkNoYW5nZXNgIG9ubHkgZmlyZXMgZm9yIGlucHV0cyBBbmd1bGFyXG4gKiBpdHNlbGYgc2V0cywgc28gYSBjb21wb25lbnQgd2hvc2UgYGZpZWxkYCBpcyBhc3NpZ25lZCBkaXJlY3RseSDigJQgd2hpY2ggdGhlIGZpZWxkIHNwZWNzIGRvLFxuICogYW5kIGFueSBjb25zdW1lciBob2xkaW5nIGEgYENvbXBvbmVudFJlZmAgbWF5IGRvIOKAlCB3b3VsZCByZW5kZXIgbm8gb3B0aW9ucyBhdCBhbGwuXG4gKlxuICogUGFpbnRzIHN5bmNocm9ub3VzbHkgZmlyc3QgKGlubGluZSBvcHRpb25zLCBvciBhIHdhcm0gbGlzdCksIHRoZW4gZmlsbHMgaW4gd2hlbiBhIGNvbGQgbGlzdFxuICogbGFuZHMuIFRoZSBsYXRlIHJlc3VsdCBpcyBkcm9wcGVkIGlmIHRoZSBmaWVsZCBvciBsYW5ndWFnZSBjaGFuZ2VkIHdoaWxlIGl0IHdhcyBpbiBmbGlnaHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWZyZXNoQ2hvaWNlT3B0aW9ucyhob3N0OiBDaG9pY2VPcHRpb25Ib3N0LCBsb29rdXBzOiBMb29rdXBSZWdpc3RyeVNlcnZpY2UpOiB2b2lkIHtcbiAgY29uc3QgbGFzdCA9IGhvc3RMYXN0Q29uZmlnLmdldChob3N0KTtcbiAgaWYgKGxhc3QgJiYgbGFzdC5maWVsZCA9PT0gaG9zdC5maWVsZCAmJiBsYXN0LmxhbmcgPT09IGhvc3QubGFuZ3VhZ2UpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaG9zdExhc3RDb25maWcuc2V0KGhvc3QsIHsgZmllbGQ6IGhvc3QuZmllbGQsIGxhbmc6IGhvc3QubGFuZ3VhZ2UgfSk7XG5cbiAgaG9zdC5vcHRpb25zLnNldChsb29rdXBzLm9wdGlvbnNGb3IoaG9zdC5maWVsZCwgaG9zdC5sYW5ndWFnZSkpO1xuICBpZiAoIWxvb2t1cHMubmVlZHNSZXNvbHZlKGhvc3QuZmllbGQpKSByZXR1cm47XG5cbiAgY29uc3QgbGlzdE5hbWUgPSBob3N0LmZpZWxkPy5saXN0TmFtZTtcbiAgY29uc3QgbGFuZyA9IGhvc3QubGFuZ3VhZ2U7XG4gIHZvaWQgbG9va3Vwcy5yZXNvbHZlT3B0aW9ucyhob3N0LmZpZWxkLCBob3N0Lmxhbmd1YWdlKS50aGVuKG9wdGlvbnMgPT4ge1xuICAgIGlmIChob3N0LmZpZWxkPy5saXN0TmFtZSA9PT0gbGlzdE5hbWUgJiYgaG9zdC5sYW5ndWFnZSA9PT0gbGFuZykgaG9zdC5vcHRpb25zLnNldChvcHRpb25zKTtcbiAgfSk7XG59XG4iXX0=
@@ -1,46 +0,0 @@
1
- import { Injectable, inject } from '@angular/core';
2
- import { shouldMaskField as coreShouldMaskField, resolveEffectiveMask as coreResolveEffectiveMask } from '@dynamic-entity/core';
3
- import { MASKED_ROLES } from '../tokens/injection-tokens';
4
- import * as i0 from "@angular/core";
5
- /**
6
- * RbacService — ALL permission checks and masking logic live here.
7
- */
8
- export class RbacService {
9
- maskedRoles = inject(MASKED_ROLES, { optional: true }) ?? [];
10
- /**
11
- * Check if any of the user's roles satisfy the required roles.
12
- * hasPermission(roles, undefined) → true (no restriction).
13
- */
14
- hasPermission(userRoles, requiredRoles) {
15
- if (!requiredRoles?.length)
16
- return true;
17
- return userRoles.some(r => requiredRoles.includes(r));
18
- }
19
- /** 3-level OR resolution */
20
- resolveEffectiveMask(formMask, tabMask, fieldMask) {
21
- return coreResolveEffectiveMask(formMask, tabMask, fieldMask);
22
- }
23
- /** Check if the user's roles include any masked role */
24
- isUserMaskedRole(userRoles) {
25
- return this.maskedRoles.some(r => userRoles.includes(r));
26
- }
27
- /** Determine if a specific field should be masked for this user */
28
- shouldMaskField(field, tab, config, userRoles) {
29
- return coreShouldMaskField(field, tab, config, userRoles, this.maskedRoles);
30
- }
31
- /** Get view/edit/delete permissions for a config */
32
- getPermissions(config, userRoles) {
33
- return {
34
- canView: this.hasPermission(userRoles, config.permissions?.view),
35
- canEdit: this.hasPermission(userRoles, config.permissions?.edit),
36
- canDelete: this.hasPermission(userRoles, config.permissions?.delete),
37
- };
38
- }
39
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RbacService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
40
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RbacService, providedIn: 'root' });
41
- }
42
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RbacService, decorators: [{
43
- type: Injectable,
44
- args: [{ providedIn: 'root' }]
45
- }] });
46
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmJhYy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy9yYmFjLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFbkQsT0FBTyxFQUFFLGVBQWUsSUFBSSxtQkFBbUIsRUFBRSxvQkFBb0IsSUFBSSx3QkFBd0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2hJLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQzs7QUFFMUQ7O0dBRUc7QUFFSCxNQUFNLE9BQU8sV0FBVztJQUNMLFdBQVcsR0FBRyxNQUFNLENBQUMsWUFBWSxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDO0lBRTlFOzs7T0FHRztJQUNILGFBQWEsQ0FBQyxTQUFtQixFQUFFLGFBQXdCO1FBQ3pELElBQUksQ0FBQyxhQUFhLEVBQUUsTUFBTTtZQUFFLE9BQU8sSUFBSSxDQUFDO1FBQ3hDLE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4RCxDQUFDO0lBRUQsNEJBQTRCO0lBQzVCLG9CQUFvQixDQUFDLFFBQWtCLEVBQUUsT0FBaUIsRUFBRSxTQUFtQjtRQUM3RSxPQUFPLHdCQUF3QixDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUVELHdEQUF3RDtJQUN4RCxnQkFBZ0IsQ0FBQyxTQUFtQjtRQUNsQyxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNELENBQUM7SUFFRCxtRUFBbUU7SUFDbkUsZUFBZSxDQUFDLEtBQXdCLEVBQUUsR0FBZ0MsRUFBRSxNQUF3QixFQUFFLFNBQW1CO1FBQ3ZILE9BQU8sbUJBQW1CLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUM5RSxDQUFDO0lBRUQsb0RBQW9EO0lBQ3BELGNBQWMsQ0FBQyxNQUF3QixFQUFFLFNBQW1CO1FBQzFELE9BQU87WUFDTCxPQUFPLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUM7WUFDaEUsT0FBTyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDO1lBQ2hFLFNBQVMsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsV0FBVyxFQUFFLE1BQU0sQ0FBQztTQUNyRSxDQUFDO0lBQ0osQ0FBQzt3R0FsQ1UsV0FBVzs0R0FBWCxXQUFXLGNBREUsTUFBTTs7NEZBQ25CLFdBQVc7a0JBRHZCLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgdHlwZSB7IEVudGl0eUZvcm1Db25maWcsIE5lc3RlZEZpZWxkQ29uZmlnLCBOZXN0ZWRUYWJDb25maWcgfSBmcm9tICdAZHluYW1pYy1lbnRpdHkvY29yZSc7XG5pbXBvcnQgeyBzaG91bGRNYXNrRmllbGQgYXMgY29yZVNob3VsZE1hc2tGaWVsZCwgcmVzb2x2ZUVmZmVjdGl2ZU1hc2sgYXMgY29yZVJlc29sdmVFZmZlY3RpdmVNYXNrIH0gZnJvbSAnQGR5bmFtaWMtZW50aXR5L2NvcmUnO1xuaW1wb3J0IHsgTUFTS0VEX1JPTEVTIH0gZnJvbSAnLi4vdG9rZW5zL2luamVjdGlvbi10b2tlbnMnO1xuXG4vKipcbiAqIFJiYWNTZXJ2aWNlIOKAlCBBTEwgcGVybWlzc2lvbiBjaGVja3MgYW5kIG1hc2tpbmcgbG9naWMgbGl2ZSBoZXJlLlxuICovXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIFJiYWNTZXJ2aWNlIHtcbiAgcHJpdmF0ZSByZWFkb25seSBtYXNrZWRSb2xlcyA9IGluamVjdChNQVNLRURfUk9MRVMsIHsgb3B0aW9uYWw6IHRydWUgfSkgPz8gW107XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGFueSBvZiB0aGUgdXNlcidzIHJvbGVzIHNhdGlzZnkgdGhlIHJlcXVpcmVkIHJvbGVzLlxuICAgKiBoYXNQZXJtaXNzaW9uKHJvbGVzLCB1bmRlZmluZWQpIOKGkiB0cnVlIChubyByZXN0cmljdGlvbikuXG4gICAqL1xuICBoYXNQZXJtaXNzaW9uKHVzZXJSb2xlczogc3RyaW5nW10sIHJlcXVpcmVkUm9sZXM/OiBzdHJpbmdbXSk6IGJvb2xlYW4ge1xuICAgIGlmICghcmVxdWlyZWRSb2xlcz8ubGVuZ3RoKSByZXR1cm4gdHJ1ZTtcbiAgICByZXR1cm4gdXNlclJvbGVzLnNvbWUociA9PiByZXF1aXJlZFJvbGVzLmluY2x1ZGVzKHIpKTtcbiAgfVxuXG4gIC8qKiAzLWxldmVsIE9SIHJlc29sdXRpb24gKi9cbiAgcmVzb2x2ZUVmZmVjdGl2ZU1hc2soZm9ybU1hc2s/OiBib29sZWFuLCB0YWJNYXNrPzogYm9vbGVhbiwgZmllbGRNYXNrPzogYm9vbGVhbik6IGJvb2xlYW4ge1xuICAgIHJldHVybiBjb3JlUmVzb2x2ZUVmZmVjdGl2ZU1hc2soZm9ybU1hc2ssIHRhYk1hc2ssIGZpZWxkTWFzayk7XG4gIH1cblxuICAvKiogQ2hlY2sgaWYgdGhlIHVzZXIncyByb2xlcyBpbmNsdWRlIGFueSBtYXNrZWQgcm9sZSAqL1xuICBpc1VzZXJNYXNrZWRSb2xlKHVzZXJSb2xlczogc3RyaW5nW10pOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5tYXNrZWRSb2xlcy5zb21lKHIgPT4gdXNlclJvbGVzLmluY2x1ZGVzKHIpKTtcbiAgfVxuXG4gIC8qKiBEZXRlcm1pbmUgaWYgYSBzcGVjaWZpYyBmaWVsZCBzaG91bGQgYmUgbWFza2VkIGZvciB0aGlzIHVzZXIgKi9cbiAgc2hvdWxkTWFza0ZpZWxkKGZpZWxkOiBOZXN0ZWRGaWVsZENvbmZpZywgdGFiOiBOZXN0ZWRUYWJDb25maWcgfCB1bmRlZmluZWQsIGNvbmZpZzogRW50aXR5Rm9ybUNvbmZpZywgdXNlclJvbGVzOiBzdHJpbmdbXSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBjb3JlU2hvdWxkTWFza0ZpZWxkKGZpZWxkLCB0YWIsIGNvbmZpZywgdXNlclJvbGVzLCB0aGlzLm1hc2tlZFJvbGVzKTtcbiAgfVxuXG4gIC8qKiBHZXQgdmlldy9lZGl0L2RlbGV0ZSBwZXJtaXNzaW9ucyBmb3IgYSBjb25maWcgKi9cbiAgZ2V0UGVybWlzc2lvbnMoY29uZmlnOiBFbnRpdHlGb3JtQ29uZmlnLCB1c2VyUm9sZXM6IHN0cmluZ1tdKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNhblZpZXc6IHRoaXMuaGFzUGVybWlzc2lvbih1c2VyUm9sZXMsIGNvbmZpZy5wZXJtaXNzaW9ucz8udmlldyksXG4gICAgICBjYW5FZGl0OiB0aGlzLmhhc1Blcm1pc3Npb24odXNlclJvbGVzLCBjb25maWcucGVybWlzc2lvbnM/LmVkaXQpLFxuICAgICAgY2FuRGVsZXRlOiB0aGlzLmhhc1Blcm1pc3Npb24odXNlclJvbGVzLCBjb25maWcucGVybWlzc2lvbnM/LmRlbGV0ZSksXG4gICAgfTtcbiAgfVxufVxuIl19
@@ -1,27 +0,0 @@
1
- import { Injectable } from '@angular/core';
2
- import { evaluateFormRules, filterRulesForTab } from '@dynamic-entity/core';
3
- import * as i0 from "@angular/core";
4
- /**
5
- * RulesEvaluationService — evaluates dynamic form rules against active reactive form state.
6
- */
7
- export class RulesEvaluationService {
8
- /**
9
- * Evaluate rules against form values and optional original baseline values.
10
- */
11
- evaluate(rules, values, originalValues) {
12
- return evaluateFormRules(rules, values, originalValues);
13
- }
14
- /**
15
- * Filter rules pertinent to a single tab.
16
- */
17
- filterForTab(rules, tabId, config) {
18
- return filterRulesForTab(rules, tabId, config);
19
- }
20
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RulesEvaluationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
21
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RulesEvaluationService, providedIn: 'root' });
22
- }
23
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: RulesEvaluationService, decorators: [{
24
- type: Injectable,
25
- args: [{ providedIn: 'root' }]
26
- }] });
27
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVsZXMtZXZhbHVhdGlvbi5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy9ydWxlcy1ldmFsdWF0aW9uLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUUzQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQzs7QUFFNUU7O0dBRUc7QUFFSCxNQUFNLE9BQU8sc0JBQXNCO0lBQ2pDOztPQUVHO0lBQ0gsUUFBUSxDQUNOLEtBQW9DLEVBQ3BDLE1BQStCLEVBQy9CLGNBQXdDO1FBRXhDLE9BQU8saUJBQWlCLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxjQUFjLENBQUMsQ0FBQztJQUMxRCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxZQUFZLENBQUMsS0FBb0MsRUFBRSxLQUFhLEVBQUUsTUFBd0I7UUFDeEYsT0FBTyxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ2pELENBQUM7d0dBakJVLHNCQUFzQjs0R0FBdEIsc0JBQXNCLGNBRFQsTUFBTTs7NEZBQ25CLHNCQUFzQjtrQkFEbEMsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgdHlwZSB7IEVudGl0eUZvcm1Db25maWcsIEZvcm1SdWxlLCBSdWxlRXZhbHVhdGlvblJlc3VsdCB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcbmltcG9ydCB7IGV2YWx1YXRlRm9ybVJ1bGVzLCBmaWx0ZXJSdWxlc0ZvclRhYiB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcblxuLyoqXG4gKiBSdWxlc0V2YWx1YXRpb25TZXJ2aWNlIOKAlCBldmFsdWF0ZXMgZHluYW1pYyBmb3JtIHJ1bGVzIGFnYWluc3QgYWN0aXZlIHJlYWN0aXZlIGZvcm0gc3RhdGUuXG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgUnVsZXNFdmFsdWF0aW9uU2VydmljZSB7XG4gIC8qKlxuICAgKiBFdmFsdWF0ZSBydWxlcyBhZ2FpbnN0IGZvcm0gdmFsdWVzIGFuZCBvcHRpb25hbCBvcmlnaW5hbCBiYXNlbGluZSB2YWx1ZXMuXG4gICAqL1xuICBldmFsdWF0ZShcbiAgICBydWxlczogRm9ybVJ1bGVbXSB8IHVuZGVmaW5lZCB8IG51bGwsXG4gICAgdmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICBvcmlnaW5hbFZhbHVlcz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICApOiBSdWxlRXZhbHVhdGlvblJlc3VsdCB7XG4gICAgcmV0dXJuIGV2YWx1YXRlRm9ybVJ1bGVzKHJ1bGVzLCB2YWx1ZXMsIG9yaWdpbmFsVmFsdWVzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaWx0ZXIgcnVsZXMgcGVydGluZW50IHRvIGEgc2luZ2xlIHRhYi5cbiAgICovXG4gIGZpbHRlckZvclRhYihydWxlczogRm9ybVJ1bGVbXSB8IHVuZGVmaW5lZCB8IG51bGwsIHRhYklkOiBzdHJpbmcsIGNvbmZpZzogRW50aXR5Rm9ybUNvbmZpZyk6IEZvcm1SdWxlW10ge1xuICAgIHJldHVybiBmaWx0ZXJSdWxlc0ZvclRhYihydWxlcywgdGFiSWQsIGNvbmZpZyk7XG4gIH1cbn1cbiJdfQ==
@@ -1,56 +0,0 @@
1
- import { Injectable, inject } from '@angular/core';
2
- import { VALIDATION_MESSAGES } from '../tokens/injection-tokens';
3
- import * as i0 from "@angular/core";
4
- /** The built-in English messages. Every key here can be overridden individually. */
5
- export const DEFAULT_VALIDATION_MESSAGES = {
6
- required: 'This field is required.',
7
- requiredSelection: 'Please select an option.',
8
- email: 'Please enter a valid email address.',
9
- pattern: 'Invalid format.',
10
- minlength: (_lang, err) => `Minimum ${err?.requiredLength} characters required.`,
11
- maxlength: (_lang, err) => `Maximum ${err?.requiredLength} characters allowed.`,
12
- min: (_lang, err) => `Value must be at least ${err?.min}.`,
13
- max: (_lang, err) => `Value must not exceed ${err?.max}.`,
14
- invalid: 'Invalid value.',
15
- invalidNumber: 'Invalid number.',
16
- invalidSelection: 'Invalid selection.',
17
- };
18
- export class ValidationMessagesService {
19
- overrides = inject(VALIDATION_MESSAGES, { optional: true }) ?? {};
20
- /**
21
- * The message for the first error present, in the order the caller lists.
22
- *
23
- * Order is the caller's because it is field-specific: a dropdown wants
24
- * `requiredSelection` where a text input wants `required`, and the first match wins so the
25
- * most specific message is the one shown.
26
- */
27
- resolve(errors, language, order, fallbackKey = 'invalid') {
28
- if (!errors)
29
- return '';
30
- for (const entry of order) {
31
- // A tuple maps an Angular error key to a different message key: a dropdown raises the
32
- // standard `required` error but reads better as "Please select an option", and both
33
- // messages stay independently overridable.
34
- const [errorKey, messageKey] = typeof entry === 'string' ? [entry, entry] : entry;
35
- // `errors[errorKey]` is usually an object of detail, but `required` is simply `true`.
36
- if (errors[errorKey] === undefined)
37
- continue;
38
- return this.messageFor(messageKey, language, errors[errorKey]);
39
- }
40
- return this.messageFor(fallbackKey, language, null);
41
- }
42
- /** One message by key, honouring an override before the default. */
43
- messageFor(key, language, error) {
44
- const message = this.overrides[key] ?? DEFAULT_VALIDATION_MESSAGES[key];
45
- if (message === undefined)
46
- return '';
47
- return typeof message === 'function' ? message(language, error) : message;
48
- }
49
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ValidationMessagesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
50
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ValidationMessagesService, providedIn: 'root' });
51
- }
52
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ValidationMessagesService, decorators: [{
53
- type: Injectable,
54
- args: [{ providedIn: 'root' }]
55
- }] });
56
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGlvbi1tZXNzYWdlcy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy92YWxpZGF0aW9uLW1lc3NhZ2VzLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFbkQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7O0FBMkJqRSxvRkFBb0Y7QUFDcEYsTUFBTSxDQUFDLE1BQU0sMkJBQTJCLEdBQXNDO0lBQzVFLFFBQVEsRUFBRSx5QkFBeUI7SUFDbkMsaUJBQWlCLEVBQUUsMEJBQTBCO0lBQzdDLEtBQUssRUFBRSxxQ0FBcUM7SUFDNUMsT0FBTyxFQUFFLGlCQUFpQjtJQUMxQixTQUFTLEVBQUUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQyxXQUFXLEdBQUcsRUFBRSxjQUFjLHVCQUF1QjtJQUNoRixTQUFTLEVBQUUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQyxXQUFXLEdBQUcsRUFBRSxjQUFjLHNCQUFzQjtJQUMvRSxHQUFHLEVBQUUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQywwQkFBMEIsR0FBRyxFQUFFLEdBQUcsR0FBRztJQUMxRCxHQUFHLEVBQUUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQyx5QkFBeUIsR0FBRyxFQUFFLEdBQUcsR0FBRztJQUN6RCxPQUFPLEVBQUUsZ0JBQWdCO0lBQ3pCLGFBQWEsRUFBRSxpQkFBaUI7SUFDaEMsZ0JBQWdCLEVBQUUsb0JBQW9CO0NBQ3ZDLENBQUM7QUFHRixNQUFNLE9BQU8seUJBQXlCO0lBQ25CLFNBQVMsR0FBRyxNQUFNLENBQUMsbUJBQW1CLEVBQUUsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUM7SUFFbkY7Ozs7OztPQU1HO0lBQ0gsT0FBTyxDQUNMLE1BQTJDLEVBQzNDLFFBQWdCLEVBQ2hCLEtBQTRFLEVBQzVFLFdBQVcsR0FBRyxTQUFTO1FBRXZCLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTyxFQUFFLENBQUM7UUFFdkIsS0FBSyxNQUFNLEtBQUssSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUMxQixzRkFBc0Y7WUFDdEYsb0ZBQW9GO1lBQ3BGLDJDQUEyQztZQUMzQyxNQUFNLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxHQUFHLE9BQU8sS0FBSyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztZQUNsRixzRkFBc0Y7WUFDdEYsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssU0FBUztnQkFBRSxTQUFTO1lBQzdDLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxVQUFVLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRUQsb0VBQW9FO0lBQ3BFLFVBQVUsQ0FBQyxHQUFXLEVBQUUsUUFBZ0IsRUFBRSxLQUFjO1FBQ3RELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLElBQUksMkJBQTJCLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDeEUsSUFBSSxPQUFPLEtBQUssU0FBUztZQUFFLE9BQU8sRUFBRSxDQUFDO1FBQ3JDLE9BQU8sT0FBTyxPQUFPLEtBQUssVUFBVSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7SUFDNUUsQ0FBQzt3R0FuQ1UseUJBQXlCOzRHQUF6Qix5QkFBeUIsY0FEWixNQUFNOzs0RkFDbkIseUJBQXlCO2tCQURyQyxVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHR5cGUgeyBWYWxpZGF0aW9uRXJyb3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgVkFMSURBVElPTl9NRVNTQUdFUyB9IGZyb20gJy4uL3Rva2Vucy9pbmplY3Rpb24tdG9rZW5zJztcblxuLyoqXG4gKiBSZXNvbHZlcyBhbiBBbmd1bGFyIGBWYWxpZGF0aW9uRXJyb3JzYCBvYmplY3QgdG8gdGhlIG1lc3NhZ2Ugc2hvd24gdW5kZXIgYSBmaWVsZC5cbiAqXG4gKiBUaGVzZSBzdHJpbmdzIHVzZWQgdG8gYmUgaGFyZGNvZGVkIEVuZ2xpc2ggbGl0ZXJhbHMgaW5zaWRlIGVhY2ggZmllbGQgY29tcG9uZW50LCBzbyBhXG4gKiBHZXJtYW4gZm9ybSBtZWFudCByZS1pbXBsZW1lbnRpbmcgZXZlcnkgZmllbGQgdHlwZSDigJQgdGhlIGxhYmVscyBob25vdXJlZCBgbGFuZ3VhZ2VgIHdoaWxlXG4gKiB0aGUgZXJyb3JzIHVuZGVybmVhdGggdGhlbSBkaWQgbm90LlxuICpcbiAqIEEgbWVzc2FnZSBpcyBhIHBsYWluIHN0cmluZywgb3IgYSBmdW5jdGlvbiB3aGVuIGl0IG5lZWRzIHRoZSBlcnJvcidzIG93biBkZXRhaWxcbiAqIChgbWlubGVuZ3RoLnJlcXVpcmVkTGVuZ3RoYCwgYG1pbi5taW5gLCBhbmQgc28gb24pLiBUaGUgYWN0aXZlIGBsYW5ndWFnZWAgaXMgcGFzc2VkXG4gKiB0aHJvdWdoLCBzbyBvbmUgcmVnaXN0cmF0aW9uIGNhbiBzZXJ2ZSBldmVyeSBsb2NhbGU6XG4gKlxuICogYGBgdHlwZXNjcmlwdFxuICogcHJvdmlkZU5neER5bmFtaWNFbnRpdHkoe1xuICogICB2YWxpZGF0aW9uTWVzc2FnZXM6IHtcbiAqICAgICByZXF1aXJlZDogbGFuZyA9PiAobGFuZyA9PT0gJ2RlJyA/ICdQZmxpY2h0ZmVsZC4nIDogJ1RoaXMgZmllbGQgaXMgcmVxdWlyZWQuJyksXG4gKiAgICAgbWlubGVuZ3RoOiAobGFuZywgZXJyKSA9PiBgTWluZGVzdGVucyAke2VyclsncmVxdWlyZWRMZW5ndGgnXX0gWmVpY2hlbi5gLFxuICogICB9LFxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBVbnJlZ2lzdGVyZWQga2V5cyBmYWxsIGJhY2sgdG8gdGhlIGRlZmF1bHRzIGJlbG93LCBzbyBvdmVycmlkaW5nIG9uZSBtZXNzYWdlIGRvZXMgbm90XG4gKiBtZWFuIHN1cHBseWluZyB0aGVtIGFsbC5cbiAqL1xuZXhwb3J0IHR5cGUgVmFsaWRhdGlvbk1lc3NhZ2UgPSBzdHJpbmcgfCAoKGxhbmd1YWdlOiBzdHJpbmcsIGVycm9yOiBhbnkpID0+IHN0cmluZyk7XG5cbi8qKiBUaGUgYnVpbHQtaW4gRW5nbGlzaCBtZXNzYWdlcy4gRXZlcnkga2V5IGhlcmUgY2FuIGJlIG92ZXJyaWRkZW4gaW5kaXZpZHVhbGx5LiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfVkFMSURBVElPTl9NRVNTQUdFUzogUmVjb3JkPHN0cmluZywgVmFsaWRhdGlvbk1lc3NhZ2U+ID0ge1xuICByZXF1aXJlZDogJ1RoaXMgZmllbGQgaXMgcmVxdWlyZWQuJyxcbiAgcmVxdWlyZWRTZWxlY3Rpb246ICdQbGVhc2Ugc2VsZWN0IGFuIG9wdGlvbi4nLFxuICBlbWFpbDogJ1BsZWFzZSBlbnRlciBhIHZhbGlkIGVtYWlsIGFkZHJlc3MuJyxcbiAgcGF0dGVybjogJ0ludmFsaWQgZm9ybWF0LicsXG4gIG1pbmxlbmd0aDogKF9sYW5nLCBlcnIpID0+IGBNaW5pbXVtICR7ZXJyPy5yZXF1aXJlZExlbmd0aH0gY2hhcmFjdGVycyByZXF1aXJlZC5gLFxuICBtYXhsZW5ndGg6IChfbGFuZywgZXJyKSA9PiBgTWF4aW11bSAke2Vycj8ucmVxdWlyZWRMZW5ndGh9IGNoYXJhY3RlcnMgYWxsb3dlZC5gLFxuICBtaW46IChfbGFuZywgZXJyKSA9PiBgVmFsdWUgbXVzdCBiZSBhdCBsZWFzdCAke2Vycj8ubWlufS5gLFxuICBtYXg6IChfbGFuZywgZXJyKSA9PiBgVmFsdWUgbXVzdCBub3QgZXhjZWVkICR7ZXJyPy5tYXh9LmAsXG4gIGludmFsaWQ6ICdJbnZhbGlkIHZhbHVlLicsXG4gIGludmFsaWROdW1iZXI6ICdJbnZhbGlkIG51bWJlci4nLFxuICBpbnZhbGlkU2VsZWN0aW9uOiAnSW52YWxpZCBzZWxlY3Rpb24uJyxcbn07XG5cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgVmFsaWRhdGlvbk1lc3NhZ2VzU2VydmljZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgb3ZlcnJpZGVzID0gaW5qZWN0KFZBTElEQVRJT05fTUVTU0FHRVMsIHsgb3B0aW9uYWw6IHRydWUgfSkgPz8ge307XG5cbiAgLyoqXG4gICAqIFRoZSBtZXNzYWdlIGZvciB0aGUgZmlyc3QgZXJyb3IgcHJlc2VudCwgaW4gdGhlIG9yZGVyIHRoZSBjYWxsZXIgbGlzdHMuXG4gICAqXG4gICAqIE9yZGVyIGlzIHRoZSBjYWxsZXIncyBiZWNhdXNlIGl0IGlzIGZpZWxkLXNwZWNpZmljOiBhIGRyb3Bkb3duIHdhbnRzXG4gICAqIGByZXF1aXJlZFNlbGVjdGlvbmAgd2hlcmUgYSB0ZXh0IGlucHV0IHdhbnRzIGByZXF1aXJlZGAsIGFuZCB0aGUgZmlyc3QgbWF0Y2ggd2lucyBzbyB0aGVcbiAgICogbW9zdCBzcGVjaWZpYyBtZXNzYWdlIGlzIHRoZSBvbmUgc2hvd24uXG4gICAqL1xuICByZXNvbHZlKFxuICAgIGVycm9yczogVmFsaWRhdGlvbkVycm9ycyB8IG51bGwgfCB1bmRlZmluZWQsXG4gICAgbGFuZ3VhZ2U6IHN0cmluZyxcbiAgICBvcmRlcjogcmVhZG9ubHkgKHN0cmluZyB8IHJlYWRvbmx5IFtlcnJvcktleTogc3RyaW5nLCBtZXNzYWdlS2V5OiBzdHJpbmddKVtdLFxuICAgIGZhbGxiYWNrS2V5ID0gJ2ludmFsaWQnLFxuICApOiBzdHJpbmcge1xuICAgIGlmICghZXJyb3JzKSByZXR1cm4gJyc7XG5cbiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIG9yZGVyKSB7XG4gICAgICAvLyBBIHR1cGxlIG1hcHMgYW4gQW5ndWxhciBlcnJvciBrZXkgdG8gYSBkaWZmZXJlbnQgbWVzc2FnZSBrZXk6IGEgZHJvcGRvd24gcmFpc2VzIHRoZVxuICAgICAgLy8gc3RhbmRhcmQgYHJlcXVpcmVkYCBlcnJvciBidXQgcmVhZHMgYmV0dGVyIGFzIFwiUGxlYXNlIHNlbGVjdCBhbiBvcHRpb25cIiwgYW5kIGJvdGhcbiAgICAgIC8vIG1lc3NhZ2VzIHN0YXkgaW5kZXBlbmRlbnRseSBvdmVycmlkYWJsZS5cbiAgICAgIGNvbnN0IFtlcnJvcktleSwgbWVzc2FnZUtleV0gPSB0eXBlb2YgZW50cnkgPT09ICdzdHJpbmcnID8gW2VudHJ5LCBlbnRyeV0gOiBlbnRyeTtcbiAgICAgIC8vIGBlcnJvcnNbZXJyb3JLZXldYCBpcyB1c3VhbGx5IGFuIG9iamVjdCBvZiBkZXRhaWwsIGJ1dCBgcmVxdWlyZWRgIGlzIHNpbXBseSBgdHJ1ZWAuXG4gICAgICBpZiAoZXJyb3JzW2Vycm9yS2V5XSA9PT0gdW5kZWZpbmVkKSBjb250aW51ZTtcbiAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2VGb3IobWVzc2FnZUtleSwgbGFuZ3VhZ2UsIGVycm9yc1tlcnJvcktleV0pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlRm9yKGZhbGxiYWNrS2V5LCBsYW5ndWFnZSwgbnVsbCk7XG4gIH1cblxuICAvKiogT25lIG1lc3NhZ2UgYnkga2V5LCBob25vdXJpbmcgYW4gb3ZlcnJpZGUgYmVmb3JlIHRoZSBkZWZhdWx0LiAqL1xuICBtZXNzYWdlRm9yKGtleTogc3RyaW5nLCBsYW5ndWFnZTogc3RyaW5nLCBlcnJvcjogdW5rbm93bik6IHN0cmluZyB7XG4gICAgY29uc3QgbWVzc2FnZSA9IHRoaXMub3ZlcnJpZGVzW2tleV0gPz8gREVGQVVMVF9WQUxJREFUSU9OX01FU1NBR0VTW2tleV07XG4gICAgaWYgKG1lc3NhZ2UgPT09IHVuZGVmaW5lZCkgcmV0dXJuICcnO1xuICAgIHJldHVybiB0eXBlb2YgbWVzc2FnZSA9PT0gJ2Z1bmN0aW9uJyA/IG1lc3NhZ2UobGFuZ3VhZ2UsIGVycm9yKSA6IG1lc3NhZ2U7XG4gIH1cbn1cbiJdfQ==
@@ -1,99 +0,0 @@
1
- import { Injectable, inject } from '@angular/core';
2
- import { Validators } from '@angular/forms';
3
- import { ASYNC_VALIDATOR_REGISTRY, VALIDATOR_REGISTRY } from '../tokens/injection-tokens';
4
- import * as i0 from "@angular/core";
5
- /**
6
- * ValidatorRegistryService — resolves validator configs / key strings to Angular ValidatorFns.
7
- */
8
- export class ValidatorRegistryService {
9
- consumerRegistry = inject(VALIDATOR_REGISTRY, { optional: true }) ?? new Map();
10
- asyncRegistry = inject(ASYNC_VALIDATOR_REGISTRY, { optional: true }) ?? new Map();
11
- /**
12
- * Resolve a validator key string to a ValidatorFn.
13
- * Supports parameterized built-ins like 'min:0', 'maxLength:255'.
14
- */
15
- resolve(validatorKey) {
16
- if (this.consumerRegistry.has(validatorKey)) {
17
- return this.consumerRegistry.get(validatorKey);
18
- }
19
- if (validatorKey === 'required')
20
- return Validators.required;
21
- if (validatorKey === 'email')
22
- return Validators.email;
23
- const [name, param] = validatorKey.split(':');
24
- const value = parseFloat(param);
25
- if (name === 'min' && !isNaN(value))
26
- return Validators.min(value);
27
- if (name === 'max' && !isNaN(value))
28
- return Validators.max(value);
29
- if (name === 'minLength' && !isNaN(value))
30
- return Validators.minLength(value);
31
- if (name === 'maxLength' && !isNaN(value))
32
- return Validators.maxLength(value);
33
- return null;
34
- }
35
- /** Resolve multiple validator keys into a ValidatorFn[] */
36
- resolveAll(validatorKeys = []) {
37
- return validatorKeys.map(k => this.resolve(k)).filter((v) => v !== null);
38
- }
39
- /** Resolve a FieldValidators object or string[] into ValidatorFn[] */
40
- resolveFromConfig(config) {
41
- if (!config)
42
- return [];
43
- if (Array.isArray(config))
44
- return this.resolveAll(config);
45
- const fnList = [];
46
- if (config.required)
47
- fnList.push(Validators.required);
48
- if (config.min !== undefined)
49
- fnList.push(Validators.min(config.min));
50
- if (config.max !== undefined)
51
- fnList.push(Validators.max(config.max));
52
- if (config.minLength !== undefined)
53
- fnList.push(Validators.minLength(config.minLength));
54
- if (config.maxLength !== undefined)
55
- fnList.push(Validators.maxLength(config.maxLength));
56
- if (config.pattern)
57
- fnList.push(Validators.pattern(config.pattern));
58
- if (config.email)
59
- fnList.push(Validators.email);
60
- // Named validators from the consumer registry. This branch previously hardcoded the
61
- // built-ins and consulted the registry only for the `string[]` form of this config, so
62
- // a validator the consumer had registered could not be named from a typed schema
63
- // without casting it to `any`.
64
- for (const key of config.custom ?? []) {
65
- const fn = this.resolve(key);
66
- if (fn)
67
- fnList.push(fn);
68
- }
69
- return fnList;
70
- }
71
- /**
72
- * Resolve the async validators a field names, in `validators.customAsync`.
73
- *
74
- * Async validators are deliberately a separate registry and a separate config key: Angular
75
- * attaches them through `setAsyncValidators`, runs them only once the synchronous ones
76
- * pass, and holds the control in `pending` until they settle. Mixing them into the
77
- * synchronous list would silently never run them.
78
- *
79
- * An unknown name is skipped rather than throwing, matching the synchronous behaviour.
80
- */
81
- resolveAsyncFromConfig(config) {
82
- if (!config || Array.isArray(config))
83
- return [];
84
- const out = [];
85
- for (const key of config.customAsync ?? []) {
86
- const fn = this.asyncRegistry.get(key);
87
- if (fn)
88
- out.push(fn);
89
- }
90
- return out;
91
- }
92
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ValidatorRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
93
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ValidatorRegistryService, providedIn: 'root' });
94
- }
95
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ValidatorRegistryService, decorators: [{
96
- type: Injectable,
97
- args: [{ providedIn: 'root' }]
98
- }] });
99
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9yLXJlZ2lzdHJ5LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL3ZhbGlkYXRvci1yZWdpc3RyeS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBaUMsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFM0UsT0FBTyxFQUFFLHdCQUF3QixFQUFFLGtCQUFrQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7O0FBRTFGOztHQUVHO0FBRUgsTUFBTSxPQUFPLHdCQUF3QjtJQUNsQixnQkFBZ0IsR0FBRyxNQUFNLENBQUMsa0JBQWtCLEVBQUUsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUMsSUFBSSxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQy9FLGFBQWEsR0FBRyxNQUFNLENBQUMsd0JBQXdCLEVBQUUsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUMsSUFBSSxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBRW5HOzs7T0FHRztJQUNILE9BQU8sQ0FBQyxZQUFvQjtRQUMxQixJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztZQUM1QyxPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDakQsQ0FBQztRQUVELElBQUksWUFBWSxLQUFLLFVBQVU7WUFBRSxPQUFPLFVBQVUsQ0FBQyxRQUFRLENBQUM7UUFDNUQsSUFBSSxZQUFZLEtBQUssT0FBTztZQUFFLE9BQU8sVUFBVSxDQUFDLEtBQUssQ0FBQztRQUV0RCxNQUFNLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxHQUFHLFlBQVksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDOUMsTUFB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QUFDO1FBRUQsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVEOzs7Ozs7Ozs7T0FTRztJQUNILHNCQUFzQixDQUFDLE1BQW1DO1FBQ3hELElBQUksQ0FBQyxNQUFNLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUVoRCxNQUFNLEdBQUcsR0FBdUIsRUFBRSxDQUFDO1FBQ25DLEtBQUssTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLFdBQVcsSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUMzQyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN2QyxJQUFJLEVBQUU7Z0JBQUUsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN2QixDQUFDO1FBQ0QsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO3dHQTdFVSx3QkFBd0I7NEdBQXhCLHdCQUF3QixjQURYLE1BQU07OzRGQUNuQix3QkFBd0I7a0JBRHBDLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBc3luY1ZhbGlkYXRvckZuLCBWYWxpZGF0b3JGbiwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB0eXBlIHsgRmllbGRWYWxpZGF0b3JzIH0gZnJvbSAnQGR5bmFtaWMtZW50aXR5L2NvcmUnO1xuaW1wb3J0IHsgQVNZTkNfVkFMSURBVE9SX1JFR0lTVFJZLCBWQUxJREFUT1JfUkVHSVNUUlkgfSBmcm9tICcuLi90b2tlbnMvaW5qZWN0aW9uLXRva2Vucyc7XG5cbi8qKlxuICogVmFsaWRhdG9yUmVnaXN0cnlTZXJ2aWNlIOKAlCByZXNvbHZlcyB2YWxpZGF0b3IgY29uZmlncyAvIGtleSBzdHJpbmdzIHRvIEFuZ3VsYXIgVmFsaWRhdG9yRm5zLlxuICovXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIFZhbGlkYXRvclJlZ2lzdHJ5U2VydmljZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgY29uc3VtZXJSZWdpc3RyeSA9IGluamVjdChWQUxJREFUT1JfUkVHSVNUUlksIHsgb3B0aW9uYWw6IHRydWUgfSkgPz8gbmV3IE1hcCgpO1xuICBwcml2YXRlIHJlYWRvbmx5IGFzeW5jUmVnaXN0cnkgPSBpbmplY3QoQVNZTkNfVkFMSURBVE9SX1JFR0lTVFJZLCB7IG9wdGlvbmFsOiB0cnVlIH0pID8/IG5ldyBNYXAoKTtcblxuICAvKipcbiAgICogUmVzb2x2ZSBhIHZhbGlkYXRvciBrZXkgc3RyaW5nIHRvIGEgVmFsaWRhdG9yRm4uXG4gICAqIFN1cHBvcnRzIHBhcmFtZXRlcml6ZWQgYnVpbHQtaW5zIGxpa2UgJ21pbjowJywgJ21heExlbmd0aDoyNTUnLlxuICAgKi9cbiAgcmVzb2x2ZSh2YWxpZGF0b3JLZXk6IHN0cmluZyk6IFZhbGlkYXRvckZuIHwgbnVsbCB7XG4gICAgaWYgKHRoaXMuY29uc3VtZXJSZWdpc3RyeS5oYXModmFsaWRhdG9yS2V5KSkge1xuICAgICAgcmV0dXJuIHRoaXMuY29uc3VtZXJSZWdpc3RyeS5nZXQodmFsaWRhdG9yS2V5KTtcbiAgICB9XG5cbiAgICBpZiAodmFsaWRhdG9yS2V5ID09PSAncmVxdWlyZWQnKSByZXR1cm4gVmFsaWRhdG9ycy5yZXF1aXJlZDtcbiAgICBpZiAodmFsaWRhdG9yS2V5ID09PSAnZW1haWwnKSByZXR1cm4gVmFsaWRhdG9ycy5lbWFpbDtcblxuICAgIGNvbnN0IFtuYW1lLCBwYXJhbV0gPSB2YWxpZGF0b3JLZXkuc3BsaXQoJzonKTtcbiAgICBjb25zdCB2YWx1ZSA9IHBhcnNlRmxvYXQocGFyYW0pO1xuXG4gICAgaWYgKG5hbWUgPT09ICdtaW4nICYmICFpc05hTih2YWx1ZSkpIHJldHVybiBWYWxpZGF0b3JzLm1pbih2YWx1ZSk7XG4gICAgaWYgKG5hbWUgPT09ICdtYXgnICYmICFpc05hTih2YWx1ZSkpIHJldHVybiBWYWxpZGF0b3JzLm1heCh2YWx1ZSk7XG4gICAgaWYgKG5hbWUgPT09ICdtaW5MZW5ndGgnICYmICFpc05hTih2YWx1ZSkpIHJldHVybiBWYWxpZGF0b3JzLm1pbkxlbmd0aCh2YWx1ZSk7XG4gICAgaWYgKG5hbWUgPT09ICdtYXhMZW5ndGgnICYmICFpc05hTih2YWx1ZSkpIHJldHVybiBWYWxpZGF0b3JzLm1heExlbmd0aCh2YWx1ZSk7XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8qKiBSZXNvbHZlIG11bHRpcGxlIHZhbGlkYXRvciBrZXlzIGludG8gYSBWYWxpZGF0b3JGbltdICovXG4gIHJlc29sdmVBbGwodmFsaWRhdG9yS2V5czogc3RyaW5nW10gPSBbXSk6IFZhbGlkYXRvckZuW10ge1xuICAgIHJldHVybiB2YWxpZGF0b3JLZXlzLm1hcChrID0+IHRoaXMucmVzb2x2ZShrKSkuZmlsdGVyKCh2KTogdiBpcyBWYWxpZGF0b3JGbiA9PiB2ICE9PSBudWxsKTtcbiAgfVxuXG4gIC8qKiBSZXNvbHZlIGEgRmllbGRWYWxpZGF0b3JzIG9iamVjdCBvciBzdHJpbmdbXSBpbnRvIFZhbGlkYXRvckZuW10gKi9cbiAgcmVzb2x2ZUZyb21Db25maWcoY29uZmlnPzogRmllbGRWYWxpZGF0b3JzIHwgc3RyaW5nW10pOiBWYWxpZGF0b3JGbltdIHtcbiAgICBpZiAoIWNvbmZpZykgcmV0dXJuIFtdO1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbmZpZykpIHJldHVybiB0aGlzLnJlc29sdmVBbGwoY29uZmlnKTtcblxuICAgIGNvbnN0IGZuTGlzdDogVmFsaWRhdG9yRm5bXSA9IFtdO1xuICAgIGlmIChjb25maWcucmVxdWlyZWQpIGZuTGlzdC5wdXNoKFZhbGlkYXRvcnMucmVxdWlyZWQpO1xuICAgIGlmIChjb25maWcubWluICE9PSB1bmRlZmluZWQpIGZuTGlzdC5wdXNoKFZhbGlkYXRvcnMubWluKGNvbmZpZy5taW4pKTtcbiAgICBpZiAoY29uZmlnLm1heCAhPT0gdW5kZWZpbmVkKSBmbkxpc3QucHVzaChWYWxpZGF0b3JzLm1heChjb25maWcubWF4KSk7XG4gICAgaWYgKGNvbmZpZy5taW5MZW5ndGggIT09IHVuZGVmaW5lZCkgZm5MaXN0LnB1c2goVmFsaWRhdG9ycy5taW5MZW5ndGgoY29uZmlnLm1pbkxlbmd0aCkpO1xuICAgIGlmIChjb25maWcubWF4TGVuZ3RoICE9PSB1bmRlZmluZWQpIGZuTGlzdC5wdXNoKFZhbGlkYXRvcnMubWF4TGVuZ3RoKGNvbmZpZy5tYXhMZW5ndGgpKTtcbiAgICBpZiAoY29uZmlnLnBhdHRlcm4pIGZuTGlzdC5wdXNoKFZhbGlkYXRvcnMucGF0dGVybihjb25maWcucGF0dGVybikpO1xuICAgIGlmIChjb25maWcuZW1haWwpIGZuTGlzdC5wdXNoKFZhbGlkYXRvcnMuZW1haWwpO1xuXG4gICAgLy8gTmFtZWQgdmFsaWRhdG9ycyBmcm9tIHRoZSBjb25zdW1lciByZWdpc3RyeS4gVGhpcyBicmFuY2ggcHJldmlvdXNseSBoYXJkY29kZWQgdGhlXG4gICAgLy8gYnVpbHQtaW5zIGFuZCBjb25zdWx0ZWQgdGhlIHJlZ2lzdHJ5IG9ubHkgZm9yIHRoZSBgc3RyaW5nW11gIGZvcm0gb2YgdGhpcyBjb25maWcsIHNvXG4gICAgLy8gYSB2YWxpZGF0b3IgdGhlIGNvbnN1bWVyIGhhZCByZWdpc3RlcmVkIGNvdWxkIG5vdCBiZSBuYW1lZCBmcm9tIGEgdHlwZWQgc2NoZW1hXG4gICAgLy8gd2l0aG91dCBjYXN0aW5nIGl0IHRvIGBhbnlgLlxuICAgIGZvciAoY29uc3Qga2V5IG9mIGNvbmZpZy5jdXN0b20gPz8gW10pIHtcbiAgICAgIGNvbnN0IGZuID0gdGhpcy5yZXNvbHZlKGtleSk7XG4gICAgICBpZiAoZm4pIGZuTGlzdC5wdXNoKGZuKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZm5MaXN0O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmUgdGhlIGFzeW5jIHZhbGlkYXRvcnMgYSBmaWVsZCBuYW1lcywgaW4gYHZhbGlkYXRvcnMuY3VzdG9tQXN5bmNgLlxuICAgKlxuICAgKiBBc3luYyB2YWxpZGF0b3JzIGFyZSBkZWxpYmVyYXRlbHkgYSBzZXBhcmF0ZSByZWdpc3RyeSBhbmQgYSBzZXBhcmF0ZSBjb25maWcga2V5OiBBbmd1bGFyXG4gICAqIGF0dGFjaGVzIHRoZW0gdGhyb3VnaCBgc2V0QXN5bmNWYWxpZGF0b3JzYCwgcnVucyB0aGVtIG9ubHkgb25jZSB0aGUgc3luY2hyb25vdXMgb25lc1xuICAgKiBwYXNzLCBhbmQgaG9sZHMgdGhlIGNvbnRyb2wgaW4gYHBlbmRpbmdgIHVudGlsIHRoZXkgc2V0dGxlLiBNaXhpbmcgdGhlbSBpbnRvIHRoZVxuICAgKiBzeW5jaHJvbm91cyBsaXN0IHdvdWxkIHNpbGVudGx5IG5ldmVyIHJ1biB0aGVtLlxuICAgKlxuICAgKiBBbiB1bmtub3duIG5hbWUgaXMgc2tpcHBlZCByYXRoZXIgdGhhbiB0aHJvd2luZywgbWF0Y2hpbmcgdGhlIHN5bmNocm9ub3VzIGJlaGF2aW91ci5cbiAgICovXG4gIHJlc29sdmVBc3luY0Zyb21Db25maWcoY29uZmlnPzogRmllbGRWYWxpZGF0b3JzIHwgc3RyaW5nW10pOiBBc3luY1ZhbGlkYXRvckZuW10ge1xuICAgIGlmICghY29uZmlnIHx8IEFycmF5LmlzQXJyYXkoY29uZmlnKSkgcmV0dXJuIFtdO1xuXG4gICAgY29uc3Qgb3V0OiBBc3luY1ZhbGlkYXRvckZuW10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBjb25maWcuY3VzdG9tQXN5bmMgPz8gW10pIHtcbiAgICAgIGNvbnN0IGZuID0gdGhpcy5hc3luY1JlZ2lzdHJ5LmdldChrZXkpO1xuICAgICAgaWYgKGZuKSBvdXQucHVzaChmbik7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG4gIH1cbn1cbiJdfQ==