ngx-dynamic-entity 0.0.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +139 -0
  2. package/esm2022/lib/field-types/array-field.component.mjs +160 -0
  3. package/esm2022/lib/field-types/boolean-field.component.mjs +100 -0
  4. package/esm2022/lib/field-types/checkbox-field.component.mjs +49 -41
  5. package/esm2022/lib/field-types/currency-field.component.mjs +101 -0
  6. package/esm2022/lib/field-types/date-field.component.mjs +47 -39
  7. package/esm2022/lib/field-types/dropdown-field.component.mjs +145 -54
  8. package/esm2022/lib/field-types/email-field.component.mjs +101 -0
  9. package/esm2022/lib/field-types/entity-ref-field.component.mjs +134 -70
  10. package/esm2022/lib/field-types/file-field.component.mjs +156 -0
  11. package/esm2022/lib/field-types/group-field.component.mjs +89 -0
  12. package/esm2022/lib/field-types/image-field.component.mjs +168 -0
  13. package/esm2022/lib/field-types/month-year-field.component.mjs +151 -0
  14. package/esm2022/lib/field-types/multi-select-field.component.mjs +110 -56
  15. package/esm2022/lib/field-types/number-field.component.mjs +84 -41
  16. package/esm2022/lib/field-types/password-field.component.mjs +109 -0
  17. package/esm2022/lib/field-types/radio-field.component.mjs +152 -0
  18. package/esm2022/lib/field-types/text-field.component.mjs +82 -42
  19. package/esm2022/lib/field-types/textarea-field.component.mjs +52 -41
  20. package/esm2022/lib/form/dynamic-field/dynamic-field.component.mjs +44 -26
  21. package/esm2022/lib/form/dynamic-form.component.mjs +501 -67
  22. package/esm2022/lib/form/dynamic-record-form.component.mjs +469 -0
  23. package/esm2022/lib/providers/provide-field-types.mjs +72 -0
  24. package/esm2022/lib/providers/provide-ngx-dynamic-entity.mjs +3 -5
  25. package/esm2022/lib/services/cascade-data.service.mjs +129 -0
  26. package/esm2022/lib/services/config-source.service.mjs +67 -0
  27. package/esm2022/lib/services/entity-ref-cache.mjs +20 -0
  28. package/esm2022/lib/services/entity-ref-registry.service.mjs +3 -3
  29. package/esm2022/lib/services/entity-ref-selection.service.mjs +27 -0
  30. package/esm2022/lib/services/entity-reference.service.mjs +168 -0
  31. package/esm2022/lib/services/field-registry.service.mjs +35 -30
  32. package/esm2022/lib/services/file-upload.service.mjs +89 -0
  33. package/esm2022/lib/services/lookup-registry.service.mjs +246 -0
  34. package/esm2022/lib/services/rbac.service.mjs +5 -11
  35. package/esm2022/lib/services/rules-evaluation.service.mjs +27 -0
  36. package/esm2022/lib/services/validator-registry.service.mjs +24 -7
  37. package/esm2022/lib/tokens/injection-tokens.mjs +88 -7
  38. package/esm2022/public-api.mjs +14 -5
  39. package/fesm2022/ngx-dynamic-entity.mjs +3985 -876
  40. package/fesm2022/ngx-dynamic-entity.mjs.map +1 -1
  41. package/lib/field-types/array-field.component.d.ts +22 -0
  42. package/lib/field-types/boolean-field.component.d.ts +18 -0
  43. package/lib/field-types/checkbox-field.component.d.ts +3 -2
  44. package/lib/field-types/currency-field.component.d.ts +17 -0
  45. package/lib/field-types/date-field.component.d.ts +3 -2
  46. package/lib/field-types/dropdown-field.component.d.ts +24 -4
  47. package/lib/field-types/email-field.component.d.ts +15 -0
  48. package/lib/field-types/entity-ref-field.component.d.ts +24 -11
  49. package/lib/field-types/file-field.component.d.ts +25 -0
  50. package/lib/field-types/group-field.component.d.ts +17 -0
  51. package/lib/field-types/image-field.component.d.ts +30 -0
  52. package/lib/field-types/month-year-field.component.d.ts +28 -0
  53. package/lib/field-types/multi-select-field.component.d.ts +18 -4
  54. package/lib/field-types/number-field.component.d.ts +5 -2
  55. package/lib/field-types/password-field.component.d.ts +17 -0
  56. package/lib/field-types/radio-field.component.d.ts +33 -0
  57. package/lib/field-types/text-field.component.d.ts +5 -3
  58. package/lib/field-types/textarea-field.component.d.ts +4 -2
  59. package/lib/form/dynamic-field/dynamic-field.component.d.ts +20 -7
  60. package/lib/form/dynamic-form.component.d.ts +111 -19
  61. package/lib/form/dynamic-record-form.component.d.ts +169 -0
  62. package/lib/providers/provide-field-types.d.ts +24 -0
  63. package/lib/providers/provide-ngx-dynamic-entity.d.ts +12 -7
  64. package/lib/services/cascade-data.service.d.ts +45 -0
  65. package/lib/services/config-source.service.d.ts +14 -0
  66. package/lib/services/entity-ref-cache.d.ts +27 -0
  67. package/lib/services/entity-ref-registry.service.d.ts +4 -3
  68. package/lib/services/entity-ref-selection.service.d.ts +24 -0
  69. package/lib/services/entity-reference.service.d.ts +49 -0
  70. package/lib/services/field-registry.service.d.ts +17 -7
  71. package/lib/services/file-upload.service.d.ts +27 -0
  72. package/lib/services/lookup-registry.service.d.ts +94 -0
  73. package/lib/services/rbac.service.d.ts +4 -9
  74. package/lib/services/rules-evaluation.service.d.ts +17 -0
  75. package/lib/services/validator-registry.service.d.ts +5 -4
  76. package/lib/tokens/injection-tokens.d.ts +90 -7
  77. package/package.json +14 -3
  78. package/public-api.d.ts +11 -4
  79. package/esm2022/lib/services/config.service.mjs +0 -58
  80. package/esm2022/lib/services/version.service.mjs +0 -40
  81. package/esm2022/lib/table/dynamic-table.component.mjs +0 -160
  82. package/lib/services/config.service.d.ts +0 -25
  83. package/lib/services/version.service.d.ts +0 -26
  84. package/lib/table/dynamic-table.component.d.ts +0 -56
@@ -0,0 +1,246 @@
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 ADR-008
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/OiBzdHJpbmcgfT4oKTtcblxuLyoqXG4gKiBQb2ludCBhIGNob2ljZSBjb21wb25lbnQncyBgb3B0aW9uc2Agc2lnbmFsIGF0IHRoZSByaWdodCBzb3VyY2UgKHBhcml0eSBwbGFuIMKnNi4zKS5cbiAqXG4gKiBDYWxsZWQgZnJvbSB0aGUgYGZpZWxkYCAvIGBsYW5ndWFnZWAgaW5wdXQgc2V0dGVycyBvZiBgZHJvcGRvd25gLCBgcmFkaW9gIGFuZCBgbXVsdGlTZWxlY3RgIOKAlFxuICogdGhlIHdpcmluZyBpcyB0aGVpcnMsIHRoZSBkZWNpc2lvbiBpcyB0aGUgc2VydmljZSdzLCB3aGljaCBpcyB3aGF0IGtlZXBzIHRoZSBBRFItMDA4XG4gKiBmaXZlLWlucHV0IGNvbnRyYWN0IGludGFjdDogb3B0aW9ucyBhcmUgbmV2ZXIgcHVzaGVkIGluIGFzIGEgc2l4dGggaW5wdXQuXG4gKlxuICogU2V0dGVycyByYXRoZXIgdGhhbiBgbmdPbkNoYW5nZXNgIG9uIHB1cnBvc2UuIGBuZ09uQ2hhbmdlc2Agb25seSBmaXJlcyBmb3IgaW5wdXRzIEFuZ3VsYXJcbiAqIGl0c2VsZiBzZXRzLCBzbyBhIGNvbXBvbmVudCB3aG9zZSBgZmllbGRgIGlzIGFzc2lnbmVkIGRpcmVjdGx5IOKAlCB3aGljaCB0aGUgZmllbGQgc3BlY3MgZG8sXG4gKiBhbmQgYW55IGNvbnN1bWVyIGhvbGRpbmcgYSBgQ29tcG9uZW50UmVmYCBtYXkgZG8g4oCUIHdvdWxkIHJlbmRlciBubyBvcHRpb25zIGF0IGFsbC5cbiAqXG4gKiBQYWludHMgc3luY2hyb25vdXNseSBmaXJzdCAoaW5saW5lIG9wdGlvbnMsIG9yIGEgd2FybSBsaXN0KSwgdGhlbiBmaWxscyBpbiB3aGVuIGEgY29sZCBsaXN0XG4gKiBsYW5kcy4gVGhlIGxhdGUgcmVzdWx0IGlzIGRyb3BwZWQgaWYgdGhlIGZpZWxkIG9yIGxhbmd1YWdlIGNoYW5nZWQgd2hpbGUgaXQgd2FzIGluIGZsaWdodC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZnJlc2hDaG9pY2VPcHRpb25zKGhvc3Q6IENob2ljZU9wdGlvbkhvc3QsIGxvb2t1cHM6IExvb2t1cFJlZ2lzdHJ5U2VydmljZSk6IHZvaWQge1xuICBjb25zdCBsYXN0ID0gaG9zdExhc3RDb25maWcuZ2V0KGhvc3QpO1xuICBpZiAobGFzdCAmJiBsYXN0LmZpZWxkID09PSBob3N0LmZpZWxkICYmIGxhc3QubGFuZyA9PT0gaG9zdC5sYW5ndWFnZSkge1xuICAgIHJldHVybjtcbiAgfVxuICBob3N0TGFzdENvbmZpZy5zZXQoaG9zdCwgeyBmaWVsZDogaG9zdC5maWVsZCwgbGFuZzogaG9zdC5sYW5ndWFnZSB9KTtcblxuICBob3N0Lm9wdGlvbnMuc2V0KGxvb2t1cHMub3B0aW9uc0Zvcihob3N0LmZpZWxkLCBob3N0Lmxhbmd1YWdlKSk7XG4gIGlmICghbG9va3Vwcy5uZWVkc1Jlc29sdmUoaG9zdC5maWVsZCkpIHJldHVybjtcblxuICBjb25zdCBsaXN0TmFtZSA9IGhvc3QuZmllbGQ/Lmxpc3ROYW1lO1xuICBjb25zdCBsYW5nID0gaG9zdC5sYW5ndWFnZTtcbiAgdm9pZCBsb29rdXBzLnJlc29sdmVPcHRpb25zKGhvc3QuZmllbGQsIGhvc3QubGFuZ3VhZ2UpLnRoZW4ob3B0aW9ucyA9PiB7XG4gICAgaWYgKGhvc3QuZmllbGQ/Lmxpc3ROYW1lID09PSBsaXN0TmFtZSAmJiBob3N0Lmxhbmd1YWdlID09PSBsYW5nKSBob3N0Lm9wdGlvbnMuc2V0KG9wdGlvbnMpO1xuICB9KTtcbn1cbiJdfQ==
@@ -1,10 +1,9 @@
1
1
  import { Injectable, inject } from '@angular/core';
