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,168 @@
1
+ import { Injectable, inject } from '@angular/core';
2
+ import { buildReferenceCacheKey, entityKeyFromCacheKey, normalizeReferenceOptions, resolveLabel, valuesMatch, } from '@dynamic-entity/core';
3
+ import { ENTITY_REF_CACHE_STORE } from '../tokens/injection-tokens';
4
+ import { EntityRefRegistryService } from './entity-ref-registry.service';
5
+ import * as i0 from "@angular/core";
6
+ /** Label-cache field separator. Kept out of template literals so it stays visible in source. */
7
+ const LABEL_SEP = '|';
8
+ /**
9
+ * EntityReferenceService — the cache in front of consumer-registered option loaders.
10
+ *
11
+ * Three layers, matching the reference implementation:
12
+ * 1. **options** — resolved `ReferenceOption[]` per (entity, lang, displayFields, filters).
13
+ * 2. **in-flight** — the pending Promise, so N fields referencing one entity trigger one
14
+ * load rather than N. This is the layer that actually removes duplicate HTTP calls;
15
+ * an options cache alone does nothing for concurrent first loads.
16
+ * 3. **labels** — synchronous value → text, for rendering a stored reference without
17
+ * waiting on a load.
18
+ *
19
+ * Invalidation is per entity, not global. The reference could only `clearCache()` everything
20
+ * (issue #16), so saving one record re-fetched every entity's options.
21
+ */
22
+ export class EntityReferenceService {
23
+ registry = inject(EntityRefRegistryService);
24
+ store = inject(ENTITY_REF_CACHE_STORE);
25
+ /** Loads in progress, keyed the same way as the options cache. */
26
+ inFlight = new Map();
27
+ /** `entityKey|lang|canonicalValue` -> display text. */
28
+ labels = new Map();
29
+ /**
30
+ * Options for an entity, from cache when present.
31
+ * Concurrent callers with the same key share one load.
32
+ */
33
+ async load(entityKey, ctx = {}) {
34
+ const key = buildReferenceCacheKey(entityKey, {
35
+ lang: ctx.lang,
36
+ filters: ctx.filters,
37
+ displayFields: ctx.displayFields,
38
+ parentValue: ctx.parentValue,
39
+ });
40
+ const cached = this.store.get(key);
41
+ if (cached)
42
+ return cached;
43
+ const pending = this.inFlight.get(key);
44
+ if (pending)
45
+ return pending;
46
+ const loader = this.registry.resolve(entityKey);
47
+ if (!loader)
48
+ return [];
49
+ const load = this.invoke(loader, ctx)
50
+ .then(raw => {
51
+ // displayFields drive label building, which is why they are part of the cache key.
52
+ const options = normalizeReferenceOptions(raw, ctx.displayFields ? { enabled: true, displayFields: ctx.displayFields } : undefined, ctx.lang ?? 'en');
53
+ this.store.set(key, options);
54
+ this.rememberLabels(entityKey, ctx.lang ?? 'en', options);
55
+ return options;
56
+ });
57
+ // A failed load resolves to [] for the caller but is never written to the store, so a
58
+ // transient error is retried on the next call instead of poisoning the cache. Only the
59
+ // `.then` above caches, and a rejection skips it.
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 cached. */
67
+ peek(entityKey, ctx = {}) {
68
+ return this.store.get(buildReferenceCacheKey(entityKey, {
69
+ lang: ctx.lang,
70
+ filters: ctx.filters,
71
+ displayFields: ctx.displayFields,
72
+ parentValue: ctx.parentValue,
73
+ }));
74
+ }
75
+ /**
76
+ * Display text for a stored reference value, synchronously.
77
+ * Returns `undefined` when the entity's options have never been loaded.
78
+ */
79
+ labelFor(entityKey, value, lang = 'en') {
80
+ return this.labels.get(this.labelKey(entityKey, lang, value));
81
+ }
82
+ /** Drop everything cached for one entity, leaving other entities intact. */
83
+ invalidate(entityKey) {
84
+ for (const key of this.store.keys()) {
85
+ if (entityKeyFromCacheKey(key) === entityKey)
86
+ this.store.delete(key);
87
+ }
88
+ for (const key of [...this.inFlight.keys()]) {
89
+ if (entityKeyFromCacheKey(key) === entityKey)
90
+ this.inFlight.delete(key);
91
+ }
92
+ const prefix = `${entityKey}${LABEL_SEP}`;
93
+ for (const key of [...this.labels.keys()]) {
94
+ if (key.startsWith(prefix))
95
+ this.labels.delete(key);
96
+ }
97
+ }
98
+ clear() {
99
+ this.store.clear();
100
+ this.inFlight.clear();
101
+ this.labels.clear();
102
+ }
103
+ rememberLabels(entityKey, lang, options) {
104
+ for (const option of options) {
105
+ this.labels.set(this.labelKey(entityKey, lang, option.value), option.label);
106
+ }
107
+ }
108
+ /** Label-cache key. An object value collapses to its resolved text for the active language. */
109
+ labelKey(entityKey, lang, value) {
110
+ const canonical = value !== null && typeof value === 'object'
111
+ ? resolveLabel(value, lang)
112
+ : String(value ?? '');
113
+ return [entityKey, lang, canonical].join(LABEL_SEP);
114
+ }
115
+ // ─── Loader result coercion (array | Promise | Observable) ──────────────────
116
+ invoke(loader, ctx) {
117
+ let result;
118
+ try {
119
+ result = loader(ctx);
120
+ }
121
+ catch (err) {
122
+ // Reject rather than resolve empty: `load` must be able to tell failure from
123
+ // "no matches", or it would cache the failure.
124
+ return Promise.reject(err);
125
+ }
126
+ return this.toPromise(result);
127
+ }
128
+ toPromise(result) {
129
+ if (Array.isArray(result))
130
+ return Promise.resolve(result);
131
+ if (this.isSubscribable(result)) {
132
+ // First emission wins, so an Observable that stays open still resolves the load.
133
+ return new Promise((resolve, reject) => {
134
+ let settled = false;
135
+ const settle = (fn) => {
136
+ if (settled)
137
+ return;
138
+ settled = true;
139
+ fn();
140
+ };
141
+ result.subscribe({
142
+ next: value => settle(() => resolve(value ?? [])),
143
+ // An erroring stream is a failed load, not an empty one — see `invoke`.
144
+ error: err => settle(() => reject(err)),
145
+ // Completing without emitting is a legitimate empty result, and is cached.
146
+ complete: () => settle(() => resolve([])),
147
+ });
148
+ });
149
+ }
150
+ return Promise.resolve(result);
151
+ }
152
+ isSubscribable(value) {
153
+ return (typeof value === 'object' &&
154
+ value !== null &&
155
+ typeof value.subscribe === 'function');
156
+ }
157
+ /** Exposed for cascade filtering, which matches a parent value against option values. */
158
+ matches(a, b, lang = 'en') {
159
+ return valuesMatch(a, b, lang);
160
+ }
161
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EntityReferenceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
162
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EntityReferenceService, providedIn: 'root' });
163
+ }
164
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EntityReferenceService, decorators: [{
165
+ type: Injectable,
166
+ args: [{ providedIn: 'root' }]
167
+ }] });
168
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LXJlZmVyZW5jZS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy9lbnRpdHktcmVmZXJlbmNlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFTbkQsT0FBTyxFQUNMLHNCQUFzQixFQUN0QixxQkFBcUIsRUFDckIseUJBQXlCLEVBQ3pCLFlBQVksRUFDWixXQUFXLEdBQ1osTUFBTSxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNwRSxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQzs7QUFFekUsZ0dBQWdHO0FBQ2hHLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQztBQUV0Qjs7Ozs7Ozs7Ozs7OztHQWFHO0FBRUgsTUFBTSxPQUFPLHNCQUFzQjtJQUNoQixRQUFRLEdBQUcsTUFBTSxDQUFDLHdCQUF3QixDQUFDLENBQUM7SUFDNUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO0lBRXhELGtFQUFrRTtJQUNqRCxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQXNDLENBQUM7SUFDMUUsdURBQXVEO0lBQ3RDLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBa0IsQ0FBQztJQUVwRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQWlCLEVBQUUsTUFBOEIsRUFBRTtRQUM1RCxNQUFNLEdBQUcsR0FBRyxzQkFBc0IsQ0FBQyxTQUFTLEVBQUU7WUFDNUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJO1lBQ2QsT0FBTyxFQUFFLEdBQUcsQ0FBQyxPQUFPO1lBQ3BCLGFBQWEsRUFBRSxHQUFHLENBQUMsYUFBYTtZQUNoQyxXQUFXLEVBQUUsR0FBRyxDQUFDLFdBQVc7U0FDN0IsQ0FBQyxDQUFDO1FBRUgsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbkMsSUFBSSxNQUFNO1lBQUUsT0FBTyxNQUFNLENBQUM7UUFFMUIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdkMsSUFBSSxPQUFPO1lBQUUsT0FBTyxPQUFPLENBQUM7UUFFNUIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUV2QixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUM7YUFDbEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFO1lBQ1YsbUZBQW1GO1lBQ25GLE1BQU0sT0FBTyxHQUFHLHlCQUF5QixDQUN2QyxHQUF5QixFQUN6QixHQUFHLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLEdBQUcsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUyxFQUNuRixHQUFHLENBQUMsSUFBSSxJQUFJLElBQUksQ0FDakIsQ0FBQztZQUNGLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUM3QixJQUFJLENBQUMsY0FBYyxDQUFDLFNBQVMsRUFBRSxHQUFHLENBQUMsSUFBSSxJQUFJLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztZQUMxRCxPQUFPLE9BQU8sQ0FBQztRQUNqQixDQUFDLENBQUMsQ0FBQztRQUVMLHNGQUFzRjtRQUN0Rix1RkFBdUY7UUFDdkYsa0RBQWtEO1FBQ2xELE1BQU0sT0FBTyxHQUFHLElBQUk7YUFDakIsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQXVCLENBQUM7YUFDcEMsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFFNUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ2hDLE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFFRCw2RUFBNkU7SUFDN0UsSUFBSSxDQUFDLFNBQWlCLEVBQUUsTUFBOEIsRUFBRTtRQUN0RCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUNuQixzQkFBc0IsQ0FBQyxTQUFTLEVBQUU7WUFDaEMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJO1lBQ2QsT0FBTyxFQUFFLEdBQUcsQ0FBQyxPQUFPO1lBQ3BCLGFBQWEsRUFBRSxHQUFHLENBQUMsYUFBYTtZQUNoQyxXQUFXLEVBQUUsR0FBRyxDQUFDLFdBQVc7U0FDN0IsQ0FBQyxDQUNILENBQUM7SUFDSixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsUUFBUSxDQUFDLFNBQWlCLEVBQUUsS0FBYyxFQUFFLElBQUksR0FBRyxJQUFJO1FBQ3JELE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUVELDRFQUE0RTtJQUM1RSxVQUFVLENBQUMsU0FBaUI7UUFDMUIsS0FBSyxNQUFNLEdBQUcsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7WUFDcEMsSUFBSSxxQkFBcUIsQ0FBQyxHQUFHLENBQUMsS0FBSyxTQUFTO2dCQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZFLENBQUM7UUFDRCxLQUFLLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUM1QyxJQUFJLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxLQUFLLFNBQVM7Z0JBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDMUUsQ0FBQztRQUNELE1BQU0sTUFBTSxHQUFHLEdBQUcsU0FBUyxHQUFHLFNBQVMsRUFBRSxDQUFDO1FBQzFDLEtBQUssTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQzFDLElBQUksR0FBRyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7Z0JBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdEQsQ0FBQztJQUNILENBQUM7SUFFRCxLQUFLO1FBQ0gsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNuQixJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDdEIsQ0FBQztJQUVPLGNBQWMsQ0FBQyxTQUFpQixFQUFFLElBQVksRUFBRSxPQUEwQjtRQUNoRixLQUFLLE1BQU0sTUFBTSxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQzdCLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzlFLENBQUM7SUFDSCxDQUFDO0lBRUQsK0ZBQStGO0lBQ3ZGLFFBQVEsQ0FBQyxTQUFpQixFQUFFLElBQVksRUFBRSxLQUFjO1FBQzlELE1BQU0sU0FBUyxHQUNiLEtBQUssS0FBSyxJQUFJLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUTtZQUN6QyxDQUFDLENBQUMsWUFBWSxDQUFDLEtBQStCLEVBQUUsSUFBSSxDQUFDO1lBQ3JELENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQzFCLE9BQU8sQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLFNBQVMsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRUQsK0VBQStFO0lBRXZFLE1BQU0sQ0FDWixNQUE2QixFQUM3QixHQUEyQjtRQUUzQixJQUFJLE1BQTZCLENBQUM7UUFDbEMsSUFBSSxDQUFDO1lBQ0gsTUFBTSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN2QixDQUFDO1FBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztZQUNiLDZFQUE2RTtZQUM3RSwrQ0FBK0M7WUFDL0MsT0FBTyxPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzdCLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVPLFNBQVMsQ0FBQyxNQUE2QjtRQUM3QyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO1lBQUUsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzFELElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQ2hDLGlGQUFpRjtZQUNqRixPQUFPLElBQUksT0FBTyxDQUFvQixDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtnQkFDeEQsSUFBSSxPQUFPLEdBQUcsS0FBSyxDQUFDO2dCQUNwQixNQUFNLE1BQU0sR0FBRyxDQUFDLEVBQWMsRUFBRSxFQUFFO29CQUNoQyxJQUFJLE9BQU87d0JBQUUsT0FBTztvQkFDcEIsT0FBTyxHQUFHLElBQUksQ0FBQztvQkFDZixFQUFFLEVBQUUsQ0FBQztnQkFDUCxDQUFDLENBQUM7Z0JBQ0YsTUFBTSxDQUFDLFNBQVMsQ0FBQztvQkFDZixJQUFJLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQztvQkFDakQsd0VBQXdFO29CQUN4RSxLQUFLLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUN2QywyRUFBMkU7b0JBQzNFLFFBQVEsRUFBRSxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2lCQUMxQyxDQUFDLENBQUM7WUFDTCxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFDRCxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsTUFBb0MsQ0FBQyxDQUFDO0lBQy9ELENBQUM7SUFFTyxjQUFjLENBQUMsS0FBYztRQUNuQyxPQUFPLENBQ0wsT0FBTyxLQUFLLEtBQUssUUFBUTtZQUN6QixLQUFLLEtBQUssSUFBSTtZQUNkLE9BQVEsS0FBeUMsQ0FBQyxTQUFTLEtBQUssVUFBVSxDQUMzRSxDQUFDO0lBQ0osQ0FBQztJQUVELHlGQUF5RjtJQUN6RixPQUFPLENBQUMsQ0FBVSxFQUFFLENBQVUsRUFBRSxJQUFJLEdBQUcsSUFBSTtRQUN6QyxPQUFPLFdBQVcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ2pDLENBQUM7d0dBaEtVLHNCQUFzQjs0R0FBdEIsc0JBQXNCLGNBRFQsTUFBTTs7NEZBQ25CLHNCQUFzQjtrQkFEbEMsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHR5cGUge1xyXG4gIEVudGl0eVJlZmVyZW5jZUxvYWRlcixcclxuICBSYXdSZWZlcmVuY2VJdGVtLFxyXG4gIFJlZmVyZW5jZUxvYWRlckNvbnRleHQsXHJcbiAgUmVmZXJlbmNlTG9hZGVyUmVzdWx0LFxyXG4gIFJlZmVyZW5jZU9wdGlvbixcclxuICBTdWJzY3JpYmFibGUsXHJcbn0gZnJvbSAnQGR5bmFtaWMtZW50aXR5L2NvcmUnO1xyXG5pbXBvcnQge1xyXG4gIGJ1aWxkUmVmZXJlbmNlQ2FjaGVLZXksXHJcbiAgZW50aXR5S2V5RnJvbUNhY2hlS2V5LFxyXG4gIG5vcm1hbGl6ZVJlZmVyZW5jZU9wdGlvbnMsXHJcbiAgcmVzb2x2ZUxhYmVsLFxyXG4gIHZhbHVlc01hdGNoLFxyXG59IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcclxuaW1wb3J0IHsgRU5USVRZX1JFRl9DQUNIRV9TVE9SRSB9IGZyb20gJy4uL3Rva2Vucy9pbmplY3Rpb24tdG9rZW5zJztcclxuaW1wb3J0IHsgRW50aXR5UmVmUmVnaXN0cnlTZXJ2aWNlIH0gZnJvbSAnLi9lbnRpdHktcmVmLXJlZ2lzdHJ5LnNlcnZpY2UnO1xyXG5cclxuLyoqIExhYmVsLWNhY2hlIGZpZWxkIHNlcGFyYXRvci4gS2VwdCBvdXQgb2YgdGVtcGxhdGUgbGl0ZXJhbHMgc28gaXQgc3RheXMgdmlzaWJsZSBpbiBzb3VyY2UuICovXHJcbmNvbnN0IExBQkVMX1NFUCA9ICd8JztcclxuXHJcbi8qKlxyXG4gKiBFbnRpdHlSZWZlcmVuY2VTZXJ2aWNlIOKAlCB0aGUgY2FjaGUgaW4gZnJvbnQgb2YgY29uc3VtZXItcmVnaXN0ZXJlZCBvcHRpb24gbG9hZGVycy5cclxuICpcclxuICogVGhyZWUgbGF5ZXJzLCBtYXRjaGluZyB0aGUgcmVmZXJlbmNlIGltcGxlbWVudGF0aW9uOlxyXG4gKiAgMS4gKipvcHRpb25zKiog4oCUIHJlc29sdmVkIGBSZWZlcmVuY2VPcHRpb25bXWAgcGVyIChlbnRpdHksIGxhbmcsIGRpc3BsYXlGaWVsZHMsIGZpbHRlcnMpLlxyXG4gKiAgMi4gKippbi1mbGlnaHQqKiDigJQgdGhlIHBlbmRpbmcgUHJvbWlzZSwgc28gTiBmaWVsZHMgcmVmZXJlbmNpbmcgb25lIGVudGl0eSB0cmlnZ2VyIG9uZVxyXG4gKiAgICAgbG9hZCByYXRoZXIgdGhhbiBOLiBUaGlzIGlzIHRoZSBsYXllciB0aGF0IGFjdHVhbGx5IHJlbW92ZXMgZHVwbGljYXRlIEhUVFAgY2FsbHM7XHJcbiAqICAgICBhbiBvcHRpb25zIGNhY2hlIGFsb25lIGRvZXMgbm90aGluZyBmb3IgY29uY3VycmVudCBmaXJzdCBsb2Fkcy5cclxuICogIDMuICoqbGFiZWxzKiog4oCUIHN5bmNocm9ub3VzIHZhbHVlIOKGkiB0ZXh0LCBmb3IgcmVuZGVyaW5nIGEgc3RvcmVkIHJlZmVyZW5jZSB3aXRob3V0XHJcbiAqICAgICB3YWl0aW5nIG9uIGEgbG9hZC5cclxuICpcclxuICogSW52YWxpZGF0aW9uIGlzIHBlciBlbnRpdHksIG5vdCBnbG9iYWwuIFRoZSByZWZlcmVuY2UgY291bGQgb25seSBgY2xlYXJDYWNoZSgpYCBldmVyeXRoaW5nXHJcbiAqIChpc3N1ZSAjMTYpLCBzbyBzYXZpbmcgb25lIHJlY29yZCByZS1mZXRjaGVkIGV2ZXJ5IGVudGl0eSdzIG9wdGlvbnMuXHJcbiAqL1xyXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxyXG5leHBvcnQgY2xhc3MgRW50aXR5UmVmZXJlbmNlU2VydmljZSB7XHJcbiAgcHJpdmF0ZSByZWFkb25seSByZWdpc3RyeSA9IGluamVjdChFbnRpdHlSZWZSZWdpc3RyeVNlcnZpY2UpO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgc3RvcmUgPSBpbmplY3QoRU5USVRZX1JFRl9DQUNIRV9TVE9SRSk7XHJcblxyXG4gIC8qKiBMb2FkcyBpbiBwcm9ncmVzcywga2V5ZWQgdGhlIHNhbWUgd2F5IGFzIHRoZSBvcHRpb25zIGNhY2hlLiAqL1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgaW5GbGlnaHQgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZTxSZWZlcmVuY2VPcHRpb25bXT4+KCk7XHJcbiAgLyoqIGBlbnRpdHlLZXl8bGFuZ3xjYW5vbmljYWxWYWx1ZWAgLT4gZGlzcGxheSB0ZXh0LiAqL1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgbGFiZWxzID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcclxuXHJcbiAgLyoqXHJcbiAgICogT3B0aW9ucyBmb3IgYW4gZW50aXR5LCBmcm9tIGNhY2hlIHdoZW4gcHJlc2VudC5cclxuICAgKiBDb25jdXJyZW50IGNhbGxlcnMgd2l0aCB0aGUgc2FtZSBrZXkgc2hhcmUgb25lIGxvYWQuXHJcbiAgICovXHJcbiAgYXN5bmMgbG9hZChlbnRpdHlLZXk6IHN0cmluZywgY3R4OiBSZWZlcmVuY2VMb2FkZXJDb250ZXh0ID0ge30pOiBQcm9taXNlPFJlZmVyZW5jZU9wdGlvbltdPiB7XHJcbiAgICBjb25zdCBrZXkgPSBidWlsZFJlZmVyZW5jZUNhY2hlS2V5KGVudGl0eUtleSwge1xyXG4gICAgICBsYW5nOiBjdHgubGFuZyxcclxuICAgICAgZmlsdGVyczogY3R4LmZpbHRlcnMsXHJcbiAgICAgIGRpc3BsYXlGaWVsZHM6IGN0eC5kaXNwbGF5RmllbGRzLFxyXG4gICAgICBwYXJlbnRWYWx1ZTogY3R4LnBhcmVudFZhbHVlLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgY2FjaGVkID0gdGhpcy5zdG9yZS5nZXQoa2V5KTtcclxuICAgIGlmIChjYWNoZWQpIHJldHVybiBjYWNoZWQ7XHJcblxyXG4gICAgY29uc3QgcGVuZGluZyA9IHRoaXMuaW5GbGlnaHQuZ2V0KGtleSk7XHJcbiAgICBpZiAocGVuZGluZykgcmV0dXJuIHBlbmRpbmc7XHJcblxyXG4gICAgY29uc3QgbG9hZGVyID0gdGhpcy5yZWdpc3RyeS5yZXNvbHZlKGVudGl0eUtleSk7XHJcbiAgICBpZiAoIWxvYWRlcikgcmV0dXJuIFtdO1xyXG5cclxuICAgIGNvbnN0IGxvYWQgPSB0aGlzLmludm9rZShsb2FkZXIsIGN0eClcclxuICAgICAgLnRoZW4ocmF3ID0+IHtcclxuICAgICAgICAvLyBkaXNwbGF5RmllbGRzIGRyaXZlIGxhYmVsIGJ1aWxkaW5nLCB3aGljaCBpcyB3aHkgdGhleSBhcmUgcGFydCBvZiB0aGUgY2FjaGUga2V5LlxyXG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSBub3JtYWxpemVSZWZlcmVuY2VPcHRpb25zKFxyXG4gICAgICAgICAgcmF3IGFzIFJhd1JlZmVyZW5jZUl0ZW1bXSxcclxuICAgICAgICAgIGN0eC5kaXNwbGF5RmllbGRzID8geyBlbmFibGVkOiB0cnVlLCBkaXNwbGF5RmllbGRzOiBjdHguZGlzcGxheUZpZWxkcyB9IDogdW5kZWZpbmVkLFxyXG4gICAgICAgICAgY3R4LmxhbmcgPz8gJ2VuJyxcclxuICAgICAgICApO1xyXG4gICAgICAgIHRoaXMuc3RvcmUuc2V0KGtleSwgb3B0aW9ucyk7XHJcbiAgICAgICAgdGhpcy5yZW1lbWJlckxhYmVscyhlbnRpdHlLZXksIGN0eC5sYW5nID8/ICdlbicsIG9wdGlvbnMpO1xyXG4gICAgICAgIHJldHVybiBvcHRpb25zO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAvLyBBIGZhaWxlZCBsb2FkIHJlc29sdmVzIHRvIFtdIGZvciB0aGUgY2FsbGVyIGJ1dCBpcyBuZXZlciB3cml0dGVuIHRvIHRoZSBzdG9yZSwgc28gYVxyXG4gICAgLy8gdHJhbnNpZW50IGVycm9yIGlzIHJldHJpZWQgb24gdGhlIG5leHQgY2FsbCBpbnN0ZWFkIG9mIHBvaXNvbmluZyB0aGUgY2FjaGUuIE9ubHkgdGhlXHJcbiAgICAvLyBgLnRoZW5gIGFib3ZlIGNhY2hlcywgYW5kIGEgcmVqZWN0aW9uIHNraXBzIGl0LlxyXG4gICAgY29uc3QgZ3VhcmRlZCA9IGxvYWRcclxuICAgICAgLmNhdGNoKCgpID0+IFtdIGFzIFJlZmVyZW5jZU9wdGlvbltdKVxyXG4gICAgICAuZmluYWxseSgoKSA9PiB0aGlzLmluRmxpZ2h0LmRlbGV0ZShrZXkpKTtcclxuXHJcbiAgICB0aGlzLmluRmxpZ2h0LnNldChrZXksIGd1YXJkZWQpO1xyXG4gICAgcmV0dXJuIGd1YXJkZWQ7XHJcbiAgfVxyXG5cclxuICAvKiogQ2FjaGVkIG9wdGlvbnMgd2l0aG91dCB0cmlnZ2VyaW5nIGEgbG9hZC4gYHVuZGVmaW5lZGAgd2hlbiBub3QgY2FjaGVkLiAqL1xyXG4gIHBlZWsoZW50aXR5S2V5OiBzdHJpbmcsIGN0eDogUmVmZXJlbmNlTG9hZGVyQ29udGV4dCA9IHt9KTogUmVmZXJlbmNlT3B0aW9uW10gfCB1bmRlZmluZWQge1xyXG4gICAgcmV0dXJuIHRoaXMuc3RvcmUuZ2V0KFxyXG4gICAgICBidWlsZFJlZmVyZW5jZUNhY2hlS2V5KGVudGl0eUtleSwge1xyXG4gICAgICAgIGxhbmc6IGN0eC5sYW5nLFxyXG4gICAgICAgIGZpbHRlcnM6IGN0eC5maWx0ZXJzLFxyXG4gICAgICAgIGRpc3BsYXlGaWVsZHM6IGN0eC5kaXNwbGF5RmllbGRzLFxyXG4gICAgICAgIHBhcmVudFZhbHVlOiBjdHgucGFyZW50VmFsdWUsXHJcbiAgICAgIH0pLFxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIERpc3BsYXkgdGV4dCBmb3IgYSBzdG9yZWQgcmVmZXJlbmNlIHZhbHVlLCBzeW5jaHJvbm91c2x5LlxyXG4gICAqIFJldHVybnMgYHVuZGVmaW5lZGAgd2hlbiB0aGUgZW50aXR5J3Mgb3B0aW9ucyBoYXZlIG5ldmVyIGJlZW4gbG9hZGVkLlxyXG4gICAqL1xyXG4gIGxhYmVsRm9yKGVudGl0eUtleTogc3RyaW5nLCB2YWx1ZTogdW5rbm93biwgbGFuZyA9ICdlbicpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xyXG4gICAgcmV0dXJuIHRoaXMubGFiZWxzLmdldCh0aGlzLmxhYmVsS2V5KGVudGl0eUtleSwgbGFuZywgdmFsdWUpKTtcclxuICB9XHJcblxyXG4gIC8qKiBEcm9wIGV2ZXJ5dGhpbmcgY2FjaGVkIGZvciBvbmUgZW50aXR5LCBsZWF2aW5nIG90aGVyIGVudGl0aWVzIGludGFjdC4gKi9cclxuICBpbnZhbGlkYXRlKGVudGl0eUtleTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBmb3IgKGNvbnN0IGtleSBvZiB0aGlzLnN0b3JlLmtleXMoKSkge1xyXG4gICAgICBpZiAoZW50aXR5S2V5RnJvbUNhY2hlS2V5KGtleSkgPT09IGVudGl0eUtleSkgdGhpcy5zdG9yZS5kZWxldGUoa2V5KTtcclxuICAgIH1cclxuICAgIGZvciAoY29uc3Qga2V5IG9mIFsuLi50aGlzLmluRmxpZ2h0LmtleXMoKV0pIHtcclxuICAgICAgaWYgKGVudGl0eUtleUZyb21DYWNoZUtleShrZXkpID09PSBlbnRpdHlLZXkpIHRoaXMuaW5GbGlnaHQuZGVsZXRlKGtleSk7XHJcbiAgICB9XHJcbiAgICBjb25zdCBwcmVmaXggPSBgJHtlbnRpdHlLZXl9JHtMQUJFTF9TRVB9YDtcclxuICAgIGZvciAoY29uc3Qga2V5IG9mIFsuLi50aGlzLmxhYmVscy5rZXlzKCldKSB7XHJcbiAgICAgIGlmIChrZXkuc3RhcnRzV2l0aChwcmVmaXgpKSB0aGlzLmxhYmVscy5kZWxldGUoa2V5KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNsZWFyKCk6IHZvaWQge1xyXG4gICAgdGhpcy5zdG9yZS5jbGVhcigpO1xyXG4gICAgdGhpcy5pbkZsaWdodC5jbGVhcigpO1xyXG4gICAgdGhpcy5sYWJlbHMuY2xlYXIoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcmVtZW1iZXJMYWJlbHMoZW50aXR5S2V5OiBzdHJpbmcsIGxhbmc6IHN0cmluZywgb3B0aW9uczogUmVmZXJlbmNlT3B0aW9uW10pOiB2b2lkIHtcclxuICAgIGZvciAoY29uc3Qgb3B0aW9uIG9mIG9wdGlvbnMpIHtcclxuICAgICAgdGhpcy5sYWJlbHMuc2V0KHRoaXMubGFiZWxLZXkoZW50aXR5S2V5LCBsYW5nLCBvcHRpb24udmFsdWUpLCBvcHRpb24ubGFiZWwpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIExhYmVsLWNhY2hlIGtleS4gQW4gb2JqZWN0IHZhbHVlIGNvbGxhcHNlcyB0byBpdHMgcmVzb2x2ZWQgdGV4dCBmb3IgdGhlIGFjdGl2ZSBsYW5ndWFnZS4gKi9cclxuICBwcml2YXRlIGxhYmVsS2V5KGVudGl0eUtleTogc3RyaW5nLCBsYW5nOiBzdHJpbmcsIHZhbHVlOiB1bmtub3duKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGNhbm9uaWNhbCA9XHJcbiAgICAgIHZhbHVlICE9PSBudWxsICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCdcclxuICAgICAgICA/IHJlc29sdmVMYWJlbCh2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LCBsYW5nKVxyXG4gICAgICAgIDogU3RyaW5nKHZhbHVlID8/ICcnKTtcclxuICAgIHJldHVybiBbZW50aXR5S2V5LCBsYW5nLCBjYW5vbmljYWxdLmpvaW4oTEFCRUxfU0VQKTtcclxuICB9XHJcblxyXG4gIC8vIOKUgOKUgOKUgCBMb2FkZXIgcmVzdWx0IGNvZXJjaW9uIChhcnJheSB8IFByb21pc2UgfCBPYnNlcnZhYmxlKSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcclxuXHJcbiAgcHJpdmF0ZSBpbnZva2UoXHJcbiAgICBsb2FkZXI6IEVudGl0eVJlZmVyZW5jZUxvYWRlcixcclxuICAgIGN0eDogUmVmZXJlbmNlTG9hZGVyQ29udGV4dCxcclxuICApOiBQcm9taXNlPFJlZmVyZW5jZU9wdGlvbltdPiB7XHJcbiAgICBsZXQgcmVzdWx0OiBSZWZlcmVuY2VMb2FkZXJSZXN1bHQ7XHJcbiAgICB0cnkge1xyXG4gICAgICByZXN1bHQgPSBsb2FkZXIoY3R4KTtcclxuICAgIH0gY2F0Y2ggKGVycikge1xyXG4gICAgICAvLyBSZWplY3QgcmF0aGVyIHRoYW4gcmVzb2x2ZSBlbXB0eTogYGxvYWRgIG11c3QgYmUgYWJsZSB0byB0ZWxsIGZhaWx1cmUgZnJvbVxyXG4gICAgICAvLyBcIm5vIG1hdGNoZXNcIiwgb3IgaXQgd291bGQgY2FjaGUgdGhlIGZhaWx1cmUuXHJcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnIpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRoaXMudG9Qcm9taXNlKHJlc3VsdCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHRvUHJvbWlzZShyZXN1bHQ6IFJlZmVyZW5jZUxvYWRlclJlc3VsdCk6IFByb21pc2U8UmVmZXJlbmNlT3B0aW9uW10+IHtcclxuICAgIGlmIChBcnJheS5pc0FycmF5KHJlc3VsdCkpIHJldHVybiBQcm9taXNlLnJlc29sdmUocmVzdWx0KTtcclxuICAgIGlmICh0aGlzLmlzU3Vic2NyaWJhYmxlKHJlc3VsdCkpIHtcclxuICAgICAgLy8gRmlyc3QgZW1pc3Npb24gd2lucywgc28gYW4gT2JzZXJ2YWJsZSB0aGF0IHN0YXlzIG9wZW4gc3RpbGwgcmVzb2x2ZXMgdGhlIGxvYWQuXHJcbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxSZWZlcmVuY2VPcHRpb25bXT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICAgIGxldCBzZXR0bGVkID0gZmFsc2U7XHJcbiAgICAgICAgY29uc3Qgc2V0dGxlID0gKGZuOiAoKSA9PiB2b2lkKSA9PiB7XHJcbiAgICAgICAgICBpZiAoc2V0dGxlZCkgcmV0dXJuO1xyXG4gICAgICAgICAgc2V0dGxlZCA9IHRydWU7XHJcbiAgICAgICAgICBmbigpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgcmVzdWx0LnN1YnNjcmliZSh7XHJcbiAgICAgICAgICBuZXh0OiB2YWx1ZSA9PiBzZXR0bGUoKCkgPT4gcmVzb2x2ZSh2YWx1ZSA/PyBbXSkpLFxyXG4gICAgICAgICAgLy8gQW4gZXJyb3Jpbmcgc3RyZWFtIGlzIGEgZmFpbGVkIGxvYWQsIG5vdCBhbiBlbXB0eSBvbmUg4oCUIHNlZSBgaW52b2tlYC5cclxuICAgICAgICAgIGVycm9yOiBlcnIgPT4gc2V0dGxlKCgpID0+IHJlamVjdChlcnIpKSxcclxuICAgICAgICAgIC8vIENvbXBsZXRpbmcgd2l0aG91dCBlbWl0dGluZyBpcyBhIGxlZ2l0aW1hdGUgZW1wdHkgcmVzdWx0LCBhbmQgaXMgY2FjaGVkLlxyXG4gICAgICAgICAgY29tcGxldGU6ICgpID0+IHNldHRsZSgoKSA9PiByZXNvbHZlKFtdKSksXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXN1bHQgYXMgUHJvbWlzZTxSZWZlcmVuY2VPcHRpb25bXT4pO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBpc1N1YnNjcmliYWJsZSh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIFN1YnNjcmliYWJsZTxSZWZlcmVuY2VPcHRpb25bXT4ge1xyXG4gICAgcmV0dXJuIChcclxuICAgICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJlxyXG4gICAgICB2YWx1ZSAhPT0gbnVsbCAmJlxyXG4gICAgICB0eXBlb2YgKHZhbHVlIGFzIFN1YnNjcmliYWJsZTxSZWZlcmVuY2VPcHRpb25bXT4pLnN1YnNjcmliZSA9PT0gJ2Z1bmN0aW9uJ1xyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIC8qKiBFeHBvc2VkIGZvciBjYXNjYWRlIGZpbHRlcmluZywgd2hpY2ggbWF0Y2hlcyBhIHBhcmVudCB2YWx1ZSBhZ2FpbnN0IG9wdGlvbiB2YWx1ZXMuICovXHJcbiAgbWF0Y2hlcyhhOiB1bmtub3duLCBiOiB1bmtub3duLCBsYW5nID0gJ2VuJyk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHZhbHVlc01hdGNoKGEsIGIsIGxhbmcpO1xyXG4gIH1cclxufVxyXG4iXX0=
@@ -1,44 +1,49 @@
1
1
  import { Injectable, inject } from '@angular/core';
