@dynamic-field-kit/angular 1.4.0 → 1.5.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 (51) hide show
  1. package/CHANGELOG.md +166 -0
  2. package/LICENSE +21 -0
  3. package/README.md +144 -5
  4. package/dist/components/DynamicFormDevTools.d.ts +16 -0
  5. package/dist/components/DynamicInput.d.ts +2 -1
  6. package/dist/components/FieldInput.d.ts +7 -1
  7. package/dist/components/MultiFieldInput.d.ts +13 -2
  8. package/dist/fesm2022/dynamic-field-kit-angular.mjs +578 -34
  9. package/dist/index.d.ts +1 -1
  10. package/dist/layout/index.d.ts +2 -2
  11. package/dist/lib/dynamic-field-kit.module.d.ts +4 -4
  12. package/dist/lib/dynamic-form.store.d.ts +23 -0
  13. package/dist/public-api.d.ts +10 -8
  14. package/package.json +40 -21
  15. package/dist/README.md +0 -235
  16. package/dist/esm2022/components/BaseInput.mjs +0 -59
  17. package/dist/esm2022/components/DynamicInput.mjs +0 -244
  18. package/dist/esm2022/components/FieldInput.mjs +0 -99
  19. package/dist/esm2022/components/MultiFieldInput.mjs +0 -338
  20. package/dist/esm2022/dynamic-field-kit-angular.mjs +0 -5
  21. package/dist/esm2022/fieldRegistryToken.mjs +0 -12
  22. package/dist/esm2022/layout/defaultLayouts.mjs +0 -114
  23. package/dist/esm2022/layout/index.mjs +0 -3
  24. package/dist/esm2022/layout/layoutRegistry.mjs +0 -14
  25. package/dist/esm2022/lib/dynamic-field-kit.module.mjs +0 -52
  26. package/dist/esm2022/public-api.mjs +0 -18
  27. package/dist/esm2022/types/layout.mjs +0 -2
  28. package/dist/fesm2022/dynamic-field-kit-angular.mjs.map +0 -1
  29. package/ng-package.json +0 -7
  30. package/src/components/BaseInput.ts +0 -57
  31. package/src/components/DynamicInput.ts +0 -280
  32. package/src/components/FieldInput.ts +0 -74
  33. package/src/components/MultiFieldInput.ts +0 -331
  34. package/src/fieldRegistryToken.ts +0 -15
  35. package/src/layout/defaultLayouts.ts +0 -70
  36. package/src/layout/index.ts +0 -2
  37. package/src/layout/layoutRegistry.ts +0 -25
  38. package/src/lib/dynamic-field-kit.module.ts +0 -29
  39. package/src/public-api.ts +0 -40
  40. package/src/types/layout.ts +0 -14
  41. package/test/DynamicInput.spec.ts +0 -230
  42. package/test/FieldInput.spec.ts +0 -146
  43. package/test/MultiFieldInput.spec.ts +0 -256
  44. package/test/helpers/renderers.ts +0 -89
  45. package/test/layout.spec.ts +0 -119
  46. package/test/publicApi.spec.ts +0 -64
  47. package/test/setup.ts +0 -12
  48. package/test/smoke.spec.ts +0 -27
  49. package/tsconfig.json +0 -13
  50. package/tsconfig.spec.json +0 -9
  51. package/vitest.config.ts +0 -30
package/dist/index.d.ts CHANGED
@@ -2,4 +2,4 @@
2
2
  * Generated bundle index. Do not edit.
3
3
  */
4
4
  /// <amd-module name="@dynamic-field-kit/angular" />
5
- export * from './public-api';
5
+ export * from './public-api.js';
@@ -1,2 +1,2 @@
1
- export * from './defaultLayouts';
2
- export { layoutRegistry, LayoutRegistry } from './layoutRegistry';
1
+ export * from './defaultLayouts.js';
2
+ export { layoutRegistry, LayoutRegistry } from './layoutRegistry.js';
@@ -1,9 +1,9 @@
1
1
  import * as i0 from "@angular/core";
2
2
  import * as i1 from "@angular/common";
3
- import * as i2 from "../components/DynamicInput";
4
- import * as i3 from "../components/FieldInput";
5
- import * as i4 from "../components/MultiFieldInput";
6
- import * as i5 from "../layout/defaultLayouts";
3
+ import * as i2 from "../components/DynamicInput.js";
4
+ import * as i3 from "../components/FieldInput.js";
5
+ import * as i4 from "../components/MultiFieldInput.js";
6
+ import * as i5 from "../layout/defaultLayouts.js";
7
7
  export declare class DynamicFieldKitModule {
8
8
  static ɵfac: i0.ɵɵFactoryDeclaration<DynamicFieldKitModule, never>;
9
9
  static ɵmod: i0.ɵɵNgModuleDeclaration<DynamicFieldKitModule, never, [typeof i1.CommonModule, typeof i2.DynamicInput, typeof i3.FieldInput, typeof i4.MultiFieldInput, typeof i5.ColumnLayout, typeof i5.RowLayout, typeof i5.GridLayout], [typeof i2.DynamicInput, typeof i3.FieldInput, typeof i4.MultiFieldInput, typeof i5.ColumnLayout, typeof i5.RowLayout, typeof i5.GridLayout]>;
@@ -0,0 +1,23 @@
1
+ import { FieldDescription, Properties } from '@dynamic-field-kit/core';
2
+ export interface DynamicFormOptions {
3
+ fields: FieldDescription[];
4
+ initialValues?: Properties;
5
+ validateOnBlur?: boolean;
6
+ validateOnChange?: boolean;
7
+ }
8
+ export declare function createDynamicFormStore(options: DynamicFormOptions): {
9
+ data: import("@angular/core").WritableSignal<Properties>;
10
+ errors: import("@angular/core").WritableSignal<Record<string, string[]>>;
11
+ isValid: import("@angular/core").Signal<boolean>;
12
+ isDirty: import("@angular/core").WritableSignal<boolean>;
13
+ touched: import("@angular/core").WritableSignal<Record<string, boolean>>;
14
+ isSubmitting: import("@angular/core").WritableSignal<boolean>;
15
+ isSubmitted: import("@angular/core").WritableSignal<boolean>;
16
+ setFieldValue: (name: string, value: unknown) => void;
17
+ setFieldTouched: (name: string, isTouched?: boolean) => void;
18
+ handleChange: (newData: Properties) => void;
19
+ handleBlur: (fieldName: string) => void;
20
+ reset: (newValues?: Properties) => void;
21
+ validate: () => boolean;
22
+ handleSubmit: (onValid: (data: Properties) => void | Promise<void>, onInvalid?: (errors: Record<string, string[]>) => void) => (e?: Event) => Promise<void>;
23
+ };
@@ -1,12 +1,14 @@
1
- export * from './components/BaseInput';
2
- export * from './components/DynamicInput';
3
- export * from './components/FieldInput';
4
- export * from './components/MultiFieldInput';
5
- export * from './layout';
6
- export * from './types/layout';
7
- export * from './lib/dynamic-field-kit.module';
1
+ export * from './components/BaseInput.js';
2
+ export * from './components/DynamicInput.js';
3
+ export * from './components/FieldInput.js';
4
+ export * from './components/MultiFieldInput.js';
5
+ export * from './components/DynamicFormDevTools.js';
6
+ export * from './lib/dynamic-form.store.js';
7
+ export * from './layout/index.js';
8
+ export * from './types/layout.js';
9
+ export * from './lib/dynamic-field-kit.module.js';
8
10
  export type { FieldDescription, FieldRendererProps, FieldTypeKey, } from '@dynamic-field-kit/core';
9
11
  export { fieldRegistry, FieldRegistry } from '@dynamic-field-kit/core';
10
12
  export { validateField, validateFieldAsync, validateFields, validateFieldsAsync, resolveDisabled, resolveReadOnly, resolveOptions, validators, } from '@dynamic-field-kit/core';
11
13
  export type { ValidationResult } from '@dynamic-field-kit/core';
12
- export { FIELD_REGISTRY } from './fieldRegistryToken';
14
+ export { FIELD_REGISTRY } from './fieldRegistryToken.js';
package/package.json CHANGED
@@ -1,36 +1,42 @@
1
1
  {
2
2
  "name": "@dynamic-field-kit/angular",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Angular renderer for dynamic-field-kit",
5
5
  "license": "MIT",
6
6
  "private": false,
7
7
  "type": "module",
8
- "sideEffects": false,
8
+ "sideEffects": [
9
+ "**/fesm2022/*.mjs"
10
+ ],
9
11
  "main": "dist/fesm2022/dynamic-field-kit-angular.mjs",
10
12
  "module": "dist/fesm2022/dynamic-field-kit-angular.mjs",
11
13
  "types": "dist/index.d.ts",
14
+ "files": [
15
+ "dist",
16
+ "!dist/README.md",
17
+ "!dist/LICENSE",
18
+ "CHANGELOG.md"
19
+ ],
12
20
  "peerDependencies": {
13
- "@angular/common": ">=13 <22",
14
- "@angular/core": ">=13 <22",
21
+ "@angular/common": ">=14 <22",
22
+ "@angular/core": ">=14 <22",
15
23
  "@dynamic-field-kit/core": "^1.3.0"
16
24
  },
17
25
  "publishConfig": {
18
- "access": "public"
26
+ "access": "public",
27
+ "provenance": true
19
28
  },
20
29
  "scripts": {
21
30
  "build": "ng-packagr -p ng-package.json",
31
+ "postbuild": "node ../../scripts/strip-sourcemaps.js dist && node ../../scripts/add-dts-extensions.js dist",
22
32
  "clean": "rimraf dist coverage",
23
33
  "prepublishOnly": "npm run build",
24
34
  "test": "vitest run",
25
- "publish:dist": "npm publish ./dist --access public",
26
- "release:patch": "npm version patch && npm run build && npm run publish:dist",
27
- "release:minor": "npm version minor && npm run build && npm run publish:dist",
28
- "release:major": "npm version major && npm run build && npm run publish:dist",
29
- "lint": "echo \"skip lint for Angular\""
35
+ "lint": "eslint ."
30
36
  },
31
37
  "devDependencies": {
32
- "@analogjs/vite-plugin-angular": "^1.16.1",
33
- "@analogjs/vitest-angular": "^1.16.1",
38
+ "@analogjs/vite-plugin-angular": "^2.7.1",
39
+ "@analogjs/vitest-angular": "^2.7.1",
34
40
  "@angular-devkit/build-angular": "^19.2.27",
35
41
  "@angular/cdk": "^19.0.0",
36
42
  "@angular/common": "^19.0.0",
@@ -40,24 +46,37 @@
40
46
  "@angular/forms": "^19.0.0",
41
47
  "@angular/platform-browser": "^19.0.0",
42
48
  "@angular/platform-browser-dynamic": "^19.0.0",
43
- "@dynamic-field-kit/core": "^1.3.0",
44
- "@vitest/coverage-istanbul": "^1.6.0",
45
- "@vitest/coverage-v8": "^1.6.0",
46
- "jsdom": "^24.0.0",
47
- "ng-packagr": "^17.3.0",
49
+ "@dynamic-field-kit/core": "^1.5.0",
50
+ "@vitest/coverage-istanbul": "^4.1.11",
51
+ "jsdom": "^29.1.1",
52
+ "ng-packagr": "^19.2.2",
48
53
  "rimraf": "^6.1.3",
49
54
  "rxjs": "^7.8.0",
50
- "typescript": "~5.6.0",
51
- "vitest": "^1.6.0",
55
+ "typescript": "~5.8.3",
56
+ "vitest": "^4.1.11",
52
57
  "zone.js": "^0.15.0"
53
58
  },
54
59
  "repository": {
55
60
  "type": "git",
56
- "url": "git+https://github.com/vannt-dev/dynamic-field-kit.git"
61
+ "url": "git+https://github.com/vannt-dev/dynamic-field-kit.git",
62
+ "directory": "packages/angular"
57
63
  },
58
64
  "keywords": [
59
65
  "dynamic-field",
60
66
  "dynamic-field-kit",
61
67
  "dynamic-field-kit/angular"
62
- ]
68
+ ],
69
+ "homepage": "https://github.com/vannt-dev/dynamic-field-kit/tree/develop/packages/angular#readme",
70
+ "bugs": {
71
+ "url": "https://github.com/vannt-dev/dynamic-field-kit/issues"
72
+ },
73
+ "exports": {
74
+ ".": {
75
+ "types": "./dist/index.d.ts",
76
+ "default": "./dist/fesm2022/dynamic-field-kit-angular.mjs"
77
+ },
78
+ "./package.json": {
79
+ "default": "./package.json"
80
+ }
81
+ }
63
82
  }
package/dist/README.md DELETED
@@ -1,235 +0,0 @@
1
- # @dynamic-field-kit/angular
2
-
3
- Angular adapter for `@dynamic-field-kit/core`.
4
-
5
- This package provides Angular components and a convenience module that render field schemas defined with `@dynamic-field-kit/core`.
6
-
7
- Demo app: https://github.com/vannt-dev/dynamic-field-kit-demo
8
-
9
- ## Install
10
-
11
- ```bash
12
- npm install @dynamic-field-kit/core @dynamic-field-kit/angular
13
- ```
14
-
15
- Note: `@dynamic-field-kit/core`, `@angular/core`, and `@angular/common` are **peer dependencies** — this adapter does not bundle or auto-install them, so add them to your app explicitly (as shown above). Keep a single `@dynamic-field-kit/core` version across all adapters so they share one registry.
16
-
17
- If you need to pin versions explicitly:
18
-
19
- ```bash
20
- npm install @dynamic-field-kit/core@^1.0.12 @dynamic-field-kit/angular@^1.2.3
21
- ```
22
-
23
- ## What it exports
24
-
25
- - `DynamicInput`
26
- - `FieldInput`
27
- - `MultiFieldInput`
28
- - `DynamicFieldKitModule`
29
- - `fieldRegistry`
30
- - `FieldRegistry` (class, for scoped registries)
31
- - `FIELD_REGISTRY` (injection token)
32
- - `validateField` / `validateFields` / `resolveDisabled` / `resolveReadOnly` / `ValidationResult`
33
-
34
- ## Basic setup (Angular 19+)
35
-
36
- 1. Import the component and register fields before bootstrap.
37
-
38
- ```ts
39
- import 'zone.js';
40
- import { bootstrapApplication } from '@angular/platform-browser';
41
- import { fieldRegistry } from '@dynamic-field-kit/angular';
42
- import { AppComponent } from './app/app.component';
43
- import { TextFieldComponent } from './app/components/text-field.component';
44
- import { NumberFieldComponent } from './app/components/number-field.component';
45
-
46
- fieldRegistry.register('text', TextFieldComponent as any);
47
- fieldRegistry.register('number', NumberFieldComponent as any);
48
-
49
- bootstrapApplication(AppComponent, {
50
- providers: [],
51
- }).catch((err) => console.error(err));
52
- ```
53
-
54
- 2. Use the component in a standalone component.
55
-
56
- ```ts
57
- import { Component } from '@angular/core';
58
- import { CommonModule } from '@angular/common';
59
- import { FieldDescription } from '@dynamic-field-kit/core';
60
- import { MultiFieldInput } from '@dynamic-field-kit/angular';
61
-
62
- @Component({
63
- selector: 'app-root',
64
- standalone: true,
65
- imports: [CommonModule, MultiFieldInput],
66
- templateUrl: './app.component.html',
67
- })
68
- export class AppComponent {
69
- fields: FieldDescription[] = [
70
- { name: 'name', type: 'text', label: 'Name' },
71
- { name: 'age', type: 'number', label: 'Age' },
72
- ];
73
-
74
- data: any = {};
75
-
76
- onChange(data: any) {
77
- this.data = data;
78
- }
79
- }
80
- ```
81
-
82
- 3. Render your schema in a template.
83
-
84
- ```html
85
- <dfk-multi-field-input
86
- [fieldDescriptions]="fields"
87
- [properties]="data"
88
- (onChange)="onChange($event)"
89
- ></dfk-multi-field-input>
90
- ```
91
-
92
- ## Layouts
93
-
94
- `MultiFieldInput` supports `column`, `row`, `grid`, and `responsive` (mobile/desktop with a custom breakpoint), matching the React and Vue adapters:
95
-
96
- ```html
97
- <dfk-multi-field-input
98
- [fieldDescriptions]="fields"
99
- [layout]="{ type: 'grid', columns: 3, gap: 16 }"
100
- ></dfk-multi-field-input>
101
-
102
- <dfk-multi-field-input
103
- [fieldDescriptions]="fields"
104
- [layout]="{
105
- type: 'responsive',
106
- mobile: 'column',
107
- desktop: { type: 'grid', columns: 2, gap: 12 }
108
- }"
109
- ></dfk-multi-field-input>
110
- ```
111
-
112
- ## Derived fields with `computeValue`
113
-
114
- Give a field a `computeValue` to derive its value from the rest of the form data whenever any field changes:
115
-
116
- ```ts
117
- fields: FieldDescription[] = [
118
- { name: 'firstName', type: 'text' },
119
- { name: 'lastName', type: 'text' },
120
- {
121
- name: 'fullName',
122
- type: 'text',
123
- computeValue: (data) => `${data.firstName ?? ''} ${data.lastName ?? ''}`.trim(),
124
- },
125
- ];
126
- ```
127
-
128
- ## Validation & conditions
129
-
130
- Declare a `validate` hook and dynamic `disabledCondition`/`readOnlyCondition`;
131
- your renderer component receives `error`, `disabled`, and `readOnly` inputs, and
132
- `dfk-multi-field-input` emits `(validityChange)`:
133
-
134
- ```html
135
- <dfk-multi-field-input
136
- [fieldDescriptions]="fields"
137
- [properties]="data"
138
- (onChange)="onChange($event)"
139
- (validityChange)="canSubmit = $event.valid"
140
- ></dfk-multi-field-input>
141
- ```
142
-
143
- For submit-time whole-form validation, call `validateFields(fields, data)`.
144
-
145
- ## Repeatable field groups
146
-
147
- A field with `fields` renders as a repeatable group: `data[name]` becomes an array of items, each shaped by the nested `fields`, with "Add"/"Remove" controls rendered automatically.
148
-
149
- ```ts
150
- fields: FieldDescription[] = [
151
- {
152
- name: 'contacts',
153
- type: 'group',
154
- label: 'Contacts',
155
- fields: [
156
- { name: 'email', type: 'text', label: 'Email' },
157
- { name: 'phone', type: 'text', label: 'Phone' },
158
- ],
159
- defaultItem: { email: '', phone: '' },
160
- keyField: 'id', // optional: stable trackBy key instead of the array index
161
- minItems: 1,
162
- maxItems: 5,
163
- },
164
- ];
165
- ```
166
-
167
- ```html
168
- <dfk-multi-field-input [fieldDescriptions]="fields"></dfk-multi-field-input>
169
- ```
170
-
171
- ## Scoped registries
172
-
173
- `fieldRegistry` is a process-wide singleton. To give a component or route its own renderers, provide the `FIELD_REGISTRY` token with an isolated `FieldRegistry`. Components without an override keep using the global singleton.
174
-
175
- ```ts
176
- import { FieldRegistry, FIELD_REGISTRY } from '@dynamic-field-kit/angular';
177
-
178
- const registry = new FieldRegistry();
179
- registry.register('text', TextFieldComponent as any);
180
-
181
- @Component({
182
- selector: 'app-scoped-form',
183
- standalone: true,
184
- imports: [MultiFieldInput],
185
- providers: [{ provide: FIELD_REGISTRY, useValue: registry }],
186
- template: `<dfk-multi-field-input [fieldDescriptions]="fields" />`,
187
- })
188
- export class ScopedFormComponent {}
189
- ```
190
-
191
- ## Passing renderer-specific props
192
-
193
- The generic adapter forwards only the shared `FieldRendererProps`. For inputs specific to one renderer (e.g. `acceptFile`, `maxLength`), pass them per field via `FieldDescription.props`; they are set on the renderer instance verbatim.
194
-
195
- ```ts
196
- { name: 'avatar', type: 'file', props: { acceptFile: 'image/*' } }
197
- ```
198
-
199
- ## Legacy setup (Angular 14 and earlier with NgModule)
200
-
201
- ```ts
202
- import { BrowserModule } from '@angular/platform-browser';
203
- import { NgModule } from '@angular/core';
204
- import { DynamicFieldKitModule } from '@dynamic-field-kit/angular';
205
-
206
- @NgModule({
207
- imports: [BrowserModule, DynamicFieldKitModule],
208
- })
209
- export class AppModule {}
210
- ```
211
-
212
- ## Type augmentation
213
-
214
- ```ts
215
- import '@dynamic-field-kit/core';
216
-
217
- declare module '@dynamic-field-kit/core' {
218
- interface FieldTypeMap {
219
- text: string;
220
- number: number;
221
- }
222
- }
223
- ```
224
-
225
- ## Notes
226
-
227
- - Register Angular component classes in `fieldRegistry`.
228
- - Do not register React or Vue renderers in the Angular adapter.
229
- - `MultiFieldInput` supports `column`, `row`, `grid`, and `responsive` layouts, and derives fields using `computeValue`.
230
- - Fields with `fields` render as repeatable groups instead of going through `fieldRegistry`.
231
- - The shared schema and field types still come from `@dynamic-field-kit/core`.
232
-
233
- ## License
234
-
235
- MIT
@@ -1,59 +0,0 @@
1
- import { Component, EventEmitter, Input, Output, } from '@angular/core';
2
- import * as i0 from "@angular/core";
3
- export class BaseInputComponent {
4
- cdr;
5
- value;
6
- label;
7
- placeholder;
8
- required;
9
- disabled;
10
- readOnly;
11
- error;
12
- options;
13
- className;
14
- description;
15
- valueChange = new EventEmitter();
16
- constructor(cdr) {
17
- this.cdr = cdr;
18
- }
19
- ngOnChanges(_changes) {
20
- this.detectChanges();
21
- }
22
- detectChanges() {
23
- this.cdr.markForCheck();
24
- }
25
- hasChanges(changes, prop) {
26
- return changes[prop] !== undefined;
27
- }
28
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: BaseInputComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
29
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.20", type: BaseInputComponent, isStandalone: true, selector: "ng-component", inputs: { value: "value", label: "label", placeholder: "placeholder", required: "required", disabled: "disabled", readOnly: "readOnly", error: "error", options: "options", className: "className", description: "description" }, outputs: { valueChange: "valueChange" }, usesOnChanges: true, ngImport: i0, template: '', isInline: true });
30
- }
31
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: BaseInputComponent, decorators: [{
32
- type: Component,
33
- args: [{
34
- template: '',
35
- }]
36
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { value: [{
37
- type: Input
38
- }], label: [{
39
- type: Input
40
- }], placeholder: [{
41
- type: Input
42
- }], required: [{
43
- type: Input
44
- }], disabled: [{
45
- type: Input
46
- }], readOnly: [{
47
- type: Input
48
- }], error: [{
49
- type: Input
50
- }], options: [{
51
- type: Input
52
- }], className: [{
53
- type: Input
54
- }], description: [{
55
- type: Input
56
- }], valueChange: [{
57
- type: Output
58
- }] } });
59
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQmFzZUlucHV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvQmFzZUlucHV0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFFTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLEtBQUssRUFFTCxNQUFNLEdBRVAsTUFBTSxlQUFlLENBQUM7O0FBcUJ2QixNQUFNLE9BQWdCLGtCQUFrQjtJQWNoQjtJQWJiLEtBQUssQ0FBVztJQUNoQixLQUFLLENBQVU7SUFDZixXQUFXLENBQVU7SUFDckIsUUFBUSxDQUFXO0lBQ25CLFFBQVEsQ0FBVztJQUNuQixRQUFRLENBQVc7SUFDbkIsS0FBSyxDQUFxQjtJQUMxQixPQUFPLENBQWE7SUFDcEIsU0FBUyxDQUFVO0lBQ25CLFdBQVcsQ0FBVTtJQUVwQixXQUFXLEdBQUcsSUFBSSxZQUFZLEVBQVcsQ0FBQztJQUVwRCxZQUFzQixHQUFzQjtRQUF0QixRQUFHLEdBQUgsR0FBRyxDQUFtQjtJQUFHLENBQUM7SUFFaEQsV0FBVyxDQUFDLFFBQXVCO1FBQ2pDLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUN2QixDQUFDO0lBRVMsYUFBYTtRQUNyQixJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFUyxVQUFVLENBQUMsT0FBc0IsRUFBRSxJQUFZO1FBQ3ZELE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLFNBQVMsQ0FBQztJQUNyQyxDQUFDO3dHQTFCbUIsa0JBQWtCOzRGQUFsQixrQkFBa0Isd1dBRjVCLEVBQUU7OzRGQUVRLGtCQUFrQjtrQkFIdkMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsRUFBRTtpQkFDYjtzRkFFVSxLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csS0FBSztzQkFBYixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csS0FBSztzQkFBYixLQUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSztnQkFDRyxTQUFTO3NCQUFqQixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBRUksV0FBVztzQkFBcEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT3V0cHV0LFxuICBTaW1wbGVDaGFuZ2VzLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuLy8gTWlycm9ycyB0aGUgZnJhbWV3b3JrLWFnbm9zdGljIEZpZWxkUmVuZGVyZXJQcm9wcy4gRG9tYWluLXNwZWNpZmljIGlucHV0c1xuLy8gKGFjY2VwdEZpbGUsIG1heExlbmd0aCwgLi4uKSBpbnRlbnRpb25hbGx5IGxpdmUgb24gdGhlIGluZGl2aWR1YWwgcmVuZGVyZXIsXG4vLyBub3QgaGVyZSAtIHBhc3MgdGhlbSBwZXIgZmllbGQgdmlhIEZpZWxkRGVzY3JpcHRpb24ucHJvcHMgaW5zdGVhZC5cbmV4cG9ydCBpbnRlcmZhY2UgRmllbGRJbnB1dFByb3BzIHtcbiAgdmFsdWU/OiB1bmtub3duO1xuICBsYWJlbD86IHN0cmluZztcbiAgcGxhY2Vob2xkZXI/OiBzdHJpbmc7XG4gIHJlcXVpcmVkPzogYm9vbGVhbjtcbiAgZGlzYWJsZWQ/OiBib29sZWFuO1xuICByZWFkT25seT86IGJvb2xlYW47XG4gIGVycm9yPzogc3RyaW5nIHwgc3RyaW5nW107XG4gIG9wdGlvbnM/OiB1bmtub3duW107XG4gIGNsYXNzTmFtZT86IHN0cmluZztcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG59XG5cbkBDb21wb25lbnQoe1xuICB0ZW1wbGF0ZTogJycsXG59KVxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VJbnB1dENvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcyB7XG4gIEBJbnB1dCgpIHZhbHVlPzogdW5rbm93bjtcbiAgQElucHV0KCkgbGFiZWw/OiBzdHJpbmc7XG4gIEBJbnB1dCgpIHBsYWNlaG9sZGVyPzogc3RyaW5nO1xuICBASW5wdXQoKSByZXF1aXJlZD86IGJvb2xlYW47XG4gIEBJbnB1dCgpIGRpc2FibGVkPzogYm9vbGVhbjtcbiAgQElucHV0KCkgcmVhZE9ubHk/OiBib29sZWFuO1xuICBASW5wdXQoKSBlcnJvcj86IHN0cmluZyB8IHN0cmluZ1tdO1xuICBASW5wdXQoKSBvcHRpb25zPzogdW5rbm93bltdO1xuICBASW5wdXQoKSBjbGFzc05hbWU/OiBzdHJpbmc7XG4gIEBJbnB1dCgpIGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuXG4gIEBPdXRwdXQoKSB2YWx1ZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8dW5rbm93bj4oKTtcblxuICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZikge31cblxuICBuZ09uQ2hhbmdlcyhfY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIHRoaXMuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGRldGVjdENoYW5nZXMoKTogdm9pZCB7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgaGFzQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzLCBwcm9wOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gY2hhbmdlc1twcm9wXSAhPT0gdW5kZWZpbmVkO1xuICB9XG59XG4iXX0=