2
+ import { shouldMaskField as coreShouldMaskField, resolveEffectiveMask as coreResolveEffectiveMask } from '@dynamic-entity/core';
2
3
  import { MASKED_ROLES } from '../tokens/injection-tokens';
3
4
  import * as i0 from "@angular/core";
4
5
  /**
5
6
  * RbacService — ALL permission checks and masking logic live here.
6
- * CRITICAL SYNC: resolveEffectiveMask() must be identical to rbac.utils.js in dynamic-entity-server.
7
- * Changing one without the other is a critical production bug (ADR-003).
8
7
  */
9
8
  export class RbacService {
10
9
  maskedRoles = inject(MASKED_ROLES, { optional: true }) ?? [];
@@ -17,12 +16,9 @@ export class RbacService {
17
16
  return true;
18
17
  return userRoles.some(r => requiredRoles.includes(r));
19
18
  }
20
- /**
21
- * ADR-003: 3-level OR resolution.
22
- * MUST match rbac.utils.js resolveEffectiveMask() exactly.
23
- */
19
+ /** 3-level OR resolution */
24
20
  resolveEffectiveMask(formMask, tabMask, fieldMask) {
25
- return !!(formMask || tabMask || fieldMask);
21
+ return coreResolveEffectiveMask(formMask, tabMask, fieldMask);
26
22
  }
27
23
  /** Check if the user's roles include any masked role */
28
24
  isUserMaskedRole(userRoles) {
@@ -30,9 +26,7 @@ export class RbacService {
30
26
  }
31
27
  /** Determine if a specific field should be masked for this user */
32
28
  shouldMaskField(field, tab, config, userRoles) {
33
- if (!this.isUserMaskedRole(userRoles))
34
- return false;
35
- return this.resolveEffectiveMask(config.maskData, tab?.maskData, field.maskData);
29
+ return coreShouldMaskField(field, tab, config, userRoles, this.maskedRoles);
36
30
  }
37
31
  /** Get view/edit/delete permissions for a config */
38
32
  getPermissions(config, userRoles) {
@@ -49,4 +43,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
49
43
  type: Injectable,
50
44
  args: [{ providedIn: 'root' }]
51
45
  }] });