2
- import { FIELD_TYPE_REGISTRY } from '../tokens/injection-tokens';
3
- // Built-in field components — pre-registered in this service
4
- import { TextFieldComponent } from '../field-types/text-field.component';
5
- import { TextareaFieldComponent } from '../field-types/textarea-field.component';
6
- import { NumberFieldComponent } from '../field-types/number-field.component';
7
- import { CheckboxFieldComponent } from '../field-types/checkbox-field.component';
8
- import { DateFieldComponent } from '../field-types/date-field.component';
9
- import { DropdownFieldComponent } from '../field-types/dropdown-field.component';
10
- import { MultiSelectFieldComponent } from '../field-types/multi-select-field.component';
11
- import { EntityRefFieldComponent } from '../field-types/entity-ref-field.component';
2
+ import { FIELD_TYPE_REGISTRY, FIELD_TYPE_SETS } from '../tokens/injection-tokens';
12
3
  import * as i0 from "@angular/core";
13
4
  /**
14
5
  * FieldRegistryService — resolves field type strings to Angular component classes.
15
- * Open/Closed: open for extension via consumer fieldTypes config, closed for modification.
16
- * DynamicFieldComponent uses this to mount the right component via createComponent().
6
+ *
7
+ * **Tree-shaking contract:** this service holds *no* static imports of field components.
8
+ * Nothing is bundled until something registers it, which is what makes the built-ins
9
+ * opt-in. Register them with `provideBuiltInFieldTypes()` (all 19 keys) or a narrower
10
+ * subset via `provideFieldTypes({ ... })` — see `providers/provide-field-types.ts`.
11
+ *
12
+ * Resolution order: consumer token registry → runtime registrations → nothing.
17
13
  */
