@haus-tech/product-import-export-plugin 3.6.12 → 3.6.14

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 (56) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +110 -10
  3. package/package.json +1 -1
  4. package/src/constants.d.ts +1 -0
  5. package/src/constants.js +2 -1
  6. package/src/constants.js.map +1 -1
  7. package/src/dashboard/export-configuration-panel.tsx +1 -0
  8. package/src/dashboard/utils.ts +1 -0
  9. package/src/helpers/find-text-column.d.ts +8 -0
  10. package/src/helpers/find-text-column.js +32 -0
  11. package/src/helpers/find-text-column.js.map +1 -0
  12. package/src/index.d.ts +1 -0
  13. package/src/index.js +1 -0
  14. package/src/index.js.map +1 -1
  15. package/src/product-import-export.plugin.d.ts +11 -1
  16. package/src/product-import-export.plugin.js +35 -3
  17. package/src/product-import-export.plugin.js.map +1 -1
  18. package/src/providers/import-providers/import-parser.d.ts +9 -0
  19. package/src/providers/import-providers/import-parser.js +26 -8
  20. package/src/providers/import-providers/import-parser.js.map +1 -1
  21. package/src/providers/import-providers/product-importer.d.ts +58 -10
  22. package/src/providers/import-providers/product-importer.js +163 -94
  23. package/src/providers/import-providers/product-importer.js.map +1 -1
  24. package/src/services/channel-column-resolver.d.ts +24 -0
  25. package/src/services/channel-column-resolver.js +79 -0
  26. package/src/services/channel-column-resolver.js.map +1 -0
  27. package/src/services/export-relation-lookups.d.ts +26 -0
  28. package/src/services/export-relation-lookups.js +56 -0
  29. package/src/services/export-relation-lookups.js.map +1 -0
  30. package/src/services/extended-fast-importer.service.d.ts +16 -0
  31. package/src/services/extended-fast-importer.service.js +46 -21
  32. package/src/services/extended-fast-importer.service.js.map +1 -1
  33. package/src/services/import-row-groups.d.ts +17 -0
  34. package/src/services/import-row-groups.js +69 -0
  35. package/src/services/import-row-groups.js.map +1 -0
  36. package/src/services/product-export.service.d.ts +9 -3
  37. package/src/services/product-export.service.js +57 -10
  38. package/src/services/product-export.service.js.map +1 -1
  39. package/src/services/product-import.service.d.ts +1 -3
  40. package/src/services/product-import.service.js +10 -9
  41. package/src/services/product-import.service.js.map +1 -1
  42. package/src/services/relation-lookup-resolver.d.ts +52 -0
  43. package/src/services/relation-lookup-resolver.js +245 -0
  44. package/src/services/relation-lookup-resolver.js.map +1 -0
  45. package/src/services/self-relation-custom-fields.d.ts +7 -0
  46. package/src/services/self-relation-custom-fields.js +24 -0
  47. package/src/services/self-relation-custom-fields.js.map +1 -1
  48. package/src/strategies/import-row-validation-strategy.d.ts +71 -0
  49. package/src/strategies/import-row-validation-strategy.js +16 -0
  50. package/src/strategies/import-row-validation-strategy.js.map +1 -0
  51. package/src/types.d.ts +21 -1
  52. package/src/ui/components/export-dialog.component.ts +2 -0
  53. package/src/ui/components/product-import.component.ts +1 -0
  54. package/src/services/sku-relation-resolver.d.ts +0 -33
  55. package/src/services/sku-relation-resolver.js +0 -177
  56. package/src/services/sku-relation-resolver.js.map +0 -1
@@ -0,0 +1,71 @@
1
+ import { InjectableStrategy, RequestContext } from '@vendure/core';
2
+ /**
3
+ * @description
4
+ * One product of an import file as the {@link ImportRowValidationStrategy} sees it: the product's
5
+ * first row and every variant row under it, with the line each came from (the header is line 1,
6
+ * blank and comma-only lines are not counted).
7
+ *
8
+ * Custom fields are keyed as the Admin API input takes them: a relation field under its input name
9
+ * (`<name>Id`, or `<name>Ids` for a list) holding id strings, whether the file gave ids or a lookup
10
+ * column (`:sku`, `:code`) that has been resolved. A value that could not be resolved is left out
11
+ * (the lookup error is reported anyway), and so is an empty cell, which leaves the relation as it
12
+ * is. An Asset relation keeps its raw cell under the field name, since assets are only created when
13
+ * the row is written. Other custom fields keep their cell text under the field name.
14
+ * `product.customFields` holds the first translation's custom fields, which include every
15
+ * non-localised field.
16
+ *
17
+ * The groups are copies: changing them changes nothing that is imported.
18
+ *
19
+ * @category Import
20
+ */
21
+ export interface ImportRowGroup {
22
+ line: number;
23
+ product: {
24
+ customFields: Record<string, unknown>;
25
+ translations: unknown[];
26
+ [key: string]: unknown;
27
+ };
28
+ variants: Array<{
29
+ line: number;
30
+ variant: {
31
+ sku: string;
32
+ customFields: Record<string, unknown>;
33
+ [key: string]: unknown;
34
+ };
35
+ }>;
36
+ }
37
+ /**
38
+ * @description
39
+ * A problem with one row. Shown to the uploader as `Row <line>: <message>`.
40
+ *
41
+ * @category Import
42
+ */
43
+ export interface ImportRowError {
44
+ line: number;
45
+ message: string;
46
+ }
47
+ /**
48
+ * @description
49
+ * Checks the rows of an import file before anything is written. It runs twice: when the file is
50
+ * uploaded, before it is stored and queued (the upload answers `400` with the errors), and again
51
+ * when the import job starts, since data can change while the job waits (the job fails with the
52
+ * errors and imports nothing). Errors from relation lookups and from this strategy come back in
53
+ * one list.
54
+ *
55
+ * Set it with `ProductImportExportPlugin.init({ importOptions: { rowValidationStrategy } })`.
56
+ * `init(injector)` and `destroy()` are called when the application starts and stops.
57
+ *
58
+ * @category Import
59
+ */
60
+ export interface ImportRowValidationStrategy extends InjectableStrategy {
61
+ validate(ctx: RequestContext, rows: ImportRowGroup[]): Promise<ImportRowError[]>;
62
+ }
63
+ /**
64
+ * @description
65
+ * The default {@link ImportRowValidationStrategy}: accepts every row.
66
+ *
67
+ * @category Import
68
+ */
69
+ export declare class DefaultImportRowValidationStrategy implements ImportRowValidationStrategy {
70
+ validate(): Promise<ImportRowError[]>;
71
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DefaultImportRowValidationStrategy = void 0;
4
+ /**
5
+ * @description
6
+ * The default {@link ImportRowValidationStrategy}: accepts every row.
7
+ *
8
+ * @category Import
9
+ */
10
+ class DefaultImportRowValidationStrategy {
11
+ async validate() {
12
+ return [];
13
+ }
14
+ }
15
+ exports.DefaultImportRowValidationStrategy = DefaultImportRowValidationStrategy;
16
+ //# sourceMappingURL=import-row-validation-strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-row-validation-strategy.js","sourceRoot":"","sources":["../../../../../packages/product-import-export-plugin/src/strategies/import-row-validation-strategy.ts"],"names":[],"mappings":";;;AA8DA;;;;;GAKG;AACH,MAAa,kCAAkC;IAC7C,KAAK,CAAC,QAAQ;QACZ,OAAO,EAAE,CAAA;IACX,CAAC;CACF;AAJD,gFAIC"}
package/src/types.d.ts CHANGED
@@ -3,6 +3,7 @@ import { ParsedProduct, ParsedProductWithVariants } from './providers/import-pro
3
3
  import type { Injector, Product, ProductVariant, RequestContext } from '@vendure/core';
4
4
  import { ExportStorageStrategy } from './services/export-storage/export-storage-strategy';
5
5
  import { ImportJobStorageStrategy } from './services/import-storage/import-job-storage-strategy';
6
+ import { ImportRowValidationStrategy } from './strategies/import-row-validation-strategy';
6
7
  /**
7
8
  * @description
8
9
  * The plugin can be configured using the following options:
@@ -50,6 +51,13 @@ export interface PluginInitOptions {
50
51
  storageStrategy?: ImportOptions['storageStrategy'];
51
52
  storageStrategyFactory?: ImportOptions['storageStrategyFactory'];
52
53
  importJobStorage?: ImportOptions['importJobStorage'];
54
+ /**
55
+ * @description
56
+ * Checks the rows of an import file before anything is written: at upload, before the file is
57
+ * stored, and again when the import job starts. Defaults to
58
+ * {@link DefaultImportRowValidationStrategy}, which accepts every row.
59
+ */
60
+ rowValidationStrategy?: ImportRowValidationStrategy;
53
61
  };
54
62
  exportOptions: {
55
63
  defaultFileName?: string;
@@ -80,6 +88,18 @@ export interface PluginInitOptions {
80
88
  * plugin init time.
81
89
  */
82
90
  customExportColumns?: CustomExportColumn[];
91
+ /**
92
+ * @description
93
+ * Optional. Writes the chosen relation custom fields by a column of the related row instead
94
+ * of its id, keyed `<owner>:<field>` with the column as value, e.g.
95
+ * `{ 'variant:baseVariant': 'sku', 'product:brand': 'code' }`. The CSV header becomes
96
+ * `<owner>:<field>:<entity>:<column>`, the lookup header the import reads, so the file
97
+ * imports again, also into another database. The column must be a plain text column of the
98
+ * related entity, and the field must not relate to `Asset`; the application does not start
99
+ * otherwise. Soft-deleted related rows and rows without a value in the column are left out
100
+ * of the cell, since the import matches only live rows by a value.
101
+ */
102
+ relationLookups?: Record<string, string>;
83
103
  };
84
104
  }
85
105
  /**
@@ -108,7 +128,7 @@ export type JsonAsset = {
108
128
  name?: string;
109
129
  };
110
130
  type ExportFields = Array<ProductFields | VariantFields>;
111
- type ProductFields = 'id' | 'name' | 'slug' | 'description' | 'assets' | 'facets' | 'optionGroups';
131
+ type ProductFields = 'id' | 'name' | 'slug' | 'description' | 'assets' | 'channels' | 'facets' | 'optionGroups';
112
132
  type VariantFields = 'sku' | 'optionValues' | 'price' | 'taxCategory' | 'stockOnHand' | 'trackInventory' | 'variantAssets' | 'variantFacets' | 'enabled';
113
133
  export type UpdatingStrategy = 'replace' | 'merge';
114
134
  export {};
@@ -9,6 +9,7 @@ type ProductFields =
9
9
  | 'slug'
10
10
  | 'description'
11
11
  | 'assets'
12
+ | 'channels'
12
13
  | 'facets'
13
14
  | 'optionGroups'
14
15
 
@@ -71,6 +72,7 @@ export class ExportDialogComponent
71
72
  'slug',
72
73
  'description',
73
74
  'assets',
75
+ 'channels',
74
76
  'facets',
75
77
  'optionGroups',
76
78
  'sku',
@@ -129,6 +129,7 @@ export class ProductImportComponent implements OnInit {
129
129
 
130
130
  const optionalColumns = [
131
131
  'assets',
132
+ 'channels',
132
133
  'price',
133
134
  'taxCategory',
134
135
  'stockOnHand',
@@ -1,33 +0,0 @@
1
- import { ConfigService, ID, RequestContext, TransactionalConnection } from '@vendure/core';
2
- /** The fourth header segment that makes a relation column hold SKUs instead of ids. */
3
- export declare const SKU_LOOKUP = "sku";
4
- export interface SkuRelationResult {
5
- /** One line per problem, ready to show to the person who uploaded the file. */
6
- errors: string[];
7
- /** The id of the single live variant behind each SKU the file references. */
8
- variantIdsBySku: Map<string, ID>;
9
- /** `<owner>:<field>` keys of the relation columns whose values are SKUs. */
10
- fields: Set<string>;
11
- }
12
- /**
13
- * Resolves relation custom field columns written as `<owner>:<field>:<type>:sku`, where each
14
- * value names the related ProductVariant by SKU. Every SKU must match exactly one variant that is
15
- * not deleted, in any channel: base variants usually live outside the channel being imported into.
16
- */
17
- export declare class SkuRelationResolver {
18
- private connection;
19
- private configService;
20
- constructor(connection: TransactionalConnection, configService: ConfigService);
21
- resolve(ctx: RequestContext, csv: string): Promise<SkuRelationResult>;
22
- private splitHeader;
23
- private checkHeader;
24
- private findFieldConfig;
25
- /**
26
- * The SKUs each data row references, with the row's line as the importer numbers it: the
27
- * header is line 1 and blank and comma-only lines are not counted.
28
- */
29
- private readSkus;
30
- private findLiveVariants;
31
- }
32
- /** The SKUs in a list relation cell, written `SKU|SKU`. */
33
- export declare function splitSkuList(value: string): string[];
@@ -1,177 +0,0 @@
1
- "use strict";
2
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
- return c > 3 && r && Object.defineProperty(target, key, r), r;
7
- };
8
- var __metadata = (this && this.__metadata) || function (k, v) {
9
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.SkuRelationResolver = exports.SKU_LOOKUP = void 0;
13
- exports.splitSkuList = splitSkuList;
14
- const common_1 = require("@nestjs/common");
15
- const core_1 = require("@vendure/core");
16
- const sync_1 = require("csv-parse/sync");
17
- const typeorm_1 = require("typeorm");
18
- const import_csv_lines_1 = require("../helpers/import-csv-lines");
19
- /** The fourth header segment that makes a relation column hold SKUs instead of ids. */
20
- exports.SKU_LOOKUP = 'sku';
21
- /** SKUs per database query, well below every driver's bind parameter limit. */
22
- const SKU_QUERY_CHUNK_SIZE = 1000;
23
- /**
24
- * Resolves relation custom field columns written as `<owner>:<field>:<type>:sku`, where each
25
- * value names the related ProductVariant by SKU. Every SKU must match exactly one variant that is
26
- * not deleted, in any channel: base variants usually live outside the channel being imported into.
27
- */
28
- let SkuRelationResolver = class SkuRelationResolver {
29
- connection;
30
- configService;
31
- constructor(connection, configService) {
32
- this.connection = connection;
33
- this.configService = configService;
34
- }
35
- async resolve(ctx, csv) {
36
- const variantIdsBySku = new Map();
37
- const fields = new Set();
38
- // The importer reads the same lines and headers, so both agree on which columns hold SKUs
39
- // and on row numbers.
40
- const lines = (0, import_csv_lines_1.importCsvLines)(csv);
41
- const headers = (0, import_csv_lines_1.importCsvHeaders)(lines);
42
- const lookupHeaders = headers.filter((header) => this.splitHeader(header).length === 4);
43
- if (lookupHeaders.length === 0) {
44
- return { errors: [], variantIdsBySku, fields };
45
- }
46
- const headerErrors = lookupHeaders.flatMap((header) => this.checkHeader(header));
47
- if (headerErrors.length > 0) {
48
- return { errors: headerErrors, variantIdsBySku, fields };
49
- }
50
- const columns = lookupHeaders.map((header) => {
51
- const [owner, fieldName] = this.splitHeader(header);
52
- fields.add(`${owner}:${fieldName}`);
53
- return { index: headers.indexOf(header), list: this.findFieldConfig(header)?.list === true };
54
- });
55
- let rows;
56
- try {
57
- rows = this.readSkus(lines, columns);
58
- }
59
- catch (error) {
60
- return {
61
- errors: [`Could not read the file: ${error.message}`],
62
- variantIdsBySku,
63
- fields,
64
- };
65
- }
66
- const matches = await this.findLiveVariants(ctx, uniqueSkus(rows));
67
- const errors = [];
68
- for (const { line, skus } of rows) {
69
- for (const sku of skus) {
70
- const found = matches.get(sku) ?? [];
71
- if (found.length === 0) {
72
- errors.push(`Row ${line}: no variant with SKU ${sku}`);
73
- }
74
- else if (found.length > 1) {
75
- errors.push(`Row ${line}: SKU ${sku} matches ${found.length} variants`);
76
- }
77
- else {
78
- variantIdsBySku.set(sku, found[0]);
79
- }
80
- }
81
- }
82
- return { errors, variantIdsBySku, fields };
83
- }
84
- splitHeader(header) {
85
- if (!header.startsWith('product:') && !header.startsWith('variant:')) {
86
- return [];
87
- }
88
- return header.split(':');
89
- }
90
- checkHeader(header) {
91
- const lookup = this.splitHeader(header)[3];
92
- if (lookup !== exports.SKU_LOOKUP) {
93
- return [`Column '${header}': only ':${exports.SKU_LOOKUP}' is supported as a lookup`];
94
- }
95
- const config = this.findFieldConfig(header);
96
- if (!config) {
97
- const [owner, fieldName] = this.splitHeader(header);
98
- const entity = owner === 'product' ? 'Product' : 'ProductVariant';
99
- return [`Column '${header}': ${entity} has no custom field named '${fieldName}'`];
100
- }
101
- const isVariantRelation = config?.type === 'relation' && config.entity === core_1.ProductVariant;
102
- if (!isVariantRelation) {
103
- return [
104
- `Column '${header}': ':${exports.SKU_LOOKUP}' works only on relation custom fields to ProductVariant`,
105
- ];
106
- }
107
- return [];
108
- }
109
- findFieldConfig(header) {
110
- const [owner, fieldName] = this.splitHeader(header);
111
- const configs = owner === 'product'
112
- ? this.configService.customFields.Product
113
- : this.configService.customFields.ProductVariant;
114
- return configs.find((config) => config.name === fieldName);
115
- }
116
- /**
117
- * The SKUs each data row references, with the row's line as the importer numbers it: the
118
- * header is line 1 and blank and comma-only lines are not counted.
119
- */
120
- readSkus(lines, columns) {
121
- const [, ...records] = (0, sync_1.parse)(lines.join('\n'), {
122
- bom: true,
123
- // As lenient as the importer's parser, so a file it imports is never rejected here.
124
- relax_column_count: true,
125
- relax_quotes: true,
126
- });
127
- return records
128
- .map((record, index) => ({
129
- line: index + 2,
130
- skus: columns.flatMap(({ index: column, list }) => splitSkus(record[column], list)),
131
- }))
132
- .filter((row) => row.skus.length > 0);
133
- }
134
- async findLiveVariants(ctx, skus) {
135
- const matches = new Map();
136
- if (skus.length === 0) {
137
- return matches;
138
- }
139
- const repository = this.connection.getRepository(ctx, core_1.ProductVariant);
140
- const variants = [];
141
- for (let start = 0; start < skus.length; start += SKU_QUERY_CHUNK_SIZE) {
142
- const chunk = skus.slice(start, start + SKU_QUERY_CHUNK_SIZE);
143
- variants.push(...(await repository.find({
144
- select: ['id', 'sku'],
145
- where: { sku: (0, typeorm_1.In)(chunk), deletedAt: (0, typeorm_1.IsNull)() },
146
- })));
147
- }
148
- for (const variant of variants) {
149
- matches.set(variant.sku, [...(matches.get(variant.sku) ?? []), variant.id]);
150
- }
151
- return matches;
152
- }
153
- };
154
- exports.SkuRelationResolver = SkuRelationResolver;
155
- exports.SkuRelationResolver = SkuRelationResolver = __decorate([
156
- (0, common_1.Injectable)(),
157
- __metadata("design:paramtypes", [core_1.TransactionalConnection,
158
- core_1.ConfigService])
159
- ], SkuRelationResolver);
160
- /** The SKUs in a list relation cell, written `SKU|SKU`. */
161
- function splitSkuList(value) {
162
- return value
163
- .split('|')
164
- .map((sku) => sku.trim())
165
- .filter((sku) => sku !== '');
166
- }
167
- function splitSkus(value, list) {
168
- const trimmed = value?.trim() ?? '';
169
- if (trimmed === '') {
170
- return [];
171
- }
172
- return list ? splitSkuList(trimmed) : [trimmed];
173
- }
174
- function uniqueSkus(rows) {
175
- return [...new Set(rows.flatMap((row) => row.skus))];
176
- }
177
- //# sourceMappingURL=sku-relation-resolver.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sku-relation-resolver.js","sourceRoot":"","sources":["../../../../../packages/product-import-export-plugin/src/services/sku-relation-resolver.ts"],"names":[],"mappings":";;;;;;;;;;;;AAkLA,oCAKC;AAvLD,2CAA2C;AAC3C,wCAQsB;AACtB,yCAAsC;AACtC,qCAAoC;AACpC,kEAA8E;AAE9E,uFAAuF;AAC1E,QAAA,UAAU,GAAG,KAAK,CAAA;AAE/B,+EAA+E;AAC/E,MAAM,oBAAoB,GAAG,IAAI,CAAA;AAgBjC;;;;GAIG;AAEI,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAEpB;IACA;IAFV,YACU,UAAmC,EACnC,aAA4B;QAD5B,eAAU,GAAV,UAAU,CAAyB;QACnC,kBAAa,GAAb,aAAa,CAAe;IACnC,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,GAAmB,EAAE,GAAW;QAC5C,MAAM,eAAe,GAAG,IAAI,GAAG,EAAc,CAAA;QAC7C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAA;QAChC,0FAA0F;QAC1F,sBAAsB;QACtB,MAAM,KAAK,GAAG,IAAA,iCAAc,EAAC,GAAG,CAAC,CAAA;QACjC,MAAM,OAAO,GAAG,IAAA,mCAAgB,EAAC,KAAK,CAAC,CAAA;QACvC,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAA;QACvF,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,CAAA;QAChD,CAAC;QAED,MAAM,YAAY,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAA;QAChF,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,EAAE,CAAA;QAC1D,CAAC;QAED,MAAM,OAAO,GAAgB,aAAa,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;YACxD,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;YACnD,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,IAAI,SAAS,EAAE,CAAC,CAAA;YACnC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,IAAI,KAAK,IAAI,EAAE,CAAA;QAC9F,CAAC,CAAC,CAAA;QAEF,IAAI,IAA6C,CAAA;QACjD,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QACtC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,MAAM,EAAE,CAAC,4BAA6B,KAAe,CAAC,OAAO,EAAE,CAAC;gBAChE,eAAe;gBACf,MAAM;aACP,CAAA;QACH,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAA;QAClE,MAAM,MAAM,GAAa,EAAE,CAAA;QAC3B,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;YAClC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAA;gBACpC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACvB,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,yBAAyB,GAAG,EAAE,CAAC,CAAA;gBACxD,CAAC;qBAAM,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC5B,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,SAAS,GAAG,YAAY,KAAK,CAAC,MAAM,WAAW,CAAC,CAAA;gBACzE,CAAC;qBAAM,CAAC;oBACN,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;gBACpC,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,CAAA;IAC5C,CAAC;IAEO,WAAW,CAAC,MAAc;QAChC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YACrE,OAAO,EAAE,CAAA;QACX,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC1B,CAAC;IAEO,WAAW,CAAC,MAAc;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;QAC1C,IAAI,MAAM,KAAK,kBAAU,EAAE,CAAC;YAC1B,OAAO,CAAC,WAAW,MAAM,aAAa,kBAAU,4BAA4B,CAAC,CAAA;QAC/E,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAA;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;YACnD,MAAM,MAAM,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAA;YACjE,OAAO,CAAC,WAAW,MAAM,MAAM,MAAM,+BAA+B,SAAS,GAAG,CAAC,CAAA;QACnF,CAAC;QACD,MAAM,iBAAiB,GACrB,MAAM,EAAE,IAAI,KAAK,UAAU,IAAK,MAAoC,CAAC,MAAM,KAAK,qBAAc,CAAA;QAChG,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,OAAO;gBACL,WAAW,MAAM,QAAQ,kBAAU,0DAA0D;aAC9F,CAAA;QACH,CAAC;QACD,OAAO,EAAE,CAAA;IACX,CAAC;IAEO,eAAe,CAAC,MAAc;QACpC,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;QACnD,MAAM,OAAO,GACX,KAAK,KAAK,SAAS;YACjB,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,OAAO;YACzC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,cAAc,CAAA;QACpD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAA;IAC5D,CAAC;IAED;;;OAGG;IACK,QAAQ,CAAC,KAAe,EAAE,OAAoB;QACpD,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,IAAA,YAAK,EAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC7C,GAAG,EAAE,IAAI;YACT,oFAAoF;YACpF,kBAAkB,EAAE,IAAI;YACxB,YAAY,EAAE,IAAI;SACnB,CAAe,CAAA;QAEhB,OAAO,OAAO;aACX,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YACvB,IAAI,EAAE,KAAK,GAAG,CAAC;YACf,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;SACpF,CAAC,CAAC;aACF,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACzC,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,GAAmB,EAAE,IAAc;QAChE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAgB,CAAA;QACvC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,OAAO,CAAA;QAChB,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,GAAG,EAAE,qBAAc,CAAC,CAAA;QACrE,MAAM,QAAQ,GAAqB,EAAE,CAAA;QACrC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,oBAAoB,EAAE,CAAC;YACvE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,oBAAoB,CAAC,CAAA;YAC7D,QAAQ,CAAC,IAAI,CACX,GAAG,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC;gBACxB,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC;gBACrB,KAAK,EAAE,EAAE,GAAG,EAAE,IAAA,YAAE,EAAC,KAAK,CAAC,EAAE,SAAS,EAAE,IAAA,gBAAM,GAAE,EAAE;aAC/C,CAAC,CAAC,CACJ,CAAA;QACH,CAAC;QACD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAA;QAC7E,CAAC;QACD,OAAO,OAAO,CAAA;IAChB,CAAC;CACF,CAAA;AAvIY,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,mBAAU,GAAE;qCAGW,8BAAuB;QACpB,oBAAa;GAH3B,mBAAmB,CAuI/B;AAED,2DAA2D;AAC3D,SAAgB,YAAY,CAAC,KAAa;IACxC,OAAO,KAAK;SACT,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;SACxB,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,CAAA;AAChC,CAAC;AAED,SAAS,SAAS,CAAC,KAAyB,EAAE,IAAa;IACzD,MAAM,OAAO,GAAG,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;IACnC,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QACnB,OAAO,EAAE,CAAA;IACX,CAAC;IACD,OAAO,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;AACjD,CAAC;AAED,SAAS,UAAU,CAAC,IAA+B;IACjD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACtD,CAAC"}