52
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmJhYy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy9yYmFjLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFbkQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDRCQUE0QixDQUFDOztBQUUxRDs7OztHQUlHO0FBRUgsTUFBTSxPQUFPLFdBQVc7SUFDTCxXQUFXLEdBQUcsTUFBTSxDQUFDLFlBQVksRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUU5RTs7O09BR0c7SUFDSCxhQUFhLENBQUMsU0FBbUIsRUFBRSxhQUF3QjtRQUN6RCxJQUFJLENBQUMsYUFBYSxFQUFFLE1BQU07WUFBRSxPQUFPLElBQUksQ0FBQztRQUN4QyxPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUVEOzs7T0FHRztJQUNILG9CQUFvQixDQUFDLFFBQWtCLEVBQUUsT0FBaUIsRUFBRSxTQUFtQjtRQUM3RSxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsSUFBSSxPQUFPLElBQUksU0FBUyxDQUFDLENBQUM7SUFDOUMsQ0FBQztJQUVELHdEQUF3RDtJQUN4RCxnQkFBZ0IsQ0FBQyxTQUFtQjtRQUNsQyxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNELENBQUM7SUFFRCxtRUFBbUU7SUFDbkUsZUFBZSxDQUFDLEtBQWtCLEVBQUUsR0FBMEIsRUFBRSxNQUFvQixFQUFFLFNBQW1CO1FBQ3ZHLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxDQUFDO1lBQUUsT0FBTyxLQUFLLENBQUM7UUFDcEQsT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNuRixDQUFDO0lBRUQsb0RBQW9EO0lBQ3BELGNBQWMsQ0FBQyxNQUFvQixFQUFFLFNBQW1CO1FBQ3RELE9BQU87WUFDTCxPQUFPLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUM7WUFDaEUsT0FBTyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDO1lBQ2hFLFNBQVMsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsV0FBVyxFQUFFLE1BQU0sQ0FBQztTQUNyRSxDQUFDO0lBQ0osQ0FBQzt3R0F0Q1UsV0FBVzs0R0FBWCxXQUFXLGNBREUsTUFBTTs7NEZBQ25CLFdBQVc7a0JBRHZCLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgdHlwZSB7IEVudGl0eUNvbmZpZywgRmllbGRDb25maWcsIFRhYkNvbmZpZyB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcbmltcG9ydCB7IE1BU0tFRF9ST0xFUyB9IGZyb20gJy4uL3Rva2Vucy9pbmplY3Rpb24tdG9rZW5zJztcblxuLyoqXG4gKiBSYmFjU2VydmljZSDigJQgQUxMIHBlcm1pc3Npb24gY2hlY2tzIGFuZCBtYXNraW5nIGxvZ2ljIGxpdmUgaGVyZS5cbiAqIENSSVRJQ0FMIFNZTkM6IHJlc29sdmVFZmZlY3RpdmVNYXNrKCkgbXVzdCBiZSBpZGVudGljYWwgdG8gcmJhYy51dGlscy5qcyBpbiBkeW5hbWljLWVudGl0eS1zZXJ2ZXIuXG4gKiBDaGFuZ2luZyBvbmUgd2l0aG91dCB0aGUgb3RoZXIgaXMgYSBjcml0aWNhbCBwcm9kdWN0aW9uIGJ1ZyAoQURSLTAwMykuXG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgUmJhY1NlcnZpY2Uge1xuICBwcml2YXRlIHJlYWRvbmx5IG1hc2tlZFJvbGVzID0gaW5qZWN0KE1BU0tFRF9ST0xFUywgeyBvcHRpb25hbDogdHJ1ZSB9KSA/PyBbXTtcblxuICAvKipcbiAgICogQ2hlY2sgaWYgYW55IG9mIHRoZSB1c2VyJ3Mgcm9sZXMgc2F0aXNmeSB0aGUgcmVxdWlyZWQgcm9sZXMuXG4gICAqIGhhc1Blcm1pc3Npb24ocm9sZXMsIHVuZGVmaW5lZCkg4oaSIHRydWUgKG5vIHJlc3RyaWN0aW9uKS5cbiAgICovXG4gIGhhc1Blcm1pc3Npb24odXNlclJvbGVzOiBzdHJpbmdbXSwgcmVxdWlyZWRSb2xlcz86IHN0cmluZ1tdKTogYm9vbGVhbiB7XG4gICAgaWYgKCFyZXF1aXJlZFJvbGVzPy5sZW5ndGgpIHJldHVybiB0cnVlO1xuICAgIHJldHVybiB1c2VyUm9sZXMuc29tZShyID0+IHJlcXVpcmVkUm9sZXMuaW5jbHVkZXMocikpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFEUi0wMDM6IDMtbGV2ZWwgT1IgcmVzb2x1dGlvbi5cbiAgICogTVVTVCBtYXRjaCByYmFjLnV0aWxzLmpzIHJlc29sdmVFZmZlY3RpdmVNYXNrKCkgZXhhY3RseS5cbiAgICovXG4gIHJlc29sdmVFZmZlY3RpdmVNYXNrKGZvcm1NYXNrPzogYm9vbGVhbiwgdGFiTWFzaz86IGJvb2xlYW4sIGZpZWxkTWFzaz86IGJvb2xlYW4pOiBib29sZWFuIHtcbiAgICByZXR1cm4gISEoZm9ybU1hc2sgfHwgdGFiTWFzayB8fCBmaWVsZE1hc2spO1xuICB9XG5cbiAgLyoqIENoZWNrIGlmIHRoZSB1c2VyJ3Mgcm9sZXMgaW5jbHVkZSBhbnkgbWFza2VkIHJvbGUgKi9cbiAgaXNVc2VyTWFza2VkUm9sZSh1c2VyUm9sZXM6IHN0cmluZ1tdKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubWFza2VkUm9sZXMuc29tZShyID0+IHVzZXJSb2xlcy5pbmNsdWRlcyhyKSk7XG4gIH1cblxuICAvKiogRGV0ZXJtaW5lIGlmIGEgc3BlY2lmaWMgZmllbGQgc2hvdWxkIGJlIG1hc2tlZCBmb3IgdGhpcyB1c2VyICovXG4gIHNob3VsZE1hc2tGaWVsZChmaWVsZDogRmllbGRDb25maWcsIHRhYjogVGFiQ29uZmlnIHwgdW5kZWZpbmVkLCBjb25maWc6IEVudGl0eUNvbmZpZywgdXNlclJvbGVzOiBzdHJpbmdbXSk6IGJvb2xlYW4ge1xuICAgIGlmICghdGhpcy5pc1VzZXJNYXNrZWRSb2xlKHVzZXJSb2xlcykpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdGhpcy5yZXNvbHZlRWZmZWN0aXZlTWFzayhjb25maWcubWFza0RhdGEsIHRhYj8ubWFza0RhdGEsIGZpZWxkLm1hc2tEYXRhKTtcbiAgfVxuXG4gIC8qKiBHZXQgdmlldy9lZGl0L2RlbGV0ZSBwZXJtaXNzaW9ucyBmb3IgYSBjb25maWcgKi9cbiAgZ2V0UGVybWlzc2lvbnMoY29uZmlnOiBFbnRpdHlDb25maWcsIHVzZXJSb2xlczogc3RyaW5nW10pIHtcbiAgICByZXR1cm4ge1xuICAgICAgY2FuVmlldzogdGhpcy5oYXNQZXJtaXNzaW9uKHVzZXJSb2xlcywgY29uZmlnLnBlcm1pc3Npb25zPy52aWV3KSxcbiAgICAgIGNhbkVkaXQ6IHRoaXMuaGFzUGVybWlzc2lvbih1c2VyUm9sZXMsIGNvbmZpZy5wZXJtaXNzaW9ucz8uZWRpdCksXG4gICAgICBjYW5EZWxldGU6IHRoaXMuaGFzUGVybWlzc2lvbih1c2VyUm9sZXMsIGNvbmZpZy5wZXJtaXNzaW9ucz8uZGVsZXRlKSxcbiAgICB9O1xuICB9XG59XG4iXX0=
46
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmJhYy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy9yYmFjLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFbkQsT0FBTyxFQUFFLGVBQWUsSUFBSSxtQkFBbUIsRUFBRSxvQkFBb0IsSUFBSSx3QkFBd0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2hJLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQzs7QUFFMUQ7O0dBRUc7QUFFSCxNQUFNLE9BQU8sV0FBVztJQUNMLFdBQVcsR0FBRyxNQUFNLENBQUMsWUFBWSxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDO0lBRTlFOzs7T0FHRztJQUNILGFBQWEsQ0FBQyxTQUFtQixFQUFFLGFBQXdCO1FBQ3pELElBQUksQ0FBQyxhQUFhLEVBQUUsTUFBTTtZQUFFLE9BQU8sSUFBSSxDQUFDO1FBQ3hDLE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4RCxDQUFDO0lBRUQsNEJBQTRCO0lBQzVCLG9CQUFvQixDQUFDLFFBQWtCLEVBQUUsT0FBaUIsRUFBRSxTQUFtQjtRQUM3RSxPQUFPLHdCQUF3QixDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUVELHdEQUF3RDtJQUN4RCxnQkFBZ0IsQ0FBQyxTQUFtQjtRQUNsQyxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNELENBQUM7SUFFRCxtRUFBbUU7SUFDbkUsZUFBZSxDQUFDLEtBQXdCLEVBQUUsR0FBZ0MsRUFBRSxNQUF3QixFQUFFLFNBQW1CO1FBQ3ZILE9BQU8sbUJBQW1CLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUM5RSxDQUFDO0lBRUQsb0RBQW9EO0lBQ3BELGNBQWMsQ0FBQyxNQUF3QixFQUFFLFNBQW1CO1FBQzFELE9BQU87WUFDTCxPQUFPLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUM7WUFDaEUsT0FBTyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDO1lBQ2hFLFNBQVMsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsV0FBVyxFQUFFLE1BQU0sQ0FBQztTQUNyRSxDQUFDO0lBQ0osQ0FBQzt3R0FsQ1UsV0FBVzs0R0FBWCxXQUFXLGNBREUsTUFBTTs7NEZBQ25CLFdBQVc7a0JBRHZCLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB0eXBlIHsgRW50aXR5Rm9ybUNvbmZpZywgTmVzdGVkRmllbGRDb25maWcsIE5lc3RlZFRhYkNvbmZpZyB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcclxuaW1wb3J0IHsgc2hvdWxkTWFza0ZpZWxkIGFzIGNvcmVTaG91bGRNYXNrRmllbGQsIHJlc29sdmVFZmZlY3RpdmVNYXNrIGFzIGNvcmVSZXNvbHZlRWZmZWN0aXZlTWFzayB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcclxuaW1wb3J0IHsgTUFTS0VEX1JPTEVTIH0gZnJvbSAnLi4vdG9rZW5zL2luamVjdGlvbi10b2tlbnMnO1xyXG5cclxuLyoqXHJcbiAqIFJiYWNTZXJ2aWNlIOKAlCBBTEwgcGVybWlzc2lvbiBjaGVja3MgYW5kIG1hc2tpbmcgbG9naWMgbGl2ZSBoZXJlLlxyXG4gKi9cclxuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcclxuZXhwb3J0IGNsYXNzIFJiYWNTZXJ2aWNlIHtcclxuICBwcml2YXRlIHJlYWRvbmx5IG1hc2tlZFJvbGVzID0gaW5qZWN0KE1BU0tFRF9ST0xFUywgeyBvcHRpb25hbDogdHJ1ZSB9KSA/PyBbXTtcclxuXHJcbiAgLyoqXHJcbiAgICogQ2hlY2sgaWYgYW55IG9mIHRoZSB1c2VyJ3Mgcm9sZXMgc2F0aXNmeSB0aGUgcmVxdWlyZWQgcm9sZXMuXHJcbiAgICogaGFzUGVybWlzc2lvbihyb2xlcywgdW5kZWZpbmVkKSDihpIgdHJ1ZSAobm8gcmVzdHJpY3Rpb24pLlxyXG4gICAqL1xyXG4gIGhhc1Blcm1pc3Npb24odXNlclJvbGVzOiBzdHJpbmdbXSwgcmVxdWlyZWRSb2xlcz86IHN0cmluZ1tdKTogYm9vbGVhbiB7XHJcbiAgICBpZiAoIXJlcXVpcmVkUm9sZXM/Lmxlbmd0aCkgcmV0dXJuIHRydWU7XHJcbiAgICByZXR1cm4gdXNlclJvbGVzLnNvbWUociA9PiByZXF1aXJlZFJvbGVzLmluY2x1ZGVzKHIpKTtcclxuICB9XHJcblxyXG4gIC8qKiAzLWxldmVsIE9SIHJlc29sdXRpb24gKi9cclxuICByZXNvbHZlRWZmZWN0aXZlTWFzayhmb3JtTWFzaz86IGJvb2xlYW4sIHRhYk1hc2s/OiBib29sZWFuLCBmaWVsZE1hc2s/OiBib29sZWFuKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gY29yZVJlc29sdmVFZmZlY3RpdmVNYXNrKGZvcm1NYXNrLCB0YWJNYXNrLCBmaWVsZE1hc2spO1xyXG4gIH1cclxuXHJcbiAgLyoqIENoZWNrIGlmIHRoZSB1c2VyJ3Mgcm9sZXMgaW5jbHVkZSBhbnkgbWFza2VkIHJvbGUgKi9cclxuICBpc1VzZXJNYXNrZWRSb2xlKHVzZXJSb2xlczogc3RyaW5nW10pOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLm1hc2tlZFJvbGVzLnNvbWUociA9PiB1c2VyUm9sZXMuaW5jbHVkZXMocikpO1xyXG4gIH1cclxuXHJcbiAgLyoqIERldGVybWluZSBpZiBhIHNwZWNpZmljIGZpZWxkIHNob3VsZCBiZSBtYXNrZWQgZm9yIHRoaXMgdXNlciAqL1xyXG4gIHNob3VsZE1hc2tGaWVsZChmaWVsZDogTmVzdGVkRmllbGRDb25maWcsIHRhYjogTmVzdGVkVGFiQ29uZmlnIHwgdW5kZWZpbmVkLCBjb25maWc6IEVudGl0eUZvcm1Db25maWcsIHVzZXJSb2xlczogc3RyaW5nW10pOiBib29sZWFuIHtcclxuICAgIHJldHVybiBjb3JlU2hvdWxkTWFza0ZpZWxkKGZpZWxkLCB0YWIsIGNvbmZpZywgdXNlclJvbGVzLCB0aGlzLm1hc2tlZFJvbGVzKTtcclxuICB9XHJcblxyXG4gIC8qKiBHZXQgdmlldy9lZGl0L2RlbGV0ZSBwZXJtaXNzaW9ucyBmb3IgYSBjb25maWcgKi9cclxuICBnZXRQZXJtaXNzaW9ucyhjb25maWc6IEVudGl0eUZvcm1Db25maWcsIHVzZXJSb2xlczogc3RyaW5nW10pIHtcclxuICAgIHJldHVybiB7XHJcbiAgICAgIGNhblZpZXc6IHRoaXMuaGFzUGVybWlzc2lvbih1c2VyUm9sZXMsIGNvbmZpZy5wZXJtaXNzaW9ucz8udmlldyksXHJcbiAgICAgIGNhbkVkaXQ6IHRoaXMuaGFzUGVybWlzc2lvbih1c2VyUm9sZXMsIGNvbmZpZy5wZXJtaXNzaW9ucz8uZWRpdCksXHJcbiAgICAgIGNhbkRlbGV0ZTogdGhpcy5oYXNQZXJtaXNzaW9uKHVzZXJSb2xlcywgY29uZmlnLnBlcm1pc3Npb25zPy5kZWxldGUpLFxyXG4gICAgfTtcclxuICB9XHJcbn1cclxuIl19
@@ -0,0 +1,27 @@
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==
@@ -3,22 +3,18 @@ import { Validators } from '@angular/forms';
3
3
  import { VALIDATOR_REGISTRY } from '../tokens/injection-tokens';
4
4
  import * as i0 from "@angular/core";
5
5
  /**
6
- * ValidatorRegistryService — resolves validator key strings to Angular ValidatorFns.
7
- * Built-in validators: 'required', 'email', 'min:N', 'max:N', 'minLength:N', 'maxLength:N'.
8
- * Consumers can register custom validators via provideNgxDynamicEntity({ validators: {...} }).
6
+ * ValidatorRegistryService — resolves validator configs / key strings to Angular ValidatorFns.
9
7
  */
10
8
  export class ValidatorRegistryService {
11
9
  consumerRegistry = inject(VALIDATOR_REGISTRY, { optional: true }) ?? new Map();
12
10
  /**
13
- * Resolve a validator key to a ValidatorFn.
11
+ * Resolve a validator key string to a ValidatorFn.
14
12
  * Supports parameterized built-ins like 'min:0', 'maxLength:255'.
15
13
  */
16
14
  resolve(validatorKey) {
17
- // Consumer validators take precedence
18
15
  if (this.consumerRegistry.has(validatorKey)) {
19
16
  return this.consumerRegistry.get(validatorKey);
20
17
  }
21
- // Built-in validators
22
18
  if (validatorKey === 'required')
23
19
  return Validators.required;
24
20
  if (validatorKey === 'email')
@@ -39,6 +35,27 @@ export class ValidatorRegistryService {
39
35
  resolveAll(validatorKeys = []) {
40
36
  return validatorKeys.map(k => this.resolve(k)).filter((v) => v !== null);
41
37
  }
38
+ /** Resolve a FieldValidators object or string[] into ValidatorFn[] */
39
+ resolveFromConfig(config) {
40
+ if (!config)
41
+ return [];
42
+ if (Array.isArray(config))
43
+ return this.resolveAll(config);
44
+ const fnList = [];
45
+ if (config.required)
46
+ fnList.push(Validators.required);
47
+ if (config.min !== undefined)
48
+ fnList.push(Validators.min(config.min));
49
+ if (config.max !== undefined)
50
+ fnList.push(Validators.max(config.max));
51
+ if (config.minLength !== undefined)
52
+ fnList.push(Validators.minLength(config.minLength));
53
+ if (config.maxLength !== undefined)
54
+ fnList.push(Validators.maxLength(config.maxLength));
55
+ if (config.pattern)
56
+ fnList.push(Validators.pattern(config.pattern));
57
+ return fnList;
58
+ }
42
59
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ValidatorRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
43
60
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ValidatorRegistryService, providedIn: 'root' });
44
61
  }
@@ -46,4 +63,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
46
63
  type: Injectable,
47
64
  args: [{ providedIn: 'root' }]
48
65
  }] });
49
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9yLXJlZ2lzdHJ5LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL3ZhbGlkYXRvci1yZWdpc3RyeS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBZ0MsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDMUUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7O0FBRWhFOzs7O0dBSUc7QUFFSCxNQUFNLE9BQU8sd0JBQXdCO0lBQ2xCLGdCQUFnQixHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxJQUFJLElBQUksR0FBRyxFQUFFLENBQUM7SUFFaEc7OztPQUdHO0lBQ0gsT0FBTyxDQUFDLFlBQW9CO1FBQzFCLHNDQUFzQztRQUN0QyxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztZQUM1QyxPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDakQsQ0FBQztRQUVELHNCQUFzQjtRQUN0QixJQUFJLFlBQVksS0FBSyxVQUFVO1lBQUUsT0FBTyxVQUFVLENBQUMsUUFBUSxDQUFDO1FBQzVELElBQUksWUFBWSxLQUFLLE9BQU87WUFBRSxPQUFPLFVBQVUsQ0FBQyxLQUFLLENBQUM7UUFFdEQsTUFBTSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsR0FBRyxZQUFZLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzlDLE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUVoQyxJQUFJLElBQUksS0FBSyxLQUFLLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDO1lBQUUsT0FBTyxVQUFVLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2xFLElBQUksSUFBSSxLQUFLLEtBQUssSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUM7WUFBRSxPQUFPLFVBQVUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbEUsSUFBSSxJQUFJLEtBQUssV0FBVyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQztZQUFFLE9BQU8sVUFBVSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM5RSxJQUFJLElBQUksS0FBSyxXQUFXLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDO1lBQUUsT0FBTyxVQUFVLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRTlFLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELDJEQUEyRDtJQUMzRCxVQUFVLENBQUMsZ0JBQTBCLEVBQUU7UUFDckMsT0FBTyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBb0IsRUFBRSxDQUFDLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQztJQUM3RixDQUFDO3dHQS9CVSx3QkFBd0I7NEdBQXhCLHdCQUF3QixjQURYLE1BQU07OzRGQUNuQix3QkFBd0I7a0JBRHBDLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBYnN0cmFjdENvbnRyb2wsIFZhbGlkYXRvckZuLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgVkFMSURBVE9SX1JFR0lTVFJZIH0gZnJvbSAnLi4vdG9rZW5zL2luamVjdGlvbi10b2tlbnMnO1xuXG4vKipcbiAqIFZhbGlkYXRvclJlZ2lzdHJ5U2VydmljZSDigJQgcmVzb2x2ZXMgdmFsaWRhdG9yIGtleSBzdHJpbmdzIHRvIEFuZ3VsYXIgVmFsaWRhdG9yRm5zLlxuICogQnVpbHQtaW4gdmFsaWRhdG9yczogJ3JlcXVpcmVkJywgJ2VtYWlsJywgJ21pbjpOJywgJ21heDpOJywgJ21pbkxlbmd0aDpOJywgJ21heExlbmd0aDpOJy5cbiAqIENvbnN1bWVycyBjYW4gcmVnaXN0ZXIgY3VzdG9tIHZhbGlkYXRvcnMgdmlhIHByb3ZpZGVOZ3hEeW5hbWljRW50aXR5KHsgdmFsaWRhdG9yczogey4uLn0gfSkuXG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgVmFsaWRhdG9yUmVnaXN0cnlTZXJ2aWNlIHtcbiAgcHJpdmF0ZSByZWFkb25seSBjb25zdW1lclJlZ2lzdHJ5ID0gaW5qZWN0KFZBTElEQVRPUl9SRUdJU1RSWSwgeyBvcHRpb25hbDogdHJ1ZSB9KSA/PyBuZXcgTWFwKCk7XG5cbiAgLyoqXG4gICAqIFJlc29sdmUgYSB2YWxpZGF0b3Iga2V5IHRvIGEgVmFsaWRhdG9yRm4uXG4gICAqIFN1cHBvcnRzIHBhcmFtZXRlcml6ZWQgYnVpbHQtaW5zIGxpa2UgJ21pbjowJywgJ21heExlbmd0aDoyNTUnLlxuICAgKi9cbiAgcmVzb2x2ZSh2YWxpZGF0b3JLZXk6IHN0cmluZyk6IFZhbGlkYXRvckZuIHwgbnVsbCB7XG4gICAgLy8gQ29uc3VtZXIgdmFsaWRhdG9ycyB0YWtlIHByZWNlZGVuY2VcbiAgICBpZiAodGhpcy5jb25zdW1lclJlZ2lzdHJ5Lmhhcyh2YWxpZGF0b3JLZXkpKSB7XG4gICAgICByZXR1cm4gdGhpcy5jb25zdW1lclJlZ2lzdHJ5LmdldCh2YWxpZGF0b3JLZXkpO1xuICAgIH1cblxuICAgIC8vIEJ1aWx0LWluIHZhbGlkYXRvcnNcbiAgICBpZiAodmFsaWRhdG9yS2V5ID09PSAncmVxdWlyZWQnKSByZXR1cm4gVmFsaWRhdG9ycy5yZXF1aXJlZDtcbiAgICBpZiAodmFsaWRhdG9yS2V5ID09PSAnZW1haWwnKSByZXR1cm4gVmFsaWRhdG9ycy5lbWFpbDtcblxuICAgIGNvbnN0IFtuYW1lLCBwYXJhbV0gPSB2YWxpZGF0b3JLZXkuc3BsaXQoJzonKTtcbiAgICBjb25zdCB2YWx1ZSA9IHBhcnNlRmxvYXQocGFyYW0pO1xuXG4gICAgaWYgKG5hbWUgPT09ICdtaW4nICYmICFpc05hTih2YWx1ZSkpIHJldHVybiBWYWxpZGF0b3JzLm1pbih2YWx1ZSk7XG4gICAgaWYgKG5hbWUgPT09ICdtYXgnICYmICFpc05hTih2YWx1ZSkpIHJldHVybiBWYWxpZGF0b3JzLm1heCh2YWx1ZSk7XG4gICAgaWYgKG5hbWUgPT09ICdtaW5MZW5ndGgnICYmICFpc05hTih2YWx1ZSkpIHJldHVybiBWYWxpZGF0b3JzLm1pbkxlbmd0aCh2YWx1ZSk7XG4gICAgaWYgKG5hbWUgPT09ICdtYXhMZW5ndGgnICYmICFpc05hTih2YWx1ZSkpIHJldHVybiBWYWxpZGF0b3JzLm1heExlbmd0aCh2YWx1ZSk7XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8qKiBSZXNvbHZlIG11bHRpcGxlIHZhbGlkYXRvciBrZXlzIGludG8gYSBWYWxpZGF0b3JGbltdICovXG4gIHJlc29sdmVBbGwodmFsaWRhdG9yS2V5czogc3RyaW5nW10gPSBbXSk6IFZhbGlkYXRvckZuW10ge1xuICAgIHJldHVybiB2YWxpZGF0b3JLZXlzLm1hcChrID0+IHRoaXMucmVzb2x2ZShrKSkuZmlsdGVyKCh2KTogdiBpcyBWYWxpZGF0b3JGbiA9PiB2ICE9PSBudWxsKTtcbiAgfVxufVxuIl19
66
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdG9yLXJlZ2lzdHJ5LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL3ZhbGlkYXRvci1yZWdpc3RyeS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBZSxVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV6RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQzs7QUFFaEU7O0dBRUc7QUFFSCxNQUFNLE9BQU8sd0JBQXdCO0lBQ2xCLGdCQUFnQixHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxJQUFJLElBQUksR0FBRyxFQUFFLENBQUM7SUFFaEc7OztPQUdHO0lBQ0gsT0FBTyxDQUFDLFlBQW9CO1FBQzFCLElBQUksSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO1lBQzVDLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNqRCxDQUFDO1FBRUQsSUFBSSxZQUFZLEtBQUssVUFBVTtZQUFFLE9BQU8sVUFBVSxDQUFDLFFBQVEsQ0FBQztRQUM1RCxJQUFJLFlBQVksS0FBSyxPQUFPO1lBQUUsT0FBTyxVQUFVLENBQUMsS0FBSyxDQUFDO1FBRXRELE1BQU0sQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLEdBQUcsWUFBWSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM5QyxNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFaEMsSUFBSSxJQUFJLEtBQUssS0FBSyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQztZQUFFLE9BQU8sVUFBVSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNsRSxJQUFJLElBQUksS0FBSyxLQUFLLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDO1lBQUUsT0FBTyxVQUFVLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2xFLElBQUksSUFBSSxLQUFLLFdBQVcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUM7WUFBRSxPQUFPLFVBQVUsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDOUUsSUFBSSxJQUFJLEtBQUssV0FBVyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQztZQUFFLE9BQU8sVUFBVSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUU5RSxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCwyREFBMkQ7SUFDM0QsVUFBVSxDQUFDLGdCQUEwQixFQUFFO1FBQ3JDLE9BQU8sYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQW9CLEVBQUUsQ0FBQyxDQUFDLEtBQUssSUFBSSxDQUFDLENBQUM7SUFDN0YsQ0FBQztJQUVELHNFQUFzRTtJQUN0RSxpQkFBaUIsQ0FBQyxNQUFtQztRQUNuRCxJQUFJLENBQUMsTUFBTTtZQUFFLE9BQU8sRUFBRSxDQUFDO1FBQ3ZCLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7WUFBRSxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFMUQsTUFBTSxNQUFNLEdBQWtCLEVBQUUsQ0FBQztRQUNqQyxJQUFJLE1BQU0sQ0FBQyxRQUFRO1lBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdEQsSUFBSSxNQUFNLENBQUMsR0FBRyxLQUFLLFNBQVM7WUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDdEUsSUFBSSxNQUFNLENBQUMsR0FBRyxLQUFLLFNBQVM7WUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDdEUsSUFBSSxNQUFNLENBQUMsU0FBUyxLQUFLLFNBQVM7WUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDeEYsSUFBSSxNQUFNLENBQUMsU0FBUyxLQUFLLFNBQVM7WUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDeEYsSUFBSSxNQUFNLENBQUMsT0FBTztZQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUVwRSxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO3dHQTdDVSx3QkFBd0I7NEdBQXhCLHdCQUF3QixjQURYLE1BQU07OzRGQUNuQix3QkFBd0I7a0JBRHBDLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFZhbGlkYXRvckZuLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgdHlwZSB7IEZpZWxkVmFsaWRhdG9ycyB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcclxuaW1wb3J0IHsgVkFMSURBVE9SX1JFR0lTVFJZIH0gZnJvbSAnLi4vdG9rZW5zL2luamVjdGlvbi10b2tlbnMnO1xyXG5cclxuLyoqXHJcbiAqIFZhbGlkYXRvclJlZ2lzdHJ5U2VydmljZSDigJQgcmVzb2x2ZXMgdmFsaWRhdG9yIGNvbmZpZ3MgLyBrZXkgc3RyaW5ncyB0byBBbmd1bGFyIFZhbGlkYXRvckZucy5cclxuICovXHJcbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXHJcbmV4cG9ydCBjbGFzcyBWYWxpZGF0b3JSZWdpc3RyeVNlcnZpY2Uge1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgY29uc3VtZXJSZWdpc3RyeSA9IGluamVjdChWQUxJREFUT1JfUkVHSVNUUlksIHsgb3B0aW9uYWw6IHRydWUgfSkgPz8gbmV3IE1hcCgpO1xyXG5cclxuICAvKipcclxuICAgKiBSZXNvbHZlIGEgdmFsaWRhdG9yIGtleSBzdHJpbmcgdG8gYSBWYWxpZGF0b3JGbi5cclxuICAgKiBTdXBwb3J0cyBwYXJhbWV0ZXJpemVkIGJ1aWx0LWlucyBsaWtlICdtaW46MCcsICdtYXhMZW5ndGg6MjU1Jy5cclxuICAgKi9cclxuICByZXNvbHZlKHZhbGlkYXRvcktleTogc3RyaW5nKTogVmFsaWRhdG9yRm4gfCBudWxsIHtcclxuICAgIGlmICh0aGlzLmNvbnN1bWVyUmVnaXN0cnkuaGFzKHZhbGlkYXRvcktleSkpIHtcclxuICAgICAgcmV0dXJuIHRoaXMuY29uc3VtZXJSZWdpc3RyeS5nZXQodmFsaWRhdG9yS2V5KTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodmFsaWRhdG9yS2V5ID09PSAncmVxdWlyZWQnKSByZXR1cm4gVmFsaWRhdG9ycy5yZXF1aXJlZDtcclxuICAgIGlmICh2YWxpZGF0b3JLZXkgPT09ICdlbWFpbCcpIHJldHVybiBWYWxpZGF0b3JzLmVtYWlsO1xyXG5cclxuICAgIGNvbnN0IFtuYW1lLCBwYXJhbV0gPSB2YWxpZGF0b3JLZXkuc3BsaXQoJzonKTtcclxuICAgIGNvbnN0IHZhbHVlID0gcGFyc2VGbG9hdChwYXJhbSk7XHJcblxyXG4gICAgaWYgKG5hbWUgPT09ICdtaW4nICYmICFpc05hTih2YWx1ZSkpIHJldHVybiBWYWxpZGF0b3JzLm1pbih2YWx1ZSk7XHJcbiAgICBpZiAobmFtZSA9PT0gJ21heCcgJiYgIWlzTmFOKHZhbHVlKSkgcmV0dXJuIFZhbGlkYXRvcnMubWF4KHZhbHVlKTtcclxuICAgIGlmIChuYW1lID09PSAnbWluTGVuZ3RoJyAmJiAhaXNOYU4odmFsdWUpKSByZXR1cm4gVmFsaWRhdG9ycy5taW5MZW5ndGgodmFsdWUpO1xyXG4gICAgaWYgKG5hbWUgPT09ICdtYXhMZW5ndGgnICYmICFpc05hTih2YWx1ZSkpIHJldHVybiBWYWxpZGF0b3JzLm1heExlbmd0aCh2YWx1ZSk7XHJcblxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICAvKiogUmVzb2x2ZSBtdWx0aXBsZSB2YWxpZGF0b3Iga2V5cyBpbnRvIGEgVmFsaWRhdG9yRm5bXSAqL1xyXG4gIHJlc29sdmVBbGwodmFsaWRhdG9yS2V5czogc3RyaW5nW10gPSBbXSk6IFZhbGlkYXRvckZuW10ge1xyXG4gICAgcmV0dXJuIHZhbGlkYXRvcktleXMubWFwKGsgPT4gdGhpcy5yZXNvbHZlKGspKS5maWx0ZXIoKHYpOiB2IGlzIFZhbGlkYXRvckZuID0+IHYgIT09IG51bGwpO1xyXG4gIH1cclxuXHJcbiAgLyoqIFJlc29sdmUgYSBGaWVsZFZhbGlkYXRvcnMgb2JqZWN0IG9yIHN0cmluZ1tdIGludG8gVmFsaWRhdG9yRm5bXSAqL1xyXG4gIHJlc29sdmVGcm9tQ29uZmlnKGNvbmZpZz86IEZpZWxkVmFsaWRhdG9ycyB8IHN0cmluZ1tdKTogVmFsaWRhdG9yRm5bXSB7XHJcbiAgICBpZiAoIWNvbmZpZykgcmV0dXJuIFtdO1xyXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29uZmlnKSkgcmV0dXJuIHRoaXMucmVzb2x2ZUFsbChjb25maWcpO1xyXG5cclxuICAgIGNvbnN0IGZuTGlzdDogVmFsaWRhdG9yRm5bXSA9IFtdO1xyXG4gICAgaWYgKGNvbmZpZy5yZXF1aXJlZCkgZm5MaXN0LnB1c2goVmFsaWRhdG9ycy5yZXF1aXJlZCk7XHJcbiAgICBpZiAoY29uZmlnLm1pbiAhPT0gdW5kZWZpbmVkKSBmbkxpc3QucHVzaChWYWxpZGF0b3JzLm1pbihjb25maWcubWluKSk7XHJcbiAgICBpZiAoY29uZmlnLm1heCAhPT0gdW5kZWZpbmVkKSBmbkxpc3QucHVzaChWYWxpZGF0b3JzLm1heChjb25maWcubWF4KSk7XHJcbiAgICBpZiAoY29uZmlnLm1pbkxlbmd0aCAhPT0gdW5kZWZpbmVkKSBmbkxpc3QucHVzaChWYWxpZGF0b3JzLm1pbkxlbmd0aChjb25maWcubWluTGVuZ3RoKSk7XHJcbiAgICBpZiAoY29uZmlnLm1heExlbmd0aCAhPT0gdW5kZWZpbmVkKSBmbkxpc3QucHVzaChWYWxpZGF0b3JzLm1heExlbmd0aChjb25maWcubWF4TGVuZ3RoKSk7XHJcbiAgICBpZiAoY29uZmlnLnBhdHRlcm4pIGZuTGlzdC5wdXNoKFZhbGlkYXRvcnMucGF0dGVybihjb25maWcucGF0dGVybikpO1xyXG5cclxuICAgIHJldHVybiBmbkxpc3Q7XHJcbiAgfVxyXG59XHJcbiJdfQ==
@@ -1,16 +1,97 @@
1
1
  import { InjectionToken } from '@angular/core';
2
- /** Base URL for the dynamic-entity-server API */
3
- export const DYNAMIC_ENTITY_API_URL = new InjectionToken('DYNAMIC_ENTITY_API_URL');
2
+ import { InMemoryEntityRefCacheStore } from '../services/entity-ref-cache';
4
3
  /** Roles that see XXXXXXXXX for masked fields (ADR-003) */
5
4
  export const MASKED_ROLES = new InjectionToken('MASKED_ROLES');
6
- /** Migration strategy for the frontend — 'strict' | 'graceful' only (ADR-005, never 'auto') */
7
- export const MIGRATION_STRATEGY = new InjectionToken('MIGRATION_STRATEGY');
8
- /** Registry: fieldType string → Angular component class */
5
+ /**
6
+ * Consumer **overrides**: fieldType string → Angular component class.
7
+ * Highest priority — beats anything registered through `provideFieldTypes()`.
8
+ */
9
9
  export const FIELD_TYPE_REGISTRY = new InjectionToken('FIELD_TYPE_REGISTRY');
10
- /** Registry: entity key → async () => options[] loader function */
10
+ /**
11
+ * Multi-provider of field-type sets, contributed by `provideFieldTypes()` /
12
+ * `provideBuiltInFieldTypes()`. Multi so several calls compose instead of clobbering;
13
+ * later sets win on key collision. This is the seam that keeps unused field components
14
+ * out of the bundle — nothing is imported until a set names it.
15
+ */
16
+ export const FIELD_TYPE_SETS = new InjectionToken('FIELD_TYPE_SETS');
17
+ /**
18
+ * Registry: entity key → option loader.
19
+ *
20
+ * A loader receives a `ReferenceLoaderContext` (`parentValue`, `filters`, `lang`) and may
21
+ * return an array, a Promise, or an Observable of `ReferenceOption[]`. `ctx` is optional,
22
+ * so a zero-arg loader (`() => svc.list()`) is still a valid registration.
23
+ */
11
24
  export const ENTITY_REF_REGISTRY = new InjectionToken('ENTITY_REF_REGISTRY');
25
+ /**
26
+ * Registry: list name → the values of a named master list (`field.listName`).
27
+ *
28
+ * A source may be the values themselves (array / Promise / Observable) or a **loader function**,
29
+ * which is what you want for anything fetched: a bare Promise is created when the provider is
30
+ * built, so every list would load whether or not a form uses it.
31
+ *
32
+ * Values are normalised by `normalizeLookupValues` — bare strings and `LocalizedText` are
33
+ * accepted alongside the full `{ code, name, sortOrder }` shape.
34
+ *
35
+ * @example
36
+ * provideNgxDynamicEntity({
37
+ * lookups: {
38
+ * employeeStatus: () => listService.getByName('employeeStatus'),
39
+ * grades: ['Junior', 'Senior'],
40
+ * },
41
+ * })
42
+ */
43
+ export const LOOKUP_REGISTRY = new InjectionToken('LOOKUP_REGISTRY');
12
44
  /** Registry: validator key → ValidatorFn */
13
45
  export const VALIDATOR_REGISTRY = new InjectionToken('VALIDATOR_REGISTRY');
14
46
  /** Registry: hook key → async (data, context) => data */
15
47
  export const HOOK_REGISTRY = new InjectionToken('HOOK_REGISTRY');
16
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5qZWN0aW9uLXRva2Vucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvdG9rZW5zL2luamVjdGlvbi10b2tlbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUkvQyxpREFBaUQ7QUFDakQsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsSUFBSSxjQUFjLENBQVMsd0JBQXdCLENBQUMsQ0FBQztBQUUzRiwyREFBMkQ7QUFDM0QsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLElBQUksY0FBYyxDQUFXLGNBQWMsQ0FBQyxDQUFDO0FBRXpFLCtGQUErRjtBQUMvRixNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLGNBQWMsQ0FBd0Isb0JBQW9CLENBQUMsQ0FBQztBQUVsRywyREFBMkQ7QUFDM0QsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxjQUFjLENBQXlCLHFCQUFxQixDQUFDLENBQUM7QUFFckcsbUVBQW1FO0FBQ25FLE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLElBQUksY0FBYyxDQUNuRCxxQkFBcUIsQ0FDdEIsQ0FBQztBQUVGLDRDQUE0QztBQUM1QyxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLGNBQWMsQ0FBbUIsb0JBQW9CLENBQUMsQ0FBQztBQUU3Rix5REFBeUQ7QUFDekQsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHLElBQUksY0FBYyxDQUF3QixlQUFlLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGlvblRva2VuIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgdHlwZSB7IEVudGl0eUNvbmZpZywgRmllbGRDb25maWcsIE1pZ3JhdGlvblN0cmF0ZWd5IH0gZnJvbSAnQGR5bmFtaWMtZW50aXR5L2NvcmUnO1xuaW1wb3J0IHR5cGUgeyBUeXBlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbi8qKiBCYXNlIFVSTCBmb3IgdGhlIGR5bmFtaWMtZW50aXR5LXNlcnZlciBBUEkgKi9cbmV4cG9ydCBjb25zdCBEWU5BTUlDX0VOVElUWV9BUElfVVJMID0gbmV3IEluamVjdGlvblRva2VuPHN0cmluZz4oJ0RZTkFNSUNfRU5USVRZX0FQSV9VUkwnKTtcblxuLyoqIFJvbGVzIHRoYXQgc2VlIFhYWFhYWFhYWCBmb3IgbWFza2VkIGZpZWxkcyAoQURSLTAwMykgKi9cbmV4cG9ydCBjb25zdCBNQVNLRURfUk9MRVMgPSBuZXcgSW5qZWN0aW9uVG9rZW48c3RyaW5nW10+KCdNQVNLRURfUk9MRVMnKTtcblxuLyoqIE1pZ3JhdGlvbiBzdHJhdGVneSBmb3IgdGhlIGZyb250ZW5kIOKAlCAnc3RyaWN0JyB8ICdncmFjZWZ1bCcgb25seSAoQURSLTAwNSwgbmV2ZXIgJ2F1dG8nKSAqL1xuZXhwb3J0IGNvbnN0IE1JR1JBVElPTl9TVFJBVEVHWSA9IG5ldyBJbmplY3Rpb25Ub2tlbjwnc3RyaWN0JyB8ICdncmFjZWZ1bCc+KCdNSUdSQVRJT05fU1RSQVRFR1knKTtcblxuLyoqIFJlZ2lzdHJ5OiBmaWVsZFR5cGUgc3RyaW5nIOKGkiBBbmd1bGFyIGNvbXBvbmVudCBjbGFzcyAqL1xuZXhwb3J0IGNvbnN0IEZJRUxEX1RZUEVfUkVHSVNUUlkgPSBuZXcgSW5qZWN0aW9uVG9rZW48TWFwPHN0cmluZywgVHlwZTxhbnk+Pj4oJ0ZJRUxEX1RZUEVfUkVHSVNUUlknKTtcblxuLyoqIFJlZ2lzdHJ5OiBlbnRpdHkga2V5IOKGkiBhc3luYyAoKSA9PiBvcHRpb25zW10gbG9hZGVyIGZ1bmN0aW9uICovXG5leHBvcnQgY29uc3QgRU5USVRZX1JFRl9SRUdJU1RSWSA9IG5ldyBJbmplY3Rpb25Ub2tlbjxNYXA8c3RyaW5nLCAoKSA9PiBQcm9taXNlPGFueVtdPj4+KFxuICAnRU5USVRZX1JFRl9SRUdJU1RSWScsXG4pO1xuXG4vKiogUmVnaXN0cnk6IHZhbGlkYXRvciBrZXkg4oaSIFZhbGlkYXRvckZuICovXG5leHBvcnQgY29uc3QgVkFMSURBVE9SX1JFR0lTVFJZID0gbmV3IEluamVjdGlvblRva2VuPE1hcDxzdHJpbmcsIGFueT4+KCdWQUxJREFUT1JfUkVHSVNUUlknKTtcblxuLyoqIFJlZ2lzdHJ5OiBob29rIGtleSDihpIgYXN5bmMgKGRhdGEsIGNvbnRleHQpID0+IGRhdGEgKi9cbmV4cG9ydCBjb25zdCBIT09LX1JFR0lTVFJZID0gbmV3IEluamVjdGlvblRva2VuPE1hcDxzdHJpbmcsIEZ1bmN0aW9uPj4oJ0hPT0tfUkVHSVNUUlknKTtcbiJdfQ==
48
+ /**
49
+ * Consumer-registered list of common module tabs (documents, audit, tasks, etc.).
50
+ * The library ships no built-in implementations. Consumers provide their own list
51
+ * so the builder's module-picker and the renderer's tab switcher know what's available.
52
+ *
53
+ * @example
54
+ * providers: [
55
+ * {
56
+ * provide: COMMON_MODULES_REGISTRY,
57
+ * useValue: [
58
+ * { id: 'documents', label: { en: 'Documents' }, component: 'app-documents-view' },
59
+ * { id: 'audit', label: { en: 'Audit Log' }, component: 'app-audit' },
60
+ * ] satisfies CommonModuleEntry[]
61
+ * }
62
+ * ]
63
+ */
64
+ export const COMMON_MODULES_REGISTRY = new InjectionToken('COMMON_MODULES_REGISTRY');
65
+ /**
66
+ * Consumer-provided file/image upload handler.
67
+ * When supplied, image-field and file-field call it to persist the File and receive a stable
68
+ * URL back. Without it the field stores `{ file, name, size, mimeType }` for the consumer to
69
+ * upload on submit. May return the result directly, as a Promise, or as an Observable.
70
+ *
71
+ * @example
72
+ * { provide: UPLOAD_HANDLER, useFactory: () => (file: File) => myUploadService.upload(file) }
73
+ */
74
+ export const UPLOAD_HANDLER = new InjectionToken('UPLOAD_HANDLER');
75
+ /**
76
+ * Backing store for the entity-reference options cache. Defaults to in-memory.
77
+ * Provide your own to make the cache outlive a page refresh.
78
+ *
79
+ * @example
80
+ * { provide: ENTITY_REF_CACHE_STORE, useClass: SessionStorageRefCache }
81
+ */
82
+ export const ENTITY_REF_CACHE_STORE = new InjectionToken('ENTITY_REF_CACHE_STORE', { providedIn: 'root', factory: () => new InMemoryEntityRefCacheStore() });
83
+ /**
84
+ * Consumer-provided predicate function to check whether user roles can edit system default tabs or fields.
85
+ * Defaults to allowing edits if not provided.
86
+ */
87
+ /**
88
+ * Consumer-provided predicate function to check whether user roles can edit system default tabs or fields.
89
+ * Defaults to allowing edits if not provided.
90
+ */
91
+ export const SYSTEM_DEFAULT_CAN_EDIT = new InjectionToken('SYSTEM_DEFAULT_CAN_EDIT');
92
+ /**
93
+ * Registry/Resolver for resolving an EntityFormConfig by entity key across entities (Phase 8).
94
+ * Enables cross-entity field referencing (`isReferenced`, `referencedEntityKey`, `referencedFieldId`, `hasDrift`).
95
+ */
96
+ export const CONFIG_SOURCE = new InjectionToken('CONFIG_SOURCE');
97
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5qZWN0aW9uLXRva2Vucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvdG9rZW5zL2luamVjdGlvbi10b2tlbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQVEvQyxPQUFPLEVBQUUsMkJBQTJCLEVBQTRCLE1BQU0sOEJBQThCLENBQUM7QUFFckcsMkRBQTJEO0FBQzNELE1BQU0sQ0FBQyxNQUFNLFlBQVksR0FBRyxJQUFJLGNBQWMsQ0FBVyxjQUFjLENBQUMsQ0FBQztBQUV6RTs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLGNBQWMsQ0FBeUIscUJBQXFCLENBQUMsQ0FBQztBQUVyRzs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxJQUFJLGNBQWMsQ0FBOEIsaUJBQWlCLENBQUMsQ0FBQztBQUVsRzs7Ozs7O0dBTUc7QUFDSCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLGNBQWMsQ0FDbkQscUJBQXFCLENBQ3RCLENBQUM7QUFFRjs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFDSCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsSUFBSSxjQUFjLENBQWdDLGlCQUFpQixDQUFDLENBQUM7QUFFcEcsNENBQTRDO0FBQzVDLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLElBQUksY0FBYyxDQUFtQixvQkFBb0IsQ0FBQyxDQUFDO0FBRTdGLHlEQUF5RDtBQUN6RCxNQUFNLENBQUMsTUFBTSxhQUFhLEdBQUcsSUFBSSxjQUFjLENBQXdCLGVBQWUsQ0FBQyxDQUFDO0FBRXhGOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUNILE1BQU0sQ0FBQyxNQUFNLHVCQUF1QixHQUFHLElBQUksY0FBYyxDQUN2RCx5QkFBeUIsQ0FDMUIsQ0FBQztBQUVGOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFHLElBQUksY0FBYyxDQUFvQixnQkFBZ0IsQ0FBQyxDQUFDO0FBRXRGOzs7Ozs7R0FNRztBQUNILE1BQU0sQ0FBQyxNQUFNLHNCQUFzQixHQUFHLElBQUksY0FBYyxDQUN0RCx3QkFBd0IsRUFDeEIsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLDJCQUEyQixFQUFFLEVBQUUsQ0FDekUsQ0FBQztBQUVGOzs7R0FHRztBQUNIOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLHVCQUF1QixHQUFHLElBQUksY0FBYyxDQUN2RCx5QkFBeUIsQ0FDMUIsQ0FBQztBQU1GOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLGFBQWEsR0FBRyxJQUFJLGNBQWMsQ0FBc0IsZUFBZSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3Rpb25Ub2tlbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgdHlwZSB7IFR5cGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHR5cGUge1xyXG4gIENvbW1vbk1vZHVsZUVudHJ5LFxyXG4gIEVudGl0eVJlZmVyZW5jZUxvYWRlcixcclxuICBGaWxlVXBsb2FkSGFuZGxlcixcclxuICBMb29rdXBMaXN0U291cmNlLFxyXG59IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcclxuaW1wb3J0IHsgSW5NZW1vcnlFbnRpdHlSZWZDYWNoZVN0b3JlLCB0eXBlIEVudGl0eVJlZkNhY2hlU3RvcmUgfSBmcm9tICcuLi9zZXJ2aWNlcy9lbnRpdHktcmVmLWNhY2hlJztcclxuXHJcbi8qKiBSb2xlcyB0aGF0IHNlZSBYWFhYWFhYWFggZm9yIG1hc2tlZCBmaWVsZHMgKEFEUi0wMDMpICovXHJcbmV4cG9ydCBjb25zdCBNQVNLRURfUk9MRVMgPSBuZXcgSW5qZWN0aW9uVG9rZW48c3RyaW5nW10+KCdNQVNLRURfUk9MRVMnKTtcclxuXHJcbi8qKlxyXG4gKiBDb25zdW1lciAqKm92ZXJyaWRlcyoqOiBmaWVsZFR5cGUgc3RyaW5nIOKGkiBBbmd1bGFyIGNvbXBvbmVudCBjbGFzcy5cclxuICogSGlnaGVzdCBwcmlvcml0eSDigJQgYmVhdHMgYW55dGhpbmcgcmVnaXN0ZXJlZCB0aHJvdWdoIGBwcm92aWRlRmllbGRUeXBlcygpYC5cclxuICovXHJcbmV4cG9ydCBjb25zdCBGSUVMRF9UWVBFX1JFR0lTVFJZID0gbmV3IEluamVjdGlvblRva2VuPE1hcDxzdHJpbmcsIFR5cGU8YW55Pj4+KCdGSUVMRF9UWVBFX1JFR0lTVFJZJyk7XHJcblxyXG4vKipcclxuICogTXVsdGktcHJvdmlkZXIgb2YgZmllbGQtdHlwZSBzZXRzLCBjb250cmlidXRlZCBieSBgcHJvdmlkZUZpZWxkVHlwZXMoKWAgL1xyXG4gKiBgcHJvdmlkZUJ1aWx0SW5GaWVsZFR5cGVzKClgLiBNdWx0aSBzbyBzZXZlcmFsIGNhbGxzIGNvbXBvc2UgaW5zdGVhZCBvZiBjbG9iYmVyaW5nO1xyXG4gKiBsYXRlciBzZXRzIHdpbiBvbiBrZXkgY29sbGlzaW9uLiBUaGlzIGlzIHRoZSBzZWFtIHRoYXQga2VlcHMgdW51c2VkIGZpZWxkIGNvbXBvbmVudHNcclxuICogb3V0IG9mIHRoZSBidW5kbGUg4oCUIG5vdGhpbmcgaXMgaW1wb3J0ZWQgdW50aWwgYSBzZXQgbmFtZXMgaXQuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgRklFTERfVFlQRV9TRVRTID0gbmV3IEluamVjdGlvblRva2VuPFJlY29yZDxzdHJpbmcsIFR5cGU8YW55Pj5bXT4oJ0ZJRUxEX1RZUEVfU0VUUycpO1xyXG5cclxuLyoqXHJcbiAqIFJlZ2lzdHJ5OiBlbnRpdHkga2V5IOKGkiBvcHRpb24gbG9hZGVyLlxyXG4gKlxyXG4gKiBBIGxvYWRlciByZWNlaXZlcyBhIGBSZWZlcmVuY2VMb2FkZXJDb250ZXh0YCAoYHBhcmVudFZhbHVlYCwgYGZpbHRlcnNgLCBgbGFuZ2ApIGFuZCBtYXlcclxuICogcmV0dXJuIGFuIGFycmF5LCBhIFByb21pc2UsIG9yIGFuIE9ic2VydmFibGUgb2YgYFJlZmVyZW5jZU9wdGlvbltdYC4gYGN0eGAgaXMgb3B0aW9uYWwsXHJcbiAqIHNvIGEgemVyby1hcmcgbG9hZGVyIChgKCkgPT4gc3ZjLmxpc3QoKWApIGlzIHN0aWxsIGEgdmFsaWQgcmVnaXN0cmF0aW9uLlxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IEVOVElUWV9SRUZfUkVHSVNUUlkgPSBuZXcgSW5qZWN0aW9uVG9rZW48TWFwPHN0cmluZywgRW50aXR5UmVmZXJlbmNlTG9hZGVyPj4oXHJcbiAgJ0VOVElUWV9SRUZfUkVHSVNUUlknLFxyXG4pO1xyXG5cclxuLyoqXHJcbiAqIFJlZ2lzdHJ5OiBsaXN0IG5hbWUg4oaSIHRoZSB2YWx1ZXMgb2YgYSBuYW1lZCBtYXN0ZXIgbGlzdCAoYGZpZWxkLmxpc3ROYW1lYCkuXHJcbiAqXHJcbiAqIEEgc291cmNlIG1heSBiZSB0aGUgdmFsdWVzIHRoZW1zZWx2ZXMgKGFycmF5IC8gUHJvbWlzZSAvIE9ic2VydmFibGUpIG9yIGEgKipsb2FkZXIgZnVuY3Rpb24qKixcclxuICogd2hpY2ggaXMgd2hhdCB5b3Ugd2FudCBmb3IgYW55dGhpbmcgZmV0Y2hlZDogYSBiYXJlIFByb21pc2UgaXMgY3JlYXRlZCB3aGVuIHRoZSBwcm92aWRlciBpc1xyXG4gKiBidWlsdCwgc28gZXZlcnkgbGlzdCB3b3VsZCBsb2FkIHdoZXRoZXIgb3Igbm90IGEgZm9ybSB1c2VzIGl0LlxyXG4gKlxyXG4gKiBWYWx1ZXMgYXJlIG5vcm1hbGlzZWQgYnkgYG5vcm1hbGl6ZUxvb2t1cFZhbHVlc2Ag4oCUIGJhcmUgc3RyaW5ncyBhbmQgYExvY2FsaXplZFRleHRgIGFyZVxyXG4gKiBhY2NlcHRlZCBhbG9uZ3NpZGUgdGhlIGZ1bGwgYHsgY29kZSwgbmFtZSwgc29ydE9yZGVyIH1gIHNoYXBlLlxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKiBwcm92aWRlTmd4RHluYW1pY0VudGl0eSh7XHJcbiAqICAgbG9va3Vwczoge1xyXG4gKiAgICAgZW1wbG95ZWVTdGF0dXM6ICgpID0+IGxpc3RTZXJ2aWNlLmdldEJ5TmFtZSgnZW1wbG95ZWVTdGF0dXMnKSxcclxuICogICAgIGdyYWRlczogWydKdW5pb3InLCAnU2VuaW9yJ10sXHJcbiAqICAgfSxcclxuICogfSlcclxuICovXHJcbmV4cG9ydCBjb25zdCBMT09LVVBfUkVHSVNUUlkgPSBuZXcgSW5qZWN0aW9uVG9rZW48TWFwPHN0cmluZywgTG9va3VwTGlzdFNvdXJjZT4+KCdMT09LVVBfUkVHSVNUUlknKTtcclxuXHJcbi8qKiBSZWdpc3RyeTogdmFsaWRhdG9yIGtleSDihpIgVmFsaWRhdG9yRm4gKi9cclxuZXhwb3J0IGNvbnN0IFZBTElEQVRPUl9SRUdJU1RSWSA9IG5ldyBJbmplY3Rpb25Ub2tlbjxNYXA8c3RyaW5nLCBhbnk+PignVkFMSURBVE9SX1JFR0lTVFJZJyk7XHJcblxyXG4vKiogUmVnaXN0cnk6IGhvb2sga2V5IOKGkiBhc3luYyAoZGF0YSwgY29udGV4dCkgPT4gZGF0YSAqL1xyXG5leHBvcnQgY29uc3QgSE9PS19SRUdJU1RSWSA9IG5ldyBJbmplY3Rpb25Ub2tlbjxNYXA8c3RyaW5nLCBGdW5jdGlvbj4+KCdIT09LX1JFR0lTVFJZJyk7XHJcblxyXG4vKipcclxuICogQ29uc3VtZXItcmVnaXN0ZXJlZCBsaXN0IG9mIGNvbW1vbiBtb2R1bGUgdGFicyAoZG9jdW1lbnRzLCBhdWRpdCwgdGFza3MsIGV0Yy4pLlxyXG4gKiBUaGUgbGlicmFyeSBzaGlwcyBubyBidWlsdC1pbiBpbXBsZW1lbnRhdGlvbnMuIENvbnN1bWVycyBwcm92aWRlIHRoZWlyIG93biBsaXN0XHJcbiAqIHNvIHRoZSBidWlsZGVyJ3MgbW9kdWxlLXBpY2tlciBhbmQgdGhlIHJlbmRlcmVyJ3MgdGFiIHN3aXRjaGVyIGtub3cgd2hhdCdzIGF2YWlsYWJsZS5cclxuICpcclxuICogQGV4YW1wbGVcclxuICogcHJvdmlkZXJzOiBbXHJcbiAqICAge1xyXG4gKiAgICAgcHJvdmlkZTogQ09NTU9OX01PRFVMRVNfUkVHSVNUUlksXHJcbiAqICAgICB1c2VWYWx1ZTogW1xyXG4gKiAgICAgICB7IGlkOiAnZG9jdW1lbnRzJywgbGFiZWw6IHsgZW46ICdEb2N1bWVudHMnIH0sIGNvbXBvbmVudDogJ2FwcC1kb2N1bWVudHMtdmlldycgfSxcclxuICogICAgICAgeyBpZDogJ2F1ZGl0JywgICAgIGxhYmVsOiB7IGVuOiAnQXVkaXQgTG9nJyAgfSwgY29tcG9uZW50OiAnYXBwLWF1ZGl0JyB9LFxyXG4gKiAgICAgXSBzYXRpc2ZpZXMgQ29tbW9uTW9kdWxlRW50cnlbXVxyXG4gKiAgIH1cclxuICogXVxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IENPTU1PTl9NT0RVTEVTX1JFR0lTVFJZID0gbmV3IEluamVjdGlvblRva2VuPENvbW1vbk1vZHVsZUVudHJ5W10+KFxyXG4gICdDT01NT05fTU9EVUxFU19SRUdJU1RSWScsXHJcbik7XHJcblxyXG4vKipcclxuICogQ29uc3VtZXItcHJvdmlkZWQgZmlsZS9pbWFnZSB1cGxvYWQgaGFuZGxlci5cclxuICogV2hlbiBzdXBwbGllZCwgaW1hZ2UtZmllbGQgYW5kIGZpbGUtZmllbGQgY2FsbCBpdCB0byBwZXJzaXN0IHRoZSBGaWxlIGFuZCByZWNlaXZlIGEgc3RhYmxlXHJcbiAqIFVSTCBiYWNrLiBXaXRob3V0IGl0IHRoZSBmaWVsZCBzdG9yZXMgYHsgZmlsZSwgbmFtZSwgc2l6ZSwgbWltZVR5cGUgfWAgZm9yIHRoZSBjb25zdW1lciB0b1xyXG4gKiB1cGxvYWQgb24gc3VibWl0LiBNYXkgcmV0dXJuIHRoZSByZXN1bHQgZGlyZWN0bHksIGFzIGEgUHJvbWlzZSwgb3IgYXMgYW4gT2JzZXJ2YWJsZS5cclxuICpcclxuICogQGV4YW1wbGVcclxuICogeyBwcm92aWRlOiBVUExPQURfSEFORExFUiwgdXNlRmFjdG9yeTogKCkgPT4gKGZpbGU6IEZpbGUpID0+IG15VXBsb2FkU2VydmljZS51cGxvYWQoZmlsZSkgfVxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IFVQTE9BRF9IQU5ETEVSID0gbmV3IEluamVjdGlvblRva2VuPEZpbGVVcGxvYWRIYW5kbGVyPignVVBMT0FEX0hBTkRMRVInKTtcclxuXHJcbi8qKlxyXG4gKiBCYWNraW5nIHN0b3JlIGZvciB0aGUgZW50aXR5LXJlZmVyZW5jZSBvcHRpb25zIGNhY2hlLiBEZWZhdWx0cyB0byBpbi1tZW1vcnkuXHJcbiAqIFByb3ZpZGUgeW91ciBvd24gdG8gbWFrZSB0aGUgY2FjaGUgb3V0bGl2ZSBhIHBhZ2UgcmVmcmVzaC5cclxuICpcclxuICogQGV4YW1wbGVcclxuICogeyBwcm92aWRlOiBFTlRJVFlfUkVGX0NBQ0hFX1NUT1JFLCB1c2VDbGFzczogU2Vzc2lvblN0b3JhZ2VSZWZDYWNoZSB9XHJcbiAqL1xyXG5leHBvcnQgY29uc3QgRU5USVRZX1JFRl9DQUNIRV9TVE9SRSA9IG5ldyBJbmplY3Rpb25Ub2tlbjxFbnRpdHlSZWZDYWNoZVN0b3JlPihcclxuICAnRU5USVRZX1JFRl9DQUNIRV9TVE9SRScsXHJcbiAgeyBwcm92aWRlZEluOiAncm9vdCcsIGZhY3Rvcnk6ICgpID0+IG5ldyBJbk1lbW9yeUVudGl0eVJlZkNhY2hlU3RvcmUoKSB9LFxyXG4pO1xyXG5cclxuLyoqXHJcbiAqIENvbnN1bWVyLXByb3ZpZGVkIHByZWRpY2F0ZSBmdW5jdGlvbiB0byBjaGVjayB3aGV0aGVyIHVzZXIgcm9sZXMgY2FuIGVkaXQgc3lzdGVtIGRlZmF1bHQgdGFicyBvciBmaWVsZHMuXHJcbiAqIERlZmF1bHRzIHRvIGFsbG93aW5nIGVkaXRzIGlmIG5vdCBwcm92aWRlZC5cclxuICovXHJcbi8qKlxyXG4gKiBDb25zdW1lci1wcm92aWRlZCBwcmVkaWNhdGUgZnVuY3Rpb24gdG8gY2hlY2sgd2hldGhlciB1c2VyIHJvbGVzIGNhbiBlZGl0IHN5c3RlbSBkZWZhdWx0IHRhYnMgb3IgZmllbGRzLlxyXG4gKiBEZWZhdWx0cyB0byBhbGxvd2luZyBlZGl0cyBpZiBub3QgcHJvdmlkZWQuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgU1lTVEVNX0RFRkFVTFRfQ0FOX0VESVQgPSBuZXcgSW5qZWN0aW9uVG9rZW48KHJvbGVzOiBzdHJpbmdbXSkgPT4gYm9vbGVhbj4oXHJcbiAgJ1NZU1RFTV9ERUZBVUxUX0NBTl9FRElUJyxcclxuKTtcclxuXHJcbmV4cG9ydCB0eXBlIENvbmZpZ1NvdXJjZUhhbmRsZXIgPSAoXHJcbiAgZW50aXR5S2V5OiBzdHJpbmcsXHJcbikgPT4gYW55O1xyXG5cclxuLyoqXHJcbiAqIFJlZ2lzdHJ5L1Jlc29sdmVyIGZvciByZXNvbHZpbmcgYW4gRW50aXR5Rm9ybUNvbmZpZyBieSBlbnRpdHkga2V5IGFjcm9zcyBlbnRpdGllcyAoUGhhc2UgOCkuXHJcbiAqIEVuYWJsZXMgY3Jvc3MtZW50aXR5IGZpZWxkIHJlZmVyZW5jaW5nIChgaXNSZWZlcmVuY2VkYCwgYHJlZmVyZW5jZWRFbnRpdHlLZXlgLCBgcmVmZXJlbmNlZEZpZWxkSWRgLCBgaGFzRHJpZnRgKS5cclxuICovXHJcbmV4cG9ydCBjb25zdCBDT05GSUdfU09VUkNFID0gbmV3IEluamVjdGlvblRva2VuPENvbmZpZ1NvdXJjZUhhbmRsZXI+KCdDT05GSUdfU09VUkNFJyk7XHJcblxyXG5cclxuIl19