18
14
  export class FieldRegistryService {
19
15
  consumerRegistry = inject(FIELD_TYPE_REGISTRY, { optional: true }) ?? new Map();
20
- /** Built-in field type → component map. Never remove an entry. */
21
- builtInRegistry = new Map([
22
- ['text', TextFieldComponent],
23
- ['textarea', TextareaFieldComponent],
24
- ['number', NumberFieldComponent],
25
- ['checkbox', CheckboxFieldComponent],
26
- ['date', DateFieldComponent],
27
- ['dropdown', DropdownFieldComponent],
28
- ['multiSelect', MultiSelectFieldComponent],
29
- ['entity-ref', EntityRefFieldComponent],
30
- ]);
16
+ dynamicRegistry = new Map();
17
+ constructor() {
18
+ // Sets contributed by provideFieldTypes()/provideBuiltInFieldTypes(), in declaration order.
19
+ for (const set of inject(FIELD_TYPE_SETS, { optional: true }) ?? []) {
20
+ this.registerAll(set);
21
+ }
22
+ }
23
+ /** Register a field type component mapping at runtime. */
24
+ register(type, component) {
25
+ this.dynamicRegistry.set(type, component);
26
+ }
27
+ /** Register multiple field type component mappings at runtime. */
28
+ registerAll(map) {
29
+ for (const [type, comp] of Object.entries(map)) {
30
+ this.dynamicRegistry.set(type, comp);
31
+ }
32
+ }
31
33
  /**
32
34
  * Resolve a field type string to a component class.
33
- * Consumer registry takes precedence over built-ins (open for extension).
34
- * Returns null if type is unknown — caller must handle gracefully.
35
+ * Consumer token registry takes priority over runtime registrations.
35
36
  */
36
37
  resolve(fieldType) {
37
- return this.consumerRegistry.get(fieldType) ?? this.builtInRegistry.get(fieldType) ?? null;
38
+ return this.consumerRegistry.get(fieldType) ?? this.dynamicRegistry.get(fieldType) ?? null;
38
39
  }
39
- /** Check if a field type has a registered component */
40
+ /** Check if a field type has a registered component. */
40
41
  has(fieldType) {
41
- return this.consumerRegistry.has(fieldType) || this.builtInRegistry.has(fieldType);
42
+ return this.consumerRegistry.has(fieldType) || this.dynamicRegistry.has(fieldType);
43
+ }
44
+ /** Every registered field type key. Consumer overrides and runtime registrations combined. */
45
+ registeredTypes() {
46
+ return [...new Set([...this.dynamicRegistry.keys(), ...this.consumerRegistry.keys()])].sort();
42
47
  }
43
48
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FieldRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
44
49
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FieldRegistryService, providedIn: 'root' });
@@ -46,5 +51,5 @@ export class FieldRegistryService {
46
51
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FieldRegistryService, decorators: [{
47
52
  type: Injectable,
48
53
  args: [{ providedIn: 'root' }]
49
- }] });
50
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmllbGQtcmVnaXN0cnkuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvc2VydmljZXMvZmllbGQtcmVnaXN0cnkuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFRLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN6RCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUVqRSw2REFBNkQ7QUFDN0QsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDekUsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDakYsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDN0UsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDakYsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDekUsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDakYsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sNkNBQTZDLENBQUM7QUFDeEYsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sMkNBQTJDLENBQUM7O0FBRXBGOzs7O0dBSUc7QUFFSCxNQUFNLE9BQU8sb0JBQW9CO0lBQ2QsZ0JBQWdCLEdBQUcsTUFBTSxDQUFDLG1CQUFtQixFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLElBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUVqRyxrRUFBa0U7SUFDakQsZUFBZSxHQUFHLElBQUksR0FBRyxDQUFvQjtRQUM1RCxDQUFDLE1BQU0sRUFBRSxrQkFBa0IsQ0FBQztRQUM1QixDQUFDLFVBQVUsRUFBRSxzQkFBc0IsQ0FBQztRQUNwQyxDQUFDLFFBQVEsRUFBRSxvQkFBb0IsQ0FBQztRQUNoQyxDQUFDLFVBQVUsRUFBRSxzQkFBc0IsQ0FBQztRQUNwQyxDQUFDLE1BQU0sRUFBRSxrQkFBa0IsQ0FBQztRQUM1QixDQUFDLFVBQVUsRUFBRSxzQkFBc0IsQ0FBQztRQUNwQyxDQUFDLGFBQWEsRUFBRSx5QkFBeUIsQ0FBQztRQUMxQyxDQUFDLFlBQVksRUFBRSx1QkFBdUIsQ0FBQztLQUN4QyxDQUFDLENBQUM7SUFFSDs7OztPQUlHO0lBQ0gsT0FBTyxDQUFDLFNBQWlCO1FBQ3ZCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsSUFBSSxJQUFJLENBQUM7SUFDN0YsQ0FBQztJQUVELHVEQUF1RDtJQUN2RCxHQUFHLENBQUMsU0FBaUI7UUFDbkIsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxJQUFJLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3JGLENBQUM7d0dBM0JVLG9CQUFvQjs0R0FBcEIsb0JBQW9CLGNBRFAsTUFBTTs7NEZBQ25CLG9CQUFvQjtrQkFEaEMsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBUeXBlLCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZJRUxEX1RZUEVfUkVHSVNUUlkgfSBmcm9tICcuLi90b2tlbnMvaW5qZWN0aW9uLXRva2Vucyc7XG5cbi8vIEJ1aWx0LWluIGZpZWxkIGNvbXBvbmVudHMg4oCUIHByZS1yZWdpc3RlcmVkIGluIHRoaXMgc2VydmljZVxuaW1wb3J0IHsgVGV4dEZpZWxkQ29tcG9uZW50IH0gZnJvbSAnLi4vZmllbGQtdHlwZXMvdGV4dC1maWVsZC5jb21wb25lbnQnO1xuaW1wb3J0IHsgVGV4dGFyZWFGaWVsZENvbXBvbmVudCB9IGZyb20gJy4uL2ZpZWxkLXR5cGVzL3RleHRhcmVhLWZpZWxkLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBOdW1iZXJGaWVsZENvbXBvbmVudCB9IGZyb20gJy4uL2ZpZWxkLXR5cGVzL251bWJlci1maWVsZC5jb21wb25lbnQnO1xuaW1wb3J0IHsgQ2hlY2tib3hGaWVsZENvbXBvbmVudCB9IGZyb20gJy4uL2ZpZWxkLXR5cGVzL2NoZWNrYm94LWZpZWxkLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBEYXRlRmllbGRDb21wb25lbnQgfSBmcm9tICcuLi9maWVsZC10eXBlcy9kYXRlLWZpZWxkLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBEcm9wZG93bkZpZWxkQ29tcG9uZW50IH0gZnJvbSAnLi4vZmllbGQtdHlwZXMvZHJvcGRvd24tZmllbGQuY29tcG9uZW50JztcbmltcG9ydCB7IE11bHRpU2VsZWN0RmllbGRDb21wb25lbnQgfSBmcm9tICcuLi9maWVsZC10eXBlcy9tdWx0aS1zZWxlY3QtZmllbGQuY29tcG9uZW50JztcbmltcG9ydCB7IEVudGl0eVJlZkZpZWxkQ29tcG9uZW50IH0gZnJvbSAnLi4vZmllbGQtdHlwZXMvZW50aXR5LXJlZi1maWVsZC5jb21wb25lbnQnO1xuXG4vKipcbiAqIEZpZWxkUmVnaXN0cnlTZXJ2aWNlIOKAlCByZXNvbHZlcyBmaWVsZCB0eXBlIHN0cmluZ3MgdG8gQW5ndWxhciBjb21wb25lbnQgY2xhc3Nlcy5cbiAqIE9wZW4vQ2xvc2VkOiBvcGVuIGZvciBleHRlbnNpb24gdmlhIGNvbnN1bWVyIGZpZWxkVHlwZXMgY29uZmlnLCBjbG9zZWQgZm9yIG1vZGlmaWNhdGlvbi5cbiAqIER5bmFtaWNGaWVsZENvbXBvbmVudCB1c2VzIHRoaXMgdG8gbW91bnQgdGhlIHJpZ2h0IGNvbXBvbmVudCB2aWEgY3JlYXRlQ29tcG9uZW50KCkuXG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgRmllbGRSZWdpc3RyeVNlcnZpY2Uge1xuICBwcml2YXRlIHJlYWRvbmx5IGNvbnN1bWVyUmVnaXN0cnkgPSBpbmplY3QoRklFTERfVFlQRV9SRUdJU1RSWSwgeyBvcHRpb25hbDogdHJ1ZSB9KSA/PyBuZXcgTWFwKCk7XG5cbiAgLyoqIEJ1aWx0LWluIGZpZWxkIHR5cGUg4oaSIGNvbXBvbmVudCBtYXAuIE5ldmVyIHJlbW92ZSBhbiBlbnRyeS4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBidWlsdEluUmVnaXN0cnkgPSBuZXcgTWFwPHN0cmluZywgVHlwZTxhbnk+PihbXG4gICAgWyd0ZXh0JywgVGV4dEZpZWxkQ29tcG9uZW50XSxcbiAgICBbJ3RleHRhcmVhJywgVGV4dGFyZWFGaWVsZENvbXBvbmVudF0sXG4gICAgWydudW1iZXInLCBOdW1iZXJGaWVsZENvbXBvbmVudF0sXG4gICAgWydjaGVja2JveCcsIENoZWNrYm94RmllbGRDb21wb25lbnRdLFxuICAgIFsnZGF0ZScsIERhdGVGaWVsZENvbXBvbmVudF0sXG4gICAgWydkcm9wZG93bicsIERyb3Bkb3duRmllbGRDb21wb25lbnRdLFxuICAgIFsnbXVsdGlTZWxlY3QnLCBNdWx0aVNlbGVjdEZpZWxkQ29tcG9uZW50XSxcbiAgICBbJ2VudGl0eS1yZWYnLCBFbnRpdHlSZWZGaWVsZENvbXBvbmVudF0sXG4gIF0pO1xuXG4gIC8qKlxuICAgKiBSZXNvbHZlIGEgZmllbGQgdHlwZSBzdHJpbmcgdG8gYSBjb21wb25lbnQgY2xhc3MuXG4gICAqIENvbnN1bWVyIHJlZ2lzdHJ5IHRha2VzIHByZWNlZGVuY2Ugb3ZlciBidWlsdC1pbnMgKG9wZW4gZm9yIGV4dGVuc2lvbikuXG4gICAqIFJldHVybnMgbnVsbCBpZiB0eXBlIGlzIHVua25vd24g4oCUIGNhbGxlciBtdXN0IGhhbmRsZSBncmFjZWZ1bGx5LlxuICAgKi9cbiAgcmVzb2x2ZShmaWVsZFR5cGU6IHN0cmluZyk6IFR5cGU8YW55PiB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLmNvbnN1bWVyUmVnaXN0cnkuZ2V0KGZpZWxkVHlwZSkgPz8gdGhpcy5idWlsdEluUmVnaXN0cnkuZ2V0KGZpZWxkVHlwZSkgPz8gbnVsbDtcbiAgfVxuXG4gIC8qKiBDaGVjayBpZiBhIGZpZWxkIHR5cGUgaGFzIGEgcmVnaXN0ZXJlZCBjb21wb25lbnQgKi9cbiAgaGFzKGZpZWxkVHlwZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuY29uc3VtZXJSZWdpc3RyeS5oYXMoZmllbGRUeXBlKSB8fCB0aGlzLmJ1aWx0SW5SZWdpc3RyeS5oYXMoZmllbGRUeXBlKTtcbiAgfVxufVxuIl19
54
+ }], ctorParameters: () => [] });
55
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmllbGQtcmVnaXN0cnkuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvc2VydmljZXMvZmllbGQtcmVnaXN0cnkuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFRLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN6RCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsZUFBZSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7O0FBRWxGOzs7Ozs7Ozs7R0FTRztBQUVILE1BQU0sT0FBTyxvQkFBb0I7SUFDZCxnQkFBZ0IsR0FDL0IsTUFBTSxDQUFDLG1CQUFtQixFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLElBQUksSUFBSSxHQUFHLEVBQXFCLENBQUM7SUFDakUsZUFBZSxHQUFHLElBQUksR0FBRyxFQUFxQixDQUFDO0lBRWhFO1FBQ0UsNEZBQTRGO1FBQzVGLEtBQUssTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLGVBQWUsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDO1lBQ3BFLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDeEIsQ0FBQztJQUNILENBQUM7SUFFRCwwREFBMEQ7SUFDMUQsUUFBUSxDQUFDLElBQVksRUFBRSxTQUFvQjtRQUN6QyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVELGtFQUFrRTtJQUNsRSxXQUFXLENBQUMsR0FBOEI7UUFDeEMsS0FBSyxNQUFNLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUMvQyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDdkMsQ0FBQztJQUNILENBQUM7SUFFRDs7O09BR0c7SUFDSCxPQUFPLENBQUMsU0FBaUI7UUFDdkIsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxJQUFJLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxJQUFJLElBQUksQ0FBQztJQUM3RixDQUFDO0lBRUQsd0RBQXdEO0lBQ3hELEdBQUcsQ0FBQyxTQUFpQjtRQUNuQixPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLElBQUksSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDckYsQ0FBQztJQUVELDhGQUE4RjtJQUM5RixlQUFlO1FBQ2IsT0FBTyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDaEcsQ0FBQzt3R0F4Q1Usb0JBQW9COzRHQUFwQixvQkFBb0IsY0FEUCxNQUFNOzs0RkFDbkIsb0JBQW9CO2tCQURoQyxVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIFR5cGUsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBGSUVMRF9UWVBFX1JFR0lTVFJZLCBGSUVMRF9UWVBFX1NFVFMgfSBmcm9tICcuLi90b2tlbnMvaW5qZWN0aW9uLXRva2Vucyc7XHJcblxyXG4vKipcclxuICogRmllbGRSZWdpc3RyeVNlcnZpY2Ug4oCUIHJlc29sdmVzIGZpZWxkIHR5cGUgc3RyaW5ncyB0byBBbmd1bGFyIGNvbXBvbmVudCBjbGFzc2VzLlxyXG4gKlxyXG4gKiAqKlRyZWUtc2hha2luZyBjb250cmFjdDoqKiB0aGlzIHNlcnZpY2UgaG9sZHMgKm5vKiBzdGF0aWMgaW1wb3J0cyBvZiBmaWVsZCBjb21wb25lbnRzLlxyXG4gKiBOb3RoaW5nIGlzIGJ1bmRsZWQgdW50aWwgc29tZXRoaW5nIHJlZ2lzdGVycyBpdCwgd2hpY2ggaXMgd2hhdCBtYWtlcyB0aGUgYnVpbHQtaW5zXHJcbiAqIG9wdC1pbi4gUmVnaXN0ZXIgdGhlbSB3aXRoIGBwcm92aWRlQnVpbHRJbkZpZWxkVHlwZXMoKWAgKGFsbCAxOSBrZXlzKSBvciBhIG5hcnJvd2VyXHJcbiAqIHN1YnNldCB2aWEgYHByb3ZpZGVGaWVsZFR5cGVzKHsgLi4uIH0pYCDigJQgc2VlIGBwcm92aWRlcnMvcHJvdmlkZS1maWVsZC10eXBlcy50c2AuXHJcbiAqXHJcbiAqIFJlc29sdXRpb24gb3JkZXI6IGNvbnN1bWVyIHRva2VuIHJlZ2lzdHJ5IOKGkiBydW50aW1lIHJlZ2lzdHJhdGlvbnMg4oaSIG5vdGhpbmcuXHJcbiAqL1xyXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxyXG5leHBvcnQgY2xhc3MgRmllbGRSZWdpc3RyeVNlcnZpY2Uge1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgY29uc3VtZXJSZWdpc3RyeSA9XHJcbiAgICBpbmplY3QoRklFTERfVFlQRV9SRUdJU1RSWSwgeyBvcHRpb25hbDogdHJ1ZSB9KSA/PyBuZXcgTWFwPHN0cmluZywgVHlwZTxhbnk+PigpO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgZHluYW1pY1JlZ2lzdHJ5ID0gbmV3IE1hcDxzdHJpbmcsIFR5cGU8YW55Pj4oKTtcclxuXHJcbiAgY29uc3RydWN0b3IoKSB7XHJcbiAgICAvLyBTZXRzIGNvbnRyaWJ1dGVkIGJ5IHByb3ZpZGVGaWVsZFR5cGVzKCkvcHJvdmlkZUJ1aWx0SW5GaWVsZFR5cGVzKCksIGluIGRlY2xhcmF0aW9uIG9yZGVyLlxyXG4gICAgZm9yIChjb25zdCBzZXQgb2YgaW5qZWN0KEZJRUxEX1RZUEVfU0VUUywgeyBvcHRpb25hbDogdHJ1ZSB9KSA/PyBbXSkge1xyXG4gICAgICB0aGlzLnJlZ2lzdGVyQWxsKHNldCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKiogUmVnaXN0ZXIgYSBmaWVsZCB0eXBlIGNvbXBvbmVudCBtYXBwaW5nIGF0IHJ1bnRpbWUuICovXHJcbiAgcmVnaXN0ZXIodHlwZTogc3RyaW5nLCBjb21wb25lbnQ6IFR5cGU8YW55Pik6IHZvaWQge1xyXG4gICAgdGhpcy5keW5hbWljUmVnaXN0cnkuc2V0KHR5cGUsIGNvbXBvbmVudCk7XHJcbiAgfVxyXG5cclxuICAvKiogUmVnaXN0ZXIgbXVsdGlwbGUgZmllbGQgdHlwZSBjb21wb25lbnQgbWFwcGluZ3MgYXQgcnVudGltZS4gKi9cclxuICByZWdpc3RlckFsbChtYXA6IFJlY29yZDxzdHJpbmcsIFR5cGU8YW55Pj4pOiB2b2lkIHtcclxuICAgIGZvciAoY29uc3QgW3R5cGUsIGNvbXBdIG9mIE9iamVjdC5lbnRyaWVzKG1hcCkpIHtcclxuICAgICAgdGhpcy5keW5hbWljUmVnaXN0cnkuc2V0KHR5cGUsIGNvbXApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmVzb2x2ZSBhIGZpZWxkIHR5cGUgc3RyaW5nIHRvIGEgY29tcG9uZW50IGNsYXNzLlxyXG4gICAqIENvbnN1bWVyIHRva2VuIHJlZ2lzdHJ5IHRha2VzIHByaW9yaXR5IG92ZXIgcnVudGltZSByZWdpc3RyYXRpb25zLlxyXG4gICAqL1xyXG4gIHJlc29sdmUoZmllbGRUeXBlOiBzdHJpbmcpOiBUeXBlPGFueT4gfCBudWxsIHtcclxuICAgIHJldHVybiB0aGlzLmNvbnN1bWVyUmVnaXN0cnkuZ2V0KGZpZWxkVHlwZSkgPz8gdGhpcy5keW5hbWljUmVnaXN0cnkuZ2V0KGZpZWxkVHlwZSkgPz8gbnVsbDtcclxuICB9XHJcblxyXG4gIC8qKiBDaGVjayBpZiBhIGZpZWxkIHR5cGUgaGFzIGEgcmVnaXN0ZXJlZCBjb21wb25lbnQuICovXHJcbiAgaGFzKGZpZWxkVHlwZTogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5jb25zdW1lclJlZ2lzdHJ5LmhhcyhmaWVsZFR5cGUpIHx8IHRoaXMuZHluYW1pY1JlZ2lzdHJ5LmhhcyhmaWVsZFR5cGUpO1xyXG4gIH1cclxuXHJcbiAgLyoqIEV2ZXJ5IHJlZ2lzdGVyZWQgZmllbGQgdHlwZSBrZXkuIENvbnN1bWVyIG92ZXJyaWRlcyBhbmQgcnVudGltZSByZWdpc3RyYXRpb25zIGNvbWJpbmVkLiAqL1xyXG4gIHJlZ2lzdGVyZWRUeXBlcygpOiBzdHJpbmdbXSB7XHJcbiAgICByZXR1cm4gWy4uLm5ldyBTZXQoWy4uLnRoaXMuZHluYW1pY1JlZ2lzdHJ5LmtleXMoKSwgLi4udGhpcy5jb25zdW1lclJlZ2lzdHJ5LmtleXMoKV0pXS5zb3J0KCk7XHJcbiAgfVxyXG59XHJcbiJdfQ==
@@ -0,0 +1,89 @@
1
+ import { Injectable, inject } from '@angular/core';
2
+ import { UPLOAD_HANDLER } from '../tokens/injection-tokens';
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * FileUploadService — the single place image-field and file-field agree on how a
6
+ * selected `File` becomes a `FileRef`.
7
+ *
8
+ * With `UPLOAD_HANDLER` registered the file is persisted and stored as `{ url }`;
9
+ * without one it is stored as `{ file }` for the consumer to upload at submit time.
10
+ */
11
+ export class FileUploadService {
12
+ handler = inject(UPLOAD_HANDLER, { optional: true });
13
+ get hasHandler() {
14
+ return !!this.handler;
15
+ }
16
+ /** Metadata common to both persisted and unpersisted refs. */
17
+ describe(file) {
18
+ return { name: file.name, size: file.size, mimeType: file.type };
19
+ }
20
+ /**
21
+ * Turn a selected File into the value to store on the control.
22
+ * @throws when a registered handler rejects — callers surface it as a field error.
23
+ */
24
+ async toFileRef(file) {
25
+ const meta = this.describe(file);
26
+ if (!this.handler)
27
+ return { ...meta, file };
28
+ const result = await this.normalize(this.handler(file));
29
+ return { ...meta, url: result.url, name: result.name ?? meta.name };
30
+ }
31
+ /** Object URL for previewing an unpersisted File. Callers must revoke it. */
32
+ previewUrlFor(ref) {
33
+ if (!ref)
34
+ return null;
35
+ if (ref.url)
36
+ return ref.url;
37
+ if (ref.file && typeof URL !== 'undefined' && typeof URL.createObjectURL === 'function') {
38
+ return URL.createObjectURL(ref.file);
39
+ }
40
+ return null;
41
+ }
42
+ revokePreviewUrl(url) {
43
+ if (!url || !url.startsWith('blob:'))
44
+ return;
45
+ if (typeof URL !== 'undefined' && typeof URL.revokeObjectURL === 'function') {
46
+ URL.revokeObjectURL(url);
47
+ }
48
+ }
49
+ normalize(result) {
50
+ if (this.isSubscribable(result)) {
51
+ return new Promise((resolve, reject) => {
52
+ let settled = false;
53
+ result.subscribe({
54
+ next: value => {
55
+ if (settled)
56
+ return;
57
+ settled = true;
58
+ resolve(value);
59
+ },
60
+ error: err => {
61
+ if (settled)
62
+ return;
63
+ settled = true;
64
+ reject(err);
65
+ },
66
+ complete: () => {
67
+ if (settled)
68
+ return;
69
+ settled = true;
70
+ reject(new Error('Upload handler completed without emitting a result.'));
71
+ },
72
+ });
73
+ });
74
+ }
75
+ return Promise.resolve(result);
76
+ }
77
+ isSubscribable(value) {
78
+ return (typeof value === 'object' &&
79
+ value !== null &&
80
+ typeof value.subscribe === 'function');
81
+ }
82
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileUploadService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
83
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileUploadService, providedIn: 'root' });
84
+ }
85
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileUploadService, decorators: [{
86
+ type: Injectable,
87
+ args: [{ providedIn: 'root' }]
88
+ }] });
89
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZS11cGxvYWQuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvc2VydmljZXMvZmlsZS11cGxvYWQuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUVuRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7O0FBRTVEOzs7Ozs7R0FNRztBQUVILE1BQU0sT0FBTyxpQkFBaUI7SUFDWCxPQUFPLEdBQUcsTUFBTSxDQUFDLGNBQWMsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBRXRFLElBQUksVUFBVTtRQUNaLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDeEIsQ0FBQztJQUVELDhEQUE4RDtJQUN0RCxRQUFRLENBQUMsSUFBVTtRQUN6QixPQUFPLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNuRSxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFVO1FBQ3hCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDakMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPO1lBQUUsT0FBTyxFQUFFLEdBQUcsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDO1FBRTVDLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDeEQsT0FBTyxFQUFFLEdBQUcsSUFBSSxFQUFFLEdBQUcsRUFBRSxNQUFNLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN0RSxDQUFDO0lBRUQsNkVBQTZFO0lBQzdFLGFBQWEsQ0FBQyxHQUErQjtRQUMzQyxJQUFJLENBQUMsR0FBRztZQUFFLE9BQU8sSUFBSSxDQUFDO1FBQ3RCLElBQUksR0FBRyxDQUFDLEdBQUc7WUFBRSxPQUFPLEdBQUcsQ0FBQyxHQUFHLENBQUM7UUFDNUIsSUFBSSxHQUFHLENBQUMsSUFBSSxJQUFJLE9BQU8sR0FBRyxLQUFLLFdBQVcsSUFBSSxPQUFPLEdBQUcsQ0FBQyxlQUFlLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDeEYsT0FBTyxHQUFHLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2QyxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsZ0JBQWdCLENBQUMsR0FBa0I7UUFDakMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDO1lBQUUsT0FBTztRQUM3QyxJQUFJLE9BQU8sR0FBRyxLQUFLLFdBQVcsSUFBSSxPQUFPLEdBQUcsQ0FBQyxlQUFlLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDNUUsR0FBRyxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUMzQixDQUFDO0lBQ0gsQ0FBQztJQUVPLFNBQVMsQ0FDZixNQUF5RTtRQUV6RSxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUNoQyxPQUFPLElBQUksT0FBTyxDQUFlLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO2dCQUNuRCxJQUFJLE9BQU8sR0FBRyxLQUFLLENBQUM7Z0JBQ3BCLE1BQU0sQ0FBQyxTQUFTLENBQUM7b0JBQ2YsSUFBSSxFQUFFLEtBQUssQ0FBQyxFQUFFO3dCQUNaLElBQUksT0FBTzs0QkFBRSxPQUFPO3dCQUNwQixPQUFPLEdBQUcsSUFBSSxDQUFDO3dCQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDakIsQ0FBQztvQkFDRCxLQUFLLEVBQUUsR0FBRyxDQUFDLEVBQUU7d0JBQ1gsSUFBSSxPQUFPOzRCQUFFLE9BQU87d0JBQ3BCLE9BQU8sR0FBRyxJQUFJLENBQUM7d0JBQ2YsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUNkLENBQUM7b0JBQ0QsUUFBUSxFQUFFLEdBQUcsRUFBRTt3QkFDYixJQUFJLE9BQU87NEJBQUUsT0FBTzt3QkFDcEIsT0FBTyxHQUFHLElBQUksQ0FBQzt3QkFDZixNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMscURBQXFELENBQUMsQ0FBQyxDQUFDO29CQUMzRSxDQUFDO2lCQUNGLENBQUMsQ0FBQztZQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUNELE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUE4QyxDQUFDLENBQUM7SUFDekUsQ0FBQztJQUVPLGNBQWMsQ0FBQyxLQUFjO1FBQ25DLE9BQU8sQ0FDTCxPQUFPLEtBQUssS0FBSyxRQUFRO1lBQ3pCLEtBQUssS0FBSyxJQUFJO1lBQ2QsT0FBUSxLQUFvQyxDQUFDLFNBQVMsS0FBSyxVQUFVLENBQ3RFLENBQUM7SUFDSixDQUFDO3dHQTNFVSxpQkFBaUI7NEdBQWpCLGlCQUFpQixjQURKLE1BQU07OzRGQUNuQixpQkFBaUI7a0JBRDdCLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB0eXBlIHsgRmlsZVJlZiwgU3Vic2NyaWJhYmxlLCBVcGxvYWRSZXN1bHQgfSBmcm9tICdAZHluYW1pYy1lbnRpdHkvY29yZSc7XHJcbmltcG9ydCB7IFVQTE9BRF9IQU5ETEVSIH0gZnJvbSAnLi4vdG9rZW5zL2luamVjdGlvbi10b2tlbnMnO1xyXG5cclxuLyoqXHJcbiAqIEZpbGVVcGxvYWRTZXJ2aWNlIOKAlCB0aGUgc2luZ2xlIHBsYWNlIGltYWdlLWZpZWxkIGFuZCBmaWxlLWZpZWxkIGFncmVlIG9uIGhvdyBhXHJcbiAqIHNlbGVjdGVkIGBGaWxlYCBiZWNvbWVzIGEgYEZpbGVSZWZgLlxyXG4gKlxyXG4gKiBXaXRoIGBVUExPQURfSEFORExFUmAgcmVnaXN0ZXJlZCB0aGUgZmlsZSBpcyBwZXJzaXN0ZWQgYW5kIHN0b3JlZCBhcyBgeyB1cmwgfWA7XHJcbiAqIHdpdGhvdXQgb25lIGl0IGlzIHN0b3JlZCBhcyBgeyBmaWxlIH1gIGZvciB0aGUgY29uc3VtZXIgdG8gdXBsb2FkIGF0IHN1Ym1pdCB0aW1lLlxyXG4gKi9cclxuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcclxuZXhwb3J0IGNsYXNzIEZpbGVVcGxvYWRTZXJ2aWNlIHtcclxuICBwcml2YXRlIHJlYWRvbmx5IGhhbmRsZXIgPSBpbmplY3QoVVBMT0FEX0hBTkRMRVIsIHsgb3B0aW9uYWw6IHRydWUgfSk7XHJcblxyXG4gIGdldCBoYXNIYW5kbGVyKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuICEhdGhpcy5oYW5kbGVyO1xyXG4gIH1cclxuXHJcbiAgLyoqIE1ldGFkYXRhIGNvbW1vbiB0byBib3RoIHBlcnNpc3RlZCBhbmQgdW5wZXJzaXN0ZWQgcmVmcy4gKi9cclxuICBwcml2YXRlIGRlc2NyaWJlKGZpbGU6IEZpbGUpOiBGaWxlUmVmIHtcclxuICAgIHJldHVybiB7IG5hbWU6IGZpbGUubmFtZSwgc2l6ZTogZmlsZS5zaXplLCBtaW1lVHlwZTogZmlsZS50eXBlIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUdXJuIGEgc2VsZWN0ZWQgRmlsZSBpbnRvIHRoZSB2YWx1ZSB0byBzdG9yZSBvbiB0aGUgY29udHJvbC5cclxuICAgKiBAdGhyb3dzIHdoZW4gYSByZWdpc3RlcmVkIGhhbmRsZXIgcmVqZWN0cyDigJQgY2FsbGVycyBzdXJmYWNlIGl0IGFzIGEgZmllbGQgZXJyb3IuXHJcbiAgICovXHJcbiAgYXN5bmMgdG9GaWxlUmVmKGZpbGU6IEZpbGUpOiBQcm9taXNlPEZpbGVSZWY+IHtcclxuICAgIGNvbnN0IG1ldGEgPSB0aGlzLmRlc2NyaWJlKGZpbGUpO1xyXG4gICAgaWYgKCF0aGlzLmhhbmRsZXIpIHJldHVybiB7IC4uLm1ldGEsIGZpbGUgfTtcclxuXHJcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLm5vcm1hbGl6ZSh0aGlzLmhhbmRsZXIoZmlsZSkpO1xyXG4gICAgcmV0dXJuIHsgLi4ubWV0YSwgdXJsOiByZXN1bHQudXJsLCBuYW1lOiByZXN1bHQubmFtZSA/PyBtZXRhLm5hbWUgfTtcclxuICB9XHJcblxyXG4gIC8qKiBPYmplY3QgVVJMIGZvciBwcmV2aWV3aW5nIGFuIHVucGVyc2lzdGVkIEZpbGUuIENhbGxlcnMgbXVzdCByZXZva2UgaXQuICovXHJcbiAgcHJldmlld1VybEZvcihyZWY6IEZpbGVSZWYgfCBudWxsIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgbnVsbCB7XHJcbiAgICBpZiAoIXJlZikgcmV0dXJuIG51bGw7XHJcbiAgICBpZiAocmVmLnVybCkgcmV0dXJuIHJlZi51cmw7XHJcbiAgICBpZiAocmVmLmZpbGUgJiYgdHlwZW9mIFVSTCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIFVSTC5jcmVhdGVPYmplY3RVUkwgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgcmV0dXJuIFVSTC5jcmVhdGVPYmplY3RVUkwocmVmLmZpbGUpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICByZXZva2VQcmV2aWV3VXJsKHVybDogc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xyXG4gICAgaWYgKCF1cmwgfHwgIXVybC5zdGFydHNXaXRoKCdibG9iOicpKSByZXR1cm47XHJcbiAgICBpZiAodHlwZW9mIFVSTCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIFVSTC5yZXZva2VPYmplY3RVUkwgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBub3JtYWxpemUoXHJcbiAgICByZXN1bHQ6IFVwbG9hZFJlc3VsdCB8IFByb21pc2U8VXBsb2FkUmVzdWx0PiB8IFN1YnNjcmliYWJsZTxVcGxvYWRSZXN1bHQ+LFxyXG4gICk6IFByb21pc2U8VXBsb2FkUmVzdWx0PiB7XHJcbiAgICBpZiAodGhpcy5pc1N1YnNjcmliYWJsZShyZXN1bHQpKSB7XHJcbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxVcGxvYWRSZXN1bHQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgICBsZXQgc2V0dGxlZCA9IGZhbHNlO1xyXG4gICAgICAgIHJlc3VsdC5zdWJzY3JpYmUoe1xyXG4gICAgICAgICAgbmV4dDogdmFsdWUgPT4ge1xyXG4gICAgICAgICAgICBpZiAoc2V0dGxlZCkgcmV0dXJuO1xyXG4gICAgICAgICAgICBzZXR0bGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgcmVzb2x2ZSh2YWx1ZSk7XHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgICAgZXJyb3I6IGVyciA9PiB7XHJcbiAgICAgICAgICAgIGlmIChzZXR0bGVkKSByZXR1cm47XHJcbiAgICAgICAgICAgIHNldHRsZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICByZWplY3QoZXJyKTtcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgICBjb21wbGV0ZTogKCkgPT4ge1xyXG4gICAgICAgICAgICBpZiAoc2V0dGxlZCkgcmV0dXJuO1xyXG4gICAgICAgICAgICBzZXR0bGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignVXBsb2FkIGhhbmRsZXIgY29tcGxldGVkIHdpdGhvdXQgZW1pdHRpbmcgYSByZXN1bHQuJykpO1xyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9KTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCBhcyBVcGxvYWRSZXN1bHQgfCBQcm9taXNlPFVwbG9hZFJlc3VsdD4pO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBpc1N1YnNjcmliYWJsZSh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIFN1YnNjcmliYWJsZTxVcGxvYWRSZXN1bHQ+IHtcclxuICAgIHJldHVybiAoXHJcbiAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiZcclxuICAgICAgdmFsdWUgIT09IG51bGwgJiZcclxuICAgICAgdHlwZW9mICh2YWx1ZSBhcyBTdWJzY3JpYmFibGU8VXBsb2FkUmVzdWx0Pikuc3Vic2NyaWJlID09PSAnZnVuY3Rpb24nXHJcbiAgICApO1xyXG4gIH1cclxufVxyXG4iXX0=