@ng-forge/openapi-generator 0.7.0 → 0.8.0-next.2
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.
- package/README.md +6 -0
- package/bin/ng-forge-generator.js +55 -19
- package/package.json +2 -2
- package/src/__tests__/integration/helpers.d.ts +21 -0
- package/src/__tests__/integration/helpers.d.ts.map +1 -1
- package/src/index.js +55 -19
- package/src/mapper/schema-to-fields.d.ts +1 -0
- package/src/mapper/schema-to-fields.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Converts OpenAPI 3.x specifications into `@ng-forge/dynamic-forms` FormConfig objects and TypeScript interfaces.
|
|
4
4
|
|
|
5
|
+
[](https://github.com/ng-forge/ng-forge/actions/workflows/ci.yml)
|
|
6
|
+
[](https://www.npmjs.com/package/@ng-forge/openapi-generator)
|
|
7
|
+
[](https://www.npmjs.com/package/@ng-forge/openapi-generator)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
[](https://discord.gg/qpzzvFagj3)
|
|
10
|
+
|
|
5
11
|
## Quick Start
|
|
6
12
|
|
|
7
13
|
**1. Write (or already have) an OpenAPI 3.x spec:**
|
|
@@ -453,6 +453,7 @@ var logger = {
|
|
|
453
453
|
};
|
|
454
454
|
|
|
455
455
|
// packages/openapi-generator/src/mapper/schema-to-fields.ts
|
|
456
|
+
var NULLABLE_SUPPORTED_FIELD_TYPES = /* @__PURE__ */ new Set(["input", "textarea", "select", "radio", "multi-checkbox", "slider", "datepicker"]);
|
|
456
457
|
function singularize(label) {
|
|
457
458
|
if (label.length >= 4 && label.endsWith("s") && !label.endsWith("ss")) {
|
|
458
459
|
return label.slice(0, -1);
|
|
@@ -568,6 +569,14 @@ function mapPropertyToField(prop, options, ambiguousFields, warnings) {
|
|
|
568
569
|
field.disabled = true;
|
|
569
570
|
logger.verbose(`Field '${fieldPath}': disabled (readOnly in schema)`);
|
|
570
571
|
}
|
|
572
|
+
const schemaObj = prop.schema;
|
|
573
|
+
const hasNullBranch = (variants) => Array.isArray(variants) && variants.some((v) => v && v["type"] === "null");
|
|
574
|
+
const isNullable = schemaObj["nullable"] === true || Array.isArray(schemaObj["type"]) && schemaObj["type"].includes("null") || hasNullBranch(schemaObj["oneOf"]) || hasNullBranch(schemaObj["anyOf"]);
|
|
575
|
+
if (isNullable && NULLABLE_SUPPORTED_FIELD_TYPES.has(finalType)) {
|
|
576
|
+
field.nullable = true;
|
|
577
|
+
} else if (isNullable) {
|
|
578
|
+
logger.verbose(`Field '${fieldPath}': schema nullable ignored \u2014 '${finalType}' does not support the nullable flag in this release.`);
|
|
579
|
+
}
|
|
571
580
|
if (prop.schema.default !== void 0) {
|
|
572
581
|
field.value = prop.schema.default;
|
|
573
582
|
}
|
|
@@ -578,19 +587,22 @@ function mapPropertyToField(prop, options, ambiguousFields, warnings) {
|
|
|
578
587
|
field.props = { ...field.props, hint: prop.schema.description };
|
|
579
588
|
}
|
|
580
589
|
if (prop.schema.enum) {
|
|
581
|
-
const
|
|
582
|
-
|
|
583
|
-
const
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
label
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
590
|
+
const filteredEnum = prop.schema.enum.filter((v) => v !== null);
|
|
591
|
+
if (filteredEnum.length > 0) {
|
|
592
|
+
const enumLabels = prop.schema["x-enum-labels"];
|
|
593
|
+
field.options = filteredEnum.map((v, i) => {
|
|
594
|
+
const strVal = String(v);
|
|
595
|
+
let label;
|
|
596
|
+
if (Array.isArray(enumLabels) && enumLabels[i]) {
|
|
597
|
+
label = enumLabels[i];
|
|
598
|
+
} else if (enumLabels && !Array.isArray(enumLabels) && enumLabels[strVal]) {
|
|
599
|
+
label = enumLabels[strVal];
|
|
600
|
+
} else {
|
|
601
|
+
label = toEnumLabel(strVal);
|
|
602
|
+
}
|
|
603
|
+
return { label, value: strVal };
|
|
604
|
+
});
|
|
605
|
+
}
|
|
594
606
|
}
|
|
595
607
|
if (validators.length > 0) {
|
|
596
608
|
field.validators = validators;
|
|
@@ -652,6 +664,11 @@ function mapPropertyToField(prop, options, ambiguousFields, warnings) {
|
|
|
652
664
|
value: String(v)
|
|
653
665
|
}));
|
|
654
666
|
}
|
|
667
|
+
const itemsObj = items;
|
|
668
|
+
const itemsNullable = itemsObj["nullable"] === true || Array.isArray(itemsObj["type"]) && itemsObj["type"].includes("null");
|
|
669
|
+
if (itemsNullable && NULLABLE_SUPPORTED_FIELD_TYPES.has(templateField.type)) {
|
|
670
|
+
templateField.nullable = true;
|
|
671
|
+
}
|
|
655
672
|
field.template = templateField;
|
|
656
673
|
}
|
|
657
674
|
if (!field.disabled) {
|
|
@@ -691,6 +708,9 @@ function generateFieldLines(field, indent) {
|
|
|
691
708
|
if (field.value !== void 0) {
|
|
692
709
|
lines.push(`${indent} value: ${JSON.stringify(field.value)},`);
|
|
693
710
|
}
|
|
711
|
+
if (field.nullable) {
|
|
712
|
+
lines.push(`${indent} nullable: true,`);
|
|
713
|
+
}
|
|
694
714
|
if (field.placeholder) {
|
|
695
715
|
lines.push(`${indent} placeholder: '${escapeString(field.placeholder)}',`);
|
|
696
716
|
}
|
|
@@ -890,12 +910,24 @@ function resolveSchemaProperties(schema) {
|
|
|
890
910
|
return { properties, required };
|
|
891
911
|
}
|
|
892
912
|
function schemaToTsType(propertyName, schema, parentName, nestedInterfaces) {
|
|
893
|
-
const
|
|
894
|
-
|
|
895
|
-
|
|
913
|
+
const rawType = schema["type"];
|
|
914
|
+
let type;
|
|
915
|
+
let nullableFrom31Type = false;
|
|
916
|
+
if (Array.isArray(rawType)) {
|
|
917
|
+
const nonNull = rawType.filter((t) => t !== "null");
|
|
918
|
+
nullableFrom31Type = nonNull.length !== rawType.length;
|
|
919
|
+
type = nonNull[0];
|
|
920
|
+
} else {
|
|
921
|
+
type = rawType;
|
|
922
|
+
}
|
|
923
|
+
const isNullable = schema["nullable"] === true || nullableFrom31Type;
|
|
924
|
+
const enumValues = schema.enum ? schema.enum.filter((v) => v !== null) : void 0;
|
|
925
|
+
if (enumValues && enumValues.length > 0) {
|
|
926
|
+
const enumUnion = enumValues.map((v) => typeof v === "string" ? `'${v}'` : String(v)).join(" | ");
|
|
927
|
+
return isNullable ? `${enumUnion} | null` : enumUnion;
|
|
896
928
|
}
|
|
897
|
-
if (
|
|
898
|
-
const baseSchema = { ...schema, nullable: void 0 };
|
|
929
|
+
if (isNullable) {
|
|
930
|
+
const baseSchema = { ...schema, nullable: void 0, type };
|
|
899
931
|
const baseType = schemaToTsType(propertyName, baseSchema, parentName, nestedInterfaces);
|
|
900
932
|
return `${baseType} | null`;
|
|
901
933
|
}
|
|
@@ -916,9 +948,13 @@ function schemaToTsType(propertyName, schema, parentName, nestedInterfaces) {
|
|
|
916
948
|
return types.join(" | ");
|
|
917
949
|
}
|
|
918
950
|
if (schema.allOf) {
|
|
919
|
-
const types = schema.allOf.filter((s) => !isReferenceObject(s)).map((s) =>
|
|
951
|
+
const types = schema.allOf.filter((s) => !isReferenceObject(s)).map((s) => {
|
|
952
|
+
const t = schemaToTsType(propertyName, s, parentName, nestedInterfaces);
|
|
953
|
+
return t.includes(" | ") ? `(${t})` : t;
|
|
954
|
+
});
|
|
920
955
|
return types.join(" & ");
|
|
921
956
|
}
|
|
957
|
+
if (type === "null") return "null";
|
|
922
958
|
if (type === "string") return "string";
|
|
923
959
|
if (type === "integer" || type === "number") return "number";
|
|
924
960
|
if (type === "boolean") return "boolean";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ng-forge/openapi-generator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0-next.2",
|
|
4
4
|
"description": "Generate @ng-forge/dynamic-forms configurations from OpenAPI specs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"README.md"
|
|
41
41
|
],
|
|
42
42
|
"engines": {
|
|
43
|
-
"node": ">=
|
|
43
|
+
"node": ">=24.0.0"
|
|
44
44
|
},
|
|
45
45
|
"sideEffects": false,
|
|
46
46
|
"dependencies": {
|
|
@@ -5,4 +5,25 @@ export declare function cleanupDir(dir: string): Promise<void>;
|
|
|
5
5
|
export declare function readGenerated(outputDir: string, subdirectory: string, fileName: string): Promise<string>;
|
|
6
6
|
export declare function readConfigFile(dir: string): Promise<Record<string, unknown>>;
|
|
7
7
|
export declare function fileExists(filePath: string): Promise<boolean>;
|
|
8
|
+
export type AdapterName = 'material' | 'bootstrap' | 'primeng' | 'ionic';
|
|
9
|
+
/**
|
|
10
|
+
* Type-check a generator-produced form file the way a real consumer would: with a UI
|
|
11
|
+
* adapter (Material by default) registered via module augmentation. The adapter import
|
|
12
|
+
* is what activates field types like `'input'` — without it the generated config fails
|
|
13
|
+
* against the core-only `RegisteredFieldTypes`.
|
|
14
|
+
*
|
|
15
|
+
* Resolves `@ng-forge/dynamic-forms` and the adapter via tsconfig `paths` so the test
|
|
16
|
+
* is self-contained. Requires `dist/packages/dynamic-forms` and
|
|
17
|
+
* `dist/packages/dynamic-forms-{adapter}` to exist — `nx build dynamic-forms` and the
|
|
18
|
+
* adapter build must run before.
|
|
19
|
+
*
|
|
20
|
+
* Returns an array of pretty-formatted diagnostics. Empty array === clean compile.
|
|
21
|
+
*/
|
|
22
|
+
export declare function typecheckGeneratedForm(formFilePath: string, adapter?: AdapterName): string[];
|
|
23
|
+
/**
|
|
24
|
+
* Write a tsconfig next to a generated form that mirrors the compile options used by
|
|
25
|
+
* `typecheckGeneratedForm`. Editors and ad-hoc `tsc` invocations pick up the same
|
|
26
|
+
* adapter paths and module/resolution settings, so local inspection matches CI.
|
|
27
|
+
*/
|
|
28
|
+
export declare function writeRepoRelativeTsconfig(outputDir: string, adapter?: AdapterName): Promise<void>;
|
|
8
29
|
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../../../packages/openapi-generator/src/__tests__/integration/helpers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../../../packages/openapi-generator/src/__tests__/integration/helpers.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,UAAU,QAAqC,CAAC;AAE7D,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CAErD;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3D;AAED,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE9G;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAGlF;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE;AAkCD,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;AAEzE;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,GAAE,WAAwB,GAAG,MAAM,EAAE,CA+CxG;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,WAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBnH"}
|
package/src/index.js
CHANGED
|
@@ -445,6 +445,7 @@ var logger = {
|
|
|
445
445
|
};
|
|
446
446
|
|
|
447
447
|
// packages/openapi-generator/src/mapper/schema-to-fields.ts
|
|
448
|
+
var NULLABLE_SUPPORTED_FIELD_TYPES = /* @__PURE__ */ new Set(["input", "textarea", "select", "radio", "multi-checkbox", "slider", "datepicker"]);
|
|
448
449
|
function singularize(label) {
|
|
449
450
|
if (label.length >= 4 && label.endsWith("s") && !label.endsWith("ss")) {
|
|
450
451
|
return label.slice(0, -1);
|
|
@@ -560,6 +561,14 @@ function mapPropertyToField(prop, options, ambiguousFields, warnings) {
|
|
|
560
561
|
field.disabled = true;
|
|
561
562
|
logger.verbose(`Field '${fieldPath}': disabled (readOnly in schema)`);
|
|
562
563
|
}
|
|
564
|
+
const schemaObj = prop.schema;
|
|
565
|
+
const hasNullBranch = (variants) => Array.isArray(variants) && variants.some((v) => v && v["type"] === "null");
|
|
566
|
+
const isNullable = schemaObj["nullable"] === true || Array.isArray(schemaObj["type"]) && schemaObj["type"].includes("null") || hasNullBranch(schemaObj["oneOf"]) || hasNullBranch(schemaObj["anyOf"]);
|
|
567
|
+
if (isNullable && NULLABLE_SUPPORTED_FIELD_TYPES.has(finalType)) {
|
|
568
|
+
field.nullable = true;
|
|
569
|
+
} else if (isNullable) {
|
|
570
|
+
logger.verbose(`Field '${fieldPath}': schema nullable ignored \u2014 '${finalType}' does not support the nullable flag in this release.`);
|
|
571
|
+
}
|
|
563
572
|
if (prop.schema.default !== void 0) {
|
|
564
573
|
field.value = prop.schema.default;
|
|
565
574
|
}
|
|
@@ -570,19 +579,22 @@ function mapPropertyToField(prop, options, ambiguousFields, warnings) {
|
|
|
570
579
|
field.props = { ...field.props, hint: prop.schema.description };
|
|
571
580
|
}
|
|
572
581
|
if (prop.schema.enum) {
|
|
573
|
-
const
|
|
574
|
-
|
|
575
|
-
const
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
label
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
582
|
+
const filteredEnum = prop.schema.enum.filter((v) => v !== null);
|
|
583
|
+
if (filteredEnum.length > 0) {
|
|
584
|
+
const enumLabels = prop.schema["x-enum-labels"];
|
|
585
|
+
field.options = filteredEnum.map((v, i) => {
|
|
586
|
+
const strVal = String(v);
|
|
587
|
+
let label;
|
|
588
|
+
if (Array.isArray(enumLabels) && enumLabels[i]) {
|
|
589
|
+
label = enumLabels[i];
|
|
590
|
+
} else if (enumLabels && !Array.isArray(enumLabels) && enumLabels[strVal]) {
|
|
591
|
+
label = enumLabels[strVal];
|
|
592
|
+
} else {
|
|
593
|
+
label = toEnumLabel(strVal);
|
|
594
|
+
}
|
|
595
|
+
return { label, value: strVal };
|
|
596
|
+
});
|
|
597
|
+
}
|
|
586
598
|
}
|
|
587
599
|
if (validators.length > 0) {
|
|
588
600
|
field.validators = validators;
|
|
@@ -644,6 +656,11 @@ function mapPropertyToField(prop, options, ambiguousFields, warnings) {
|
|
|
644
656
|
value: String(v)
|
|
645
657
|
}));
|
|
646
658
|
}
|
|
659
|
+
const itemsObj = items;
|
|
660
|
+
const itemsNullable = itemsObj["nullable"] === true || Array.isArray(itemsObj["type"]) && itemsObj["type"].includes("null");
|
|
661
|
+
if (itemsNullable && NULLABLE_SUPPORTED_FIELD_TYPES.has(templateField.type)) {
|
|
662
|
+
templateField.nullable = true;
|
|
663
|
+
}
|
|
647
664
|
field.template = templateField;
|
|
648
665
|
}
|
|
649
666
|
if (!field.disabled) {
|
|
@@ -683,6 +700,9 @@ function generateFieldLines(field, indent) {
|
|
|
683
700
|
if (field.value !== void 0) {
|
|
684
701
|
lines.push(`${indent} value: ${JSON.stringify(field.value)},`);
|
|
685
702
|
}
|
|
703
|
+
if (field.nullable) {
|
|
704
|
+
lines.push(`${indent} nullable: true,`);
|
|
705
|
+
}
|
|
686
706
|
if (field.placeholder) {
|
|
687
707
|
lines.push(`${indent} placeholder: '${escapeString(field.placeholder)}',`);
|
|
688
708
|
}
|
|
@@ -882,12 +902,24 @@ function resolveSchemaProperties(schema) {
|
|
|
882
902
|
return { properties, required };
|
|
883
903
|
}
|
|
884
904
|
function schemaToTsType(propertyName, schema, parentName, nestedInterfaces) {
|
|
885
|
-
const
|
|
886
|
-
|
|
887
|
-
|
|
905
|
+
const rawType = schema["type"];
|
|
906
|
+
let type;
|
|
907
|
+
let nullableFrom31Type = false;
|
|
908
|
+
if (Array.isArray(rawType)) {
|
|
909
|
+
const nonNull = rawType.filter((t) => t !== "null");
|
|
910
|
+
nullableFrom31Type = nonNull.length !== rawType.length;
|
|
911
|
+
type = nonNull[0];
|
|
912
|
+
} else {
|
|
913
|
+
type = rawType;
|
|
914
|
+
}
|
|
915
|
+
const isNullable = schema["nullable"] === true || nullableFrom31Type;
|
|
916
|
+
const enumValues = schema.enum ? schema.enum.filter((v) => v !== null) : void 0;
|
|
917
|
+
if (enumValues && enumValues.length > 0) {
|
|
918
|
+
const enumUnion = enumValues.map((v) => typeof v === "string" ? `'${v}'` : String(v)).join(" | ");
|
|
919
|
+
return isNullable ? `${enumUnion} | null` : enumUnion;
|
|
888
920
|
}
|
|
889
|
-
if (
|
|
890
|
-
const baseSchema = { ...schema, nullable: void 0 };
|
|
921
|
+
if (isNullable) {
|
|
922
|
+
const baseSchema = { ...schema, nullable: void 0, type };
|
|
891
923
|
const baseType = schemaToTsType(propertyName, baseSchema, parentName, nestedInterfaces);
|
|
892
924
|
return `${baseType} | null`;
|
|
893
925
|
}
|
|
@@ -908,9 +940,13 @@ function schemaToTsType(propertyName, schema, parentName, nestedInterfaces) {
|
|
|
908
940
|
return types.join(" | ");
|
|
909
941
|
}
|
|
910
942
|
if (schema.allOf) {
|
|
911
|
-
const types = schema.allOf.filter((s) => !isReferenceObject(s)).map((s) =>
|
|
943
|
+
const types = schema.allOf.filter((s) => !isReferenceObject(s)).map((s) => {
|
|
944
|
+
const t = schemaToTsType(propertyName, s, parentName, nestedInterfaces);
|
|
945
|
+
return t.includes(" | ") ? `(${t})` : t;
|
|
946
|
+
});
|
|
912
947
|
return types.join(" & ");
|
|
913
948
|
}
|
|
949
|
+
if (type === "null") return "null";
|
|
914
950
|
if (type === "string") return "string";
|
|
915
951
|
if (type === "integer" || type === "number") return "number";
|
|
916
952
|
if (type === "boolean") return "boolean";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-to-fields.d.ts","sourceRoot":"","sources":["../../../../../packages/openapi-generator/src/mapper/schema-to-fields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,4BAA4B,CAAC;AAG/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"schema-to-fields.d.ts","sourceRoot":"","sources":["../../../../../packages/openapi-generator/src/mapper/schema-to-fields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,4BAA4B,CAAC;AAG/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAsB9D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,WAAW,GAAG,WAAW,EAAE,CAAC;IACvC,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,KAAK,CAAC;IACvE,YAAY,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,KAAK,CAAC;IAC1E,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,cAAmB,GAAG,aAAa,CA0D7H"}
|