@dynamic-field-kit/angular 1.3.3 → 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 +185 -0
  2. package/LICENSE +21 -0
  3. package/README.md +193 -7
  4. package/dist/components/BaseInput.d.ts +5 -11
  5. package/dist/components/DynamicFormDevTools.d.ts +16 -0
  6. package/dist/components/DynamicInput.d.ts +8 -3
  7. package/dist/components/FieldInput.d.ts +12 -2
  8. package/dist/components/MultiFieldInput.d.ts +22 -2
  9. package/dist/fesm2022/dynamic-field-kit-angular.mjs +778 -87
  10. package/dist/fieldRegistryToken.d.ts +3 -0
  11. package/dist/index.d.ts +1 -1
  12. package/dist/layout/index.d.ts +2 -2
  13. package/dist/lib/dynamic-field-kit.module.d.ts +4 -4
  14. package/dist/lib/dynamic-form.store.d.ts +23 -0
  15. package/dist/public-api.d.ts +13 -8
  16. package/dist/types/layout.d.ts +4 -25
  17. package/package.json +46 -29
  18. package/angular.json +0 -27
  19. package/dist/README.md +0 -188
  20. package/dist/esm2022/components/BaseInput.mjs +0 -68
  21. package/dist/esm2022/components/DynamicInput.mjs +0 -191
  22. package/dist/esm2022/components/FieldInput.mjs +0 -80
  23. package/dist/esm2022/components/MultiFieldInput.mjs +0 -264
  24. package/dist/esm2022/dynamic-field-kit-angular.mjs +0 -5
  25. package/dist/esm2022/layout/defaultLayouts.mjs +0 -114
  26. package/dist/esm2022/layout/index.mjs +0 -3
  27. package/dist/esm2022/layout/layoutRegistry.mjs +0 -14
  28. package/dist/esm2022/lib/dynamic-field-kit.module.mjs +0 -52
  29. package/dist/esm2022/public-api.mjs +0 -14
  30. package/dist/esm2022/types/layout.mjs +0 -2
  31. package/dist/fesm2022/dynamic-field-kit-angular.mjs.map +0 -1
  32. package/karma.conf.js +0 -37
  33. package/ng-package.json +0 -7
  34. package/src/components/BaseInput.ts +0 -60
  35. package/src/components/DynamicInput.ts +0 -224
  36. package/src/components/FieldInput.ts +0 -67
  37. package/src/components/MultiFieldInput.ts +0 -238
  38. package/src/layout/defaultLayouts.ts +0 -70
  39. package/src/layout/index.ts +0 -2
  40. package/src/layout/layoutRegistry.ts +0 -25
  41. package/src/lib/dynamic-field-kit.module.ts +0 -29
  42. package/src/public-api.ts +0 -24
  43. package/src/types/layout.ts +0 -36
  44. package/test/DynamicInput.spec.ts +0 -30
  45. package/test/FieldInput.spec.ts +0 -44
  46. package/test/angular.spec.ts +0 -102
  47. package/test/integration.spec.ts +0 -57
  48. package/test/layouts.spec.ts +0 -26
  49. package/test.ts +0 -12
  50. package/tsconfig.json +0 -13
  51. package/tsconfig.spec.json +0 -21
@@ -0,0 +1,3 @@
1
+ import { InjectionToken } from '@angular/core';
2
+ import { FieldRegistry } from '@dynamic-field-kit/core';
3
+ export declare const FIELD_REGISTRY: InjectionToken<FieldRegistry>;
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,9 +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
- export { fieldRegistry } from '@dynamic-field-kit/core';
11
+ export { fieldRegistry, FieldRegistry } from '@dynamic-field-kit/core';
12
+ export { validateField, validateFieldAsync, validateFields, validateFieldsAsync, resolveDisabled, resolveReadOnly, resolveOptions, validators, } from '@dynamic-field-kit/core';
13
+ export type { ValidationResult } from '@dynamic-field-kit/core';
14
+ export { FIELD_REGISTRY } from './fieldRegistryToken.js';
@@ -1,25 +1,4 @@
1
- export interface GridLayoutConfig {
2
- type: 'grid';
3
- columns?: number;
4
- gap?: number;
5
- width?: string;
6
- }
7
- export interface RowLayoutConfig {
8
- type: 'row';
9
- gap?: number;
10
- width?: string;
11
- flex?: boolean;
12
- }
13
- export interface ColumnLayoutConfig {
14
- type: 'column';
15
- gap?: number;
16
- width?: string;
17
- }
18
- export type BaseLayoutConfig = 'column' | 'row' | 'grid' | GridLayoutConfig | RowLayoutConfig | ColumnLayoutConfig;
19
- export interface ResponsiveLayoutConfig {
20
- type: 'responsive';
21
- mobile: BaseLayoutConfig;
22
- desktop: BaseLayoutConfig;
23
- breakpoint?: number;
24
- }
25
- export type LayoutConfig = BaseLayoutConfig | ResponsiveLayoutConfig;
1
+ import type { BaseLayout, ResponsiveLayout } from '@dynamic-field-kit/core';
2
+ export type { ColumnLayoutConfig, RowLayoutConfig, GridLayoutConfig, LayoutConfig, } from '@dynamic-field-kit/core';
3
+ export type BaseLayoutConfig = BaseLayout;
4
+ export type ResponsiveLayoutConfig = ResponsiveLayout;
package/package.json CHANGED
@@ -1,37 +1,43 @@
1
1
  {
2
2
  "name": "@dynamic-field-kit/angular",
3
- "version": "1.3.3",
3
+ "version": "1.5.0",
4
4
  "description": "Angular renderer for dynamic-field-kit",
5
5
  "license": "MIT",
6
6
  "private": false,
7
- "sideEffects": false,
7
+ "type": "module",
8
+ "sideEffects": [
9
+ "**/fesm2022/*.mjs"
10
+ ],
8
11
  "main": "dist/fesm2022/dynamic-field-kit-angular.mjs",
9
12
  "module": "dist/fesm2022/dynamic-field-kit-angular.mjs",
10
13
  "types": "dist/index.d.ts",
14
+ "files": [
15
+ "dist",
16
+ "!dist/README.md",
17
+ "!dist/LICENSE",
18
+ "CHANGELOG.md"
19
+ ],
11
20
  "peerDependencies": {
12
- "@angular/common": ">=13 <22",
13
- "@angular/core": ">=13 <22",
14
- "@dynamic-field-kit/core": "^1.2.0"
15
- },
16
- "dependencies": {
17
- "@dynamic-field-kit/core": "^1.2.0"
21
+ "@angular/common": ">=14 <22",
22
+ "@angular/core": ">=14 <22",
23
+ "@dynamic-field-kit/core": "^1.3.0"
18
24
  },
19
25
  "publishConfig": {
20
- "access": "public"
26
+ "access": "public",
27
+ "provenance": true
21
28
  },
22
29
  "scripts": {
23
30
  "build": "ng-packagr -p ng-package.json",
24
- "clean": "rimraf dist dist-spec coverage",
25
- "prepublishOnly": "npm run clean && npm run build",
26
- "test": "karma start karma.conf.js --single-run",
27
- "test:coverage": "karma start karma.conf.js --single-run --coverage",
28
- "publish:dist": "npm publish ./dist --access public",
29
- "release:patch": "npm version patch && npm run build && npm run publish:dist",
30
- "release:minor": "npm version minor && npm run build && npm run publish:dist",
31
- "release:major": "npm version major && npm run build && npm run publish:dist",
32
- "lint": "echo \"skip lint for Angular\""
31
+ "postbuild": "node ../../scripts/strip-sourcemaps.js dist && node ../../scripts/add-dts-extensions.js dist",
32
+ "clean": "rimraf dist coverage",
33
+ "prepublishOnly": "npm run build",
34
+ "test": "vitest run",
35
+ "lint": "eslint ."
33
36
  },
34
37
  "devDependencies": {
38
+ "@analogjs/vite-plugin-angular": "^2.7.1",
39
+ "@analogjs/vitest-angular": "^2.7.1",
40
+ "@angular-devkit/build-angular": "^19.2.27",
35
41
  "@angular/cdk": "^19.0.0",
36
42
  "@angular/common": "^19.0.0",
37
43
  "@angular/compiler": "^19.0.0",
@@ -40,26 +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
- "@types/jasmine": "^5.1.0",
44
- "jasmine": "^5.1.0",
45
- "karma": "^6.4.4",
46
- "karma-chrome-launcher": "^3.2.0",
47
- "karma-coverage": "^2.2.1",
48
- "karma-jasmine": "^5.1.0",
49
- "karma-typescript": "^5.5.4",
50
- "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",
51
53
  "rimraf": "^6.1.3",
52
54
  "rxjs": "^7.8.0",
53
- "typescript": "~5.6.0",
55
+ "typescript": "~5.8.3",
56
+ "vitest": "^4.1.11",
54
57
  "zone.js": "^0.15.0"
55
58
  },
56
59
  "repository": {
57
60
  "type": "git",
58
- "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"
59
63
  },
60
64
  "keywords": [
61
65
  "dynamic-field",
62
66
  "dynamic-field-kit",
63
67
  "dynamic-field-kit/angular"
64
- ]
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
+ }
65
82
  }
package/angular.json DELETED
@@ -1,27 +0,0 @@
1
- {
2
- "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3
- "version": 1,
4
- "newProjectRoot": "projects",
5
- "projects": {
6
- "dynamic-field-kit-angular": {
7
- "projectType": "library",
8
- "root": "",
9
- "sourceRoot": "src",
10
- "prefix": "dfk",
11
- "architect": {
12
- "test": {
13
- "builder": "@angular-devkit/build-angular:karma",
14
- "options": {
15
- "main": "test.ts",
16
- "polyfills": ["zone.js"],
17
- "tsConfig": "tsconfig.spec.json",
18
- "karmaConfig": "karma.conf.js",
19
- "assets": [],
20
- "styles": [],
21
- "scripts": []
22
- }
23
- }
24
- }
25
- }
26
- }
27
- }
package/dist/README.md DELETED
@@ -1,188 +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: Core is shared runtime. Install core separately and ensure a single version is used across adapters to avoid duplicate registries.
16
-
17
- - Install with core: `npm install @dynamic-field-kit/core @dynamic-field-kit/angular`
18
-
19
- If you need to pin versions explicitly:
20
-
21
- ```bash
22
- npm install @dynamic-field-kit/core@^1.0.12 @dynamic-field-kit/angular@^1.2.3
23
- ```
24
-
25
- ## What it exports
26
-
27
- - `DynamicInput`
28
- - `FieldInput`
29
- - `MultiFieldInput`
30
- - `DynamicFieldKitModule`
31
- - `fieldRegistry`
32
-
33
- ## Basic setup (Angular 19+)
34
-
35
- 1. Import the component and register fields before bootstrap.
36
-
37
- ```ts
38
- import 'zone.js';
39
- import { bootstrapApplication } from '@angular/platform-browser';
40
- import { fieldRegistry } from '@dynamic-field-kit/angular';
41
- import { AppComponent } from './app/app.component';
42
- import { TextFieldComponent } from './app/components/text-field.component';
43
- import { NumberFieldComponent } from './app/components/number-field.component';
44
-
45
- fieldRegistry.register('text', TextFieldComponent as any);
46
- fieldRegistry.register('number', NumberFieldComponent as any);
47
-
48
- bootstrapApplication(AppComponent, {
49
- providers: [],
50
- }).catch((err) => console.error(err));
51
- ```
52
-
53
- 2. Use the component in a standalone component.
54
-
55
- ```ts
56
- import { Component } from '@angular/core';
57
- import { CommonModule } from '@angular/common';
58
- import { FieldDescription } from '@dynamic-field-kit/core';
59
- import { MultiFieldInput } from '@dynamic-field-kit/angular';
60
-
61
- @Component({
62
- selector: 'app-root',
63
- standalone: true,
64
- imports: [CommonModule, MultiFieldInput],
65
- templateUrl: './app.component.html',
66
- })
67
- export class AppComponent {
68
- fields: FieldDescription[] = [
69
- { name: 'name', type: 'text', label: 'Name' },
70
- { name: 'age', type: 'number', label: 'Age' },
71
- ];
72
-
73
- data: any = {};
74
-
75
- onChange(data: any) {
76
- this.data = data;
77
- }
78
- }
79
- ```
80
-
81
- 3. Render your schema in a template.
82
-
83
- ```html
84
- <dfk-multi-field-input
85
- [fieldDescriptions]="fields"
86
- [properties]="data"
87
- (onChange)="onChange($event)"
88
- ></dfk-multi-field-input>
89
- ```
90
-
91
- ## Layouts
92
-
93
- `MultiFieldInput` supports `column`, `row`, `grid`, and `responsive` (mobile/desktop with a custom breakpoint), matching the React and Vue adapters:
94
-
95
- ```html
96
- <dfk-multi-field-input
97
- [fieldDescriptions]="fields"
98
- [layout]="{ type: 'grid', columns: 3, gap: 16 }"
99
- ></dfk-multi-field-input>
100
-
101
- <dfk-multi-field-input
102
- [fieldDescriptions]="fields"
103
- [layout]="{
104
- type: 'responsive',
105
- mobile: 'column',
106
- desktop: { type: 'grid', columns: 2, gap: 12 }
107
- }"
108
- ></dfk-multi-field-input>
109
- ```
110
-
111
- ## Derived fields with `computeValue`
112
-
113
- Give a field a `computeValue` to derive its value from the rest of the form data whenever any field changes:
114
-
115
- ```ts
116
- fields: FieldDescription[] = [
117
- { name: 'firstName', type: 'text' },
118
- { name: 'lastName', type: 'text' },
119
- {
120
- name: 'fullName',
121
- type: 'text',
122
- computeValue: (data) => `${data.firstName ?? ''} ${data.lastName ?? ''}`.trim(),
123
- },
124
- ];
125
- ```
126
-
127
- ## Repeatable field groups
128
-
129
- 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.
130
-
131
- ```ts
132
- fields: FieldDescription[] = [
133
- {
134
- name: 'contacts',
135
- type: 'group',
136
- label: 'Contacts',
137
- fields: [
138
- { name: 'email', type: 'text', label: 'Email' },
139
- { name: 'phone', type: 'text', label: 'Phone' },
140
- ],
141
- defaultItem: { email: '', phone: '' },
142
- minItems: 1,
143
- maxItems: 5,
144
- },
145
- ];
146
- ```
147
-
148
- ```html
149
- <dfk-multi-field-input [fieldDescriptions]="fields"></dfk-multi-field-input>
150
- ```
151
-
152
- ## Legacy setup (Angular 14 and earlier with NgModule)
153
-
154
- ```ts
155
- import { BrowserModule } from '@angular/platform-browser';
156
- import { NgModule } from '@angular/core';
157
- import { DynamicFieldKitModule } from '@dynamic-field-kit/angular';
158
-
159
- @NgModule({
160
- imports: [BrowserModule, DynamicFieldKitModule],
161
- })
162
- export class AppModule {}
163
- ```
164
-
165
- ## Type augmentation
166
-
167
- ```ts
168
- import '@dynamic-field-kit/core';
169
-
170
- declare module '@dynamic-field-kit/core' {
171
- interface FieldTypeMap {
172
- text: string;
173
- number: number;
174
- }
175
- }
176
- ```
177
-
178
- ## Notes
179
-
180
- - Register Angular component classes in `fieldRegistry`.
181
- - Do not register React or Vue renderers in the Angular adapter.
182
- - `MultiFieldInput` supports `column`, `row`, `grid`, and `responsive` layouts, and derives fields using `computeValue`.
183
- - Fields with `fields` render as repeatable groups instead of going through `fieldRegistry`.
184
- - The shared schema and field types still come from `@dynamic-field-kit/core`.
185
-
186
- ## License
187
-
188
- MIT
@@ -1,68 +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
- options;
11
- className;
12
- description;
13
- errorMessage;
14
- acceptFile;
15
- maxLength;
16
- minNumber;
17
- maxNumber;
18
- valueChange = new EventEmitter();
19
- constructor(cdr) {
20
- this.cdr = cdr;
21
- }
22
- ngOnChanges(_changes) {
23
- this.detectChanges();
24
- }
25
- detectChanges() {
26
- this.cdr.markForCheck();
27
- }
28
- hasChanges(changes, prop) {
29
- return changes[prop] !== undefined;
30
- }
31
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: BaseInputComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
32
- 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", options: "options", className: "className", description: "description", errorMessage: "errorMessage", acceptFile: "acceptFile", maxLength: "maxLength", minNumber: "minNumber", maxNumber: "maxNumber" }, outputs: { valueChange: "valueChange" }, usesOnChanges: true, ngImport: i0, template: '', isInline: true });
33
- }
34
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: BaseInputComponent, decorators: [{
35
- type: Component,
36
- args: [{
37
- template: '',
38
- }]
39
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { value: [{
40
- type: Input
41
- }], label: [{
42
- type: Input
43
- }], placeholder: [{
44
- type: Input
45
- }], required: [{
46
- type: Input
47
- }], disabled: [{
48
- type: Input
49
- }], options: [{
50
- type: Input
51
- }], className: [{
52
- type: Input
53
- }], description: [{
54
- type: Input
55
- }], errorMessage: [{
56
- type: Input
57
- }], acceptFile: [{
58
- type: Input
59
- }], maxLength: [{
60
- type: Input
61
- }], minNumber: [{
62
- type: Input
63
- }], maxNumber: [{
64
- type: Input
65
- }], valueChange: [{
66
- type: Output
67
- }] } });
68
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQmFzZUlucHV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvQmFzZUlucHV0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFFTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLEtBQUssRUFFTCxNQUFNLEdBRVAsTUFBTSxlQUFlLENBQUM7O0FBcUJ2QixNQUFNLE9BQWdCLGtCQUFrQjtJQWlCaEI7SUFoQmIsS0FBSyxDQUFXO0lBQ2hCLEtBQUssQ0FBVTtJQUNmLFdBQVcsQ0FBVTtJQUNyQixRQUFRLENBQVc7SUFDbkIsUUFBUSxDQUFXO0lBQ25CLE9BQU8sQ0FBYTtJQUNwQixTQUFTLENBQVU7SUFDbkIsV0FBVyxDQUFVO0lBQ3JCLFlBQVksQ0FBVTtJQUN0QixVQUFVLENBQVU7SUFDcEIsU0FBUyxDQUFVO0lBQ25CLFNBQVMsQ0FBVTtJQUNuQixTQUFTLENBQVU7SUFFbEIsV0FBVyxHQUFHLElBQUksWUFBWSxFQUFXLENBQUM7SUFFcEQsWUFBc0IsR0FBc0I7UUFBdEIsUUFBRyxHQUFILEdBQUcsQ0FBbUI7SUFBRyxDQUFDO0lBRWhELFdBQVcsQ0FBQyxRQUF1QjtRQUNqQyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDdkIsQ0FBQztJQUVTLGFBQWE7UUFDckIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBRVMsVUFBVSxDQUFDLE9BQXNCLEVBQUUsSUFBWTtRQUN2RCxPQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxTQUFTLENBQUM7SUFDckMsQ0FBQzt3R0E3Qm1CLGtCQUFrQjs0RkFBbEIsa0JBQWtCLGtjQUY1QixFQUFFOzs0RkFFUSxrQkFBa0I7a0JBSHZDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLEVBQUU7aUJBQ2I7c0ZBRVUsS0FBSztzQkFBYixLQUFLO2dCQUNHLEtBQUs7c0JBQWIsS0FBSztnQkFDRyxXQUFXO3NCQUFuQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxPQUFPO3NCQUFmLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxXQUFXO3NCQUFuQixLQUFLO2dCQUNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ0csVUFBVTtzQkFBbEIsS0FBSztnQkFDRyxTQUFTO3NCQUFqQixLQUFLO2dCQUNHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFFSSxXQUFXO3NCQUFwQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXMsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEZpZWxkSW5wdXRQcm9wcyB7XG4gIHZhbHVlPzogdW5rbm93bjtcbiAgbGFiZWw/OiBzdHJpbmc7XG4gIHBsYWNlaG9sZGVyPzogc3RyaW5nO1xuICByZXF1aXJlZD86IGJvb2xlYW47XG4gIGRpc2FibGVkPzogYm9vbGVhbjtcbiAgb3B0aW9ucz86IHVua25vd25bXTtcbiAgY2xhc3NOYW1lPzogc3RyaW5nO1xuICBkZXNjcmlwdGlvbj86IHN0cmluZztcbiAgZXJyb3JNZXNzYWdlPzogc3RyaW5nO1xuICBhY2NlcHRGaWxlPzogc3RyaW5nO1xuICBtYXhMZW5ndGg/OiBudW1iZXI7XG4gIG1pbk51bWJlcj86IG51bWJlcjtcbiAgbWF4TnVtYmVyPzogbnVtYmVyO1xufVxuXG5AQ29tcG9uZW50KHtcbiAgdGVtcGxhdGU6ICcnLFxufSlcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBCYXNlSW5wdXRDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xuICBASW5wdXQoKSB2YWx1ZT86IHVua25vd247XG4gIEBJbnB1dCgpIGxhYmVsPzogc3RyaW5nO1xuICBASW5wdXQoKSBwbGFjZWhvbGRlcj86IHN0cmluZztcbiAgQElucHV0KCkgcmVxdWlyZWQ/OiBib29sZWFuO1xuICBASW5wdXQoKSBkaXNhYmxlZD86IGJvb2xlYW47XG4gIEBJbnB1dCgpIG9wdGlvbnM/OiB1bmtub3duW107XG4gIEBJbnB1dCgpIGNsYXNzTmFtZT86IHN0cmluZztcbiAgQElucHV0KCkgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gIEBJbnB1dCgpIGVycm9yTWVzc2FnZT86IHN0cmluZztcbiAgQElucHV0KCkgYWNjZXB0RmlsZT86IHN0cmluZztcbiAgQElucHV0KCkgbWF4TGVuZ3RoPzogbnVtYmVyO1xuICBASW5wdXQoKSBtaW5OdW1iZXI/OiBudW1iZXI7XG4gIEBJbnB1dCgpIG1heE51bWJlcj86IG51bWJlcjtcblxuICBAT3V0cHV0KCkgdmFsdWVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHVua25vd24+KCk7XG5cbiAgY29uc3RydWN0b3IocHJvdGVjdGVkIGNkcjogQ2hhbmdlRGV0ZWN0b3JSZWYpIHt9XG5cbiAgbmdPbkNoYW5nZXMoX2NoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICB0aGlzLmRldGVjdENoYW5nZXMoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBkZXRlY3RDaGFuZ2VzKCk6IHZvaWQge1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGhhc0NoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcywgcHJvcDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGNoYW5nZXNbcHJvcF0gIT09IHVuZGVmaW5lZDtcbiAgfVxufVxuIl19