@package-broker/core 0.11.0 → 0.12.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.
- package/dist/db/schema.d.ts +17 -0
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +2 -0
- package/dist/db/schema.js.map +1 -1
- package/dist/modules/packages/index.d.ts.map +1 -1
- package/dist/modules/packages/index.js +2 -0
- package/dist/modules/packages/index.js.map +1 -1
- package/dist/modules/packages/packages.handlers.d.ts +17 -0
- package/dist/modules/packages/packages.handlers.d.ts.map +1 -1
- package/dist/modules/packages/packages.handlers.js +303 -0
- package/dist/modules/packages/packages.handlers.js.map +1 -1
- package/dist/modules/packages/packages.routes.d.ts +127 -0
- package/dist/modules/packages/packages.routes.d.ts.map +1 -1
- package/dist/modules/packages/packages.routes.js +121 -0
- package/dist/modules/packages/packages.routes.js.map +1 -1
- package/dist/routes/composer.d.ts.map +1 -1
- package/dist/routes/composer.js +6 -2
- package/dist/routes/composer.js.map +1 -1
- package/dist/sync/strategies/composer-repo.js +7 -4
- package/dist/sync/strategies/composer-repo.js.map +1 -1
- package/dist/utils/package-validator.d.ts +77 -0
- package/dist/utils/package-validator.d.ts.map +1 -0
- package/dist/utils/package-validator.js +217 -0
- package/dist/utils/package-validator.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composer package metadata structure
|
|
3
|
+
* Based on https://getcomposer.org/doc/04-schema.md
|
|
4
|
+
*/
|
|
5
|
+
export interface ComposerMetadata {
|
|
6
|
+
name: string;
|
|
7
|
+
version: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
license?: string | string[];
|
|
10
|
+
type?: string;
|
|
11
|
+
homepage?: string;
|
|
12
|
+
readme?: string;
|
|
13
|
+
time?: string;
|
|
14
|
+
authors?: Array<{
|
|
15
|
+
name?: string;
|
|
16
|
+
email?: string;
|
|
17
|
+
homepage?: string;
|
|
18
|
+
role?: string;
|
|
19
|
+
}>;
|
|
20
|
+
support?: {
|
|
21
|
+
email?: string;
|
|
22
|
+
issues?: string;
|
|
23
|
+
forum?: string;
|
|
24
|
+
wiki?: string;
|
|
25
|
+
irc?: string;
|
|
26
|
+
source?: string;
|
|
27
|
+
docs?: string;
|
|
28
|
+
rss?: string;
|
|
29
|
+
};
|
|
30
|
+
require?: Record<string, string>;
|
|
31
|
+
'require-dev'?: Record<string, string>;
|
|
32
|
+
conflict?: Record<string, string>;
|
|
33
|
+
replace?: Record<string, string>;
|
|
34
|
+
provide?: Record<string, string>;
|
|
35
|
+
suggest?: Record<string, string>;
|
|
36
|
+
autoload?: {
|
|
37
|
+
'psr-0'?: Record<string, string | string[]>;
|
|
38
|
+
'psr-4'?: Record<string, string | string[]>;
|
|
39
|
+
classmap?: string[];
|
|
40
|
+
files?: string[];
|
|
41
|
+
};
|
|
42
|
+
'autoload-dev'?: {
|
|
43
|
+
'psr-0'?: Record<string, string | string[]>;
|
|
44
|
+
'psr-4'?: Record<string, string | string[]>;
|
|
45
|
+
classmap?: string[];
|
|
46
|
+
files?: string[];
|
|
47
|
+
};
|
|
48
|
+
bin?: string[];
|
|
49
|
+
extra?: Record<string, any>;
|
|
50
|
+
[key: string]: any;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Validation result for package archives
|
|
54
|
+
*/
|
|
55
|
+
export interface ValidationResult {
|
|
56
|
+
success: boolean;
|
|
57
|
+
metadata?: ComposerMetadata;
|
|
58
|
+
errors?: string[];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Validate a package archive and extract composer.json metadata
|
|
62
|
+
*
|
|
63
|
+
* Performance optimized for Cloudflare Workers:
|
|
64
|
+
* - Limits composer.json search to first 100 files (avoid DoS)
|
|
65
|
+
* - Limits composer.json size to 1MB (avoid memory exhaustion)
|
|
66
|
+
* - Uses synchronous unzip (faster for small files)
|
|
67
|
+
*
|
|
68
|
+
* @param archiveData - Zip archive as Uint8Array
|
|
69
|
+
* @returns Validation result with metadata or errors
|
|
70
|
+
*/
|
|
71
|
+
export declare function validatePackageArchive(archiveData: Uint8Array): Promise<ValidationResult>;
|
|
72
|
+
/**
|
|
73
|
+
* Extract README.md from package archive (reused from existing code)
|
|
74
|
+
* Performance: Only extracts README if found in first 50 files
|
|
75
|
+
*/
|
|
76
|
+
export declare function extractReadme(zipData: Uint8Array): string | null;
|
|
77
|
+
//# sourceMappingURL=package-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-validator.d.ts","sourceRoot":"","sources":["../../src/utils/package-validator.ts"],"names":[],"mappings":"AAQA;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,KAAK,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;IACH,OAAO,CAAC,EAAE;QACR,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,CAAC,EAAE;QACT,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;QAC5C,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;IACF,cAAc,CAAC,EAAE;QACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;QAC5C,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;IACF,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,UAAU,GACtB,OAAO,CAAC,gBAAgB,CAAC,CAiL3B;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAuChE"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* PACKAGE.broker
|
|
3
|
+
* Copyright (C) 2025 Łukasz Bajsarowicz
|
|
4
|
+
* Licensed under AGPL-3.0
|
|
5
|
+
*/
|
|
6
|
+
import { unzipSync, strFromU8 } from 'fflate';
|
|
7
|
+
/**
|
|
8
|
+
* Validate a package archive and extract composer.json metadata
|
|
9
|
+
*
|
|
10
|
+
* Performance optimized for Cloudflare Workers:
|
|
11
|
+
* - Limits composer.json search to first 100 files (avoid DoS)
|
|
12
|
+
* - Limits composer.json size to 1MB (avoid memory exhaustion)
|
|
13
|
+
* - Uses synchronous unzip (faster for small files)
|
|
14
|
+
*
|
|
15
|
+
* @param archiveData - Zip archive as Uint8Array
|
|
16
|
+
* @returns Validation result with metadata or errors
|
|
17
|
+
*/
|
|
18
|
+
export async function validatePackageArchive(archiveData) {
|
|
19
|
+
const errors = [];
|
|
20
|
+
// Basic validation
|
|
21
|
+
if (!archiveData || archiveData.length === 0) {
|
|
22
|
+
return {
|
|
23
|
+
success: false,
|
|
24
|
+
errors: ['Archive is empty or invalid'],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
// Check if file is too large (max 100MB to avoid memory issues)
|
|
28
|
+
const MAX_ARCHIVE_SIZE = 100 * 1024 * 1024; // 100MB
|
|
29
|
+
if (archiveData.length > MAX_ARCHIVE_SIZE) {
|
|
30
|
+
return {
|
|
31
|
+
success: false,
|
|
32
|
+
errors: [`Archive too large: ${Math.round(archiveData.length / 1024 / 1024)}MB (max 100MB)`],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
// Check if it's a valid ZIP file (magic bytes: 50 4B 03 04 or 50 4B 05 06)
|
|
36
|
+
if (archiveData.length < 4) {
|
|
37
|
+
return {
|
|
38
|
+
success: false,
|
|
39
|
+
errors: ['File too small to be a valid ZIP archive'],
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const magic = archiveData[0] === 0x50 && archiveData[1] === 0x4B;
|
|
43
|
+
if (!magic) {
|
|
44
|
+
return {
|
|
45
|
+
success: false,
|
|
46
|
+
errors: ['Invalid ZIP archive format (only .zip files are supported)'],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// Extract files from ZIP
|
|
50
|
+
let files;
|
|
51
|
+
try {
|
|
52
|
+
files = unzipSync(archiveData);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
console.error(`[package-validator] Failed to extract ZIP:`, error);
|
|
56
|
+
return {
|
|
57
|
+
success: false,
|
|
58
|
+
errors: [`Failed to extract ZIP archive: ${error instanceof Error ? error.message : 'Unknown error'}`],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// Find composer.json file using direct path lookup (much faster than iteration)
|
|
62
|
+
// This approach finds composer.json regardless of how many files are in the archive
|
|
63
|
+
const allPaths = Object.keys(files);
|
|
64
|
+
console.log(`[package-validator] Archive contains ${allPaths.length} files`);
|
|
65
|
+
// Find all composer.json files in the archive (case-insensitive)
|
|
66
|
+
const composerJsonPaths = allPaths.filter(p => {
|
|
67
|
+
const pathLower = p.toLowerCase();
|
|
68
|
+
// Match: composer.json, */composer.json, or */*/composer.json
|
|
69
|
+
return pathLower === 'composer.json' ||
|
|
70
|
+
/^[^/]+\/composer\.json$/.test(pathLower) ||
|
|
71
|
+
/^[^/]+\/[^/]+\/composer\.json$/.test(pathLower);
|
|
72
|
+
});
|
|
73
|
+
console.log(`[package-validator] Found ${composerJsonPaths.length} composer.json file(s):`, composerJsonPaths);
|
|
74
|
+
if (composerJsonPaths.length === 0) {
|
|
75
|
+
// Debug: show first 20 paths to help troubleshoot
|
|
76
|
+
console.log(`[package-validator] First 20 paths in archive:`, allPaths.slice(0, 20));
|
|
77
|
+
// Also check if there's a composer.json at any depth (for better error message)
|
|
78
|
+
const deepComposerPaths = allPaths.filter(p => p.toLowerCase().endsWith('/composer.json') || p.toLowerCase() === 'composer.json');
|
|
79
|
+
if (deepComposerPaths.length > 0) {
|
|
80
|
+
console.log(`[package-validator] Found composer.json at unsupported depth:`, deepComposerPaths);
|
|
81
|
+
return {
|
|
82
|
+
success: false,
|
|
83
|
+
errors: [`composer.json found but too deep in directory structure: ${deepComposerPaths[0]} (max 2 levels)`],
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
success: false,
|
|
88
|
+
errors: [`composer.json not found in archive (${allPaths.length} files, searched root and up to 2 levels deep)`],
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
// Sort by depth (prefer shallower paths) and pick the first one
|
|
92
|
+
// Depth 0: composer.json, Depth 1: dir/composer.json, Depth 2: dir/subdir/composer.json
|
|
93
|
+
const sortedPaths = composerJsonPaths.sort((a, b) => {
|
|
94
|
+
const depthA = (a.match(/\//g) || []).length;
|
|
95
|
+
const depthB = (b.match(/\//g) || []).length;
|
|
96
|
+
return depthA - depthB;
|
|
97
|
+
});
|
|
98
|
+
const composerJsonPath = sortedPaths[0];
|
|
99
|
+
const content = files[composerJsonPath];
|
|
100
|
+
console.log(`[package-validator] Using composer.json at: ${composerJsonPath}`);
|
|
101
|
+
// Check file size (max 1MB for composer.json)
|
|
102
|
+
const MAX_COMPOSER_JSON_SIZE = 1024 * 1024; // 1MB
|
|
103
|
+
if (content.length > MAX_COMPOSER_JSON_SIZE) {
|
|
104
|
+
return {
|
|
105
|
+
success: false,
|
|
106
|
+
errors: [`composer.json too large: ${Math.round(content.length / 1024)}KB (max 1MB)`],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
let composerJsonContent;
|
|
110
|
+
try {
|
|
111
|
+
composerJsonContent = strFromU8(content);
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
return {
|
|
115
|
+
success: false,
|
|
116
|
+
errors: [`Failed to read ${composerJsonPath}: ${error instanceof Error ? error.message : 'Unknown error'}`],
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
// Parse composer.json
|
|
120
|
+
let metadata;
|
|
121
|
+
try {
|
|
122
|
+
metadata = JSON.parse(composerJsonContent);
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
return {
|
|
126
|
+
success: false,
|
|
127
|
+
errors: [`Invalid JSON in ${composerJsonPath}: ${error instanceof Error ? error.message : 'Parse error'}`],
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
// Validate required fields
|
|
131
|
+
if (!metadata.name) {
|
|
132
|
+
errors.push('Missing required field: "name"');
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
// Validate name format (vendor/package)
|
|
136
|
+
// Using a simpler, non-backtracking pattern to avoid ReDoS vulnerability
|
|
137
|
+
// Matches: starts with alphanumeric, followed by alphanumerics/underscores/dots/dashes
|
|
138
|
+
const namePattern = /^[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$/i;
|
|
139
|
+
if (!namePattern.test(metadata.name)) {
|
|
140
|
+
errors.push(`Invalid package name format: "${metadata.name}" (must be vendor/package)`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (!metadata.version) {
|
|
144
|
+
errors.push('Missing required field: "version"');
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
// Validate version format (loose semantic versioning check)
|
|
148
|
+
const versionPattern = /^v?(\d+)(\.\d+)?(\.\d+)?(\.\d+)?([.-]?(alpha|beta|rc|dev|patch|pl|p)\.?\d*)?$/i;
|
|
149
|
+
if (!versionPattern.test(metadata.version)) {
|
|
150
|
+
errors.push(`Invalid version format: "${metadata.version}" (must follow semantic versioning)`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Optional: Validate type field if present
|
|
154
|
+
if (metadata.type) {
|
|
155
|
+
const validTypes = [
|
|
156
|
+
'library', 'project', 'metapackage', 'composer-plugin',
|
|
157
|
+
'magento2-module', 'magento2-theme', 'magento2-language',
|
|
158
|
+
'wordpress-plugin', 'wordpress-theme', 'symfony-bundle',
|
|
159
|
+
'drupal-module', 'drupal-theme',
|
|
160
|
+
];
|
|
161
|
+
// Allow other types but warn if not in common list
|
|
162
|
+
if (!validTypes.includes(metadata.type) && !metadata.type.match(/^(magento|wordpress|drupal|symfony|laravel|typo3)-/)) {
|
|
163
|
+
// This is just informational, not a validation error
|
|
164
|
+
console.log(`Non-standard package type: "${metadata.type}"`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (errors.length > 0) {
|
|
168
|
+
return {
|
|
169
|
+
success: false,
|
|
170
|
+
errors,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
success: true,
|
|
175
|
+
metadata,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Extract README.md from package archive (reused from existing code)
|
|
180
|
+
* Performance: Only extracts README if found in first 50 files
|
|
181
|
+
*/
|
|
182
|
+
export function extractReadme(zipData) {
|
|
183
|
+
try {
|
|
184
|
+
const files = unzipSync(zipData);
|
|
185
|
+
const readmeNames = [
|
|
186
|
+
'README.md', 'readme.md', 'README.MD', 'Readme.md',
|
|
187
|
+
'README.mdown', 'readme.mdown', 'README.MDOWN', 'Readme.mdown',
|
|
188
|
+
'README', 'readme', 'README.txt', 'readme.txt',
|
|
189
|
+
];
|
|
190
|
+
let filesChecked = 0;
|
|
191
|
+
const MAX_FILES_TO_CHECK = 50;
|
|
192
|
+
// Look for README in root or first-level directory
|
|
193
|
+
for (const [path, content] of Object.entries(files)) {
|
|
194
|
+
filesChecked++;
|
|
195
|
+
if (filesChecked > MAX_FILES_TO_CHECK) {
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
const filename = path.split('/').pop() || '';
|
|
199
|
+
const filenameLower = filename.toLowerCase();
|
|
200
|
+
// Prefer .md files
|
|
201
|
+
if (readmeNames.slice(0, 8).some(name => filenameLower === name.toLowerCase())) {
|
|
202
|
+
// Limit README size to 500KB
|
|
203
|
+
if (content.length > 500 * 1024) {
|
|
204
|
+
console.warn(`README too large: ${path} (${content.length} bytes)`);
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
return strFromU8(content);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
console.error('Error extracting README from ZIP:', error);
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=package-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-validator.js","sourceRoot":"","sources":["../../src/utils/package-validator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AA+D9C;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,WAAuB;IAEvB,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,mBAAmB;IACnB,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7C,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,CAAC,6BAA6B,CAAC;SACxC,CAAC;IACJ,CAAC;IAED,gEAAgE;IAChE,MAAM,gBAAgB,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,QAAQ;IACpD,IAAI,WAAW,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;QAC1C,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,CAAC,sBAAsB,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC;SAC7F,CAAC;IACJ,CAAC;IAED,2EAA2E;IAC3E,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,CAAC,0CAA0C,CAAC;SACrD,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IACjE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,CAAC,4DAA4D,CAAC;SACvE,CAAC;IACJ,CAAC;IAED,yBAAyB;IACzB,IAAI,KAAiC,CAAC;IACtC,IAAI,CAAC;QACH,KAAK,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,4CAA4C,EAAE,KAAK,CAAC,CAAC;QACnE,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,CAAC,kCAAkC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC;SACvG,CAAC;IACJ,CAAC;IAED,gFAAgF;IAChF,oFAAoF;IACpF,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,wCAAwC,QAAQ,CAAC,MAAM,QAAQ,CAAC,CAAC;IAE7E,iEAAiE;IACjE,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;QAC5C,MAAM,SAAS,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QAClC,8DAA8D;QAC9D,OAAO,SAAS,KAAK,eAAe;YAC7B,yBAAyB,CAAC,IAAI,CAAC,SAAS,CAAC;YACzC,gCAAgC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,6BAA6B,iBAAiB,CAAC,MAAM,yBAAyB,EAAE,iBAAiB,CAAC,CAAC;IAE/G,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,kDAAkD;QAClD,OAAO,CAAC,GAAG,CAAC,gDAAgD,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAErF,gFAAgF;QAChF,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,eAAe,CAAC,CAAC;QAClI,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,+DAA+D,EAAE,iBAAiB,CAAC,CAAC;YAChG,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,CAAC,4DAA4D,iBAAiB,CAAC,CAAC,CAAC,iBAAiB,CAAC;aAC5G,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,CAAC,uCAAuC,QAAQ,CAAC,MAAM,gDAAgD,CAAC;SACjH,CAAC;IACJ,CAAC;IAED,gEAAgE;IAChE,wFAAwF;IACxF,MAAM,WAAW,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAClD,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;QAC7C,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;QAC7C,OAAO,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,MAAM,gBAAgB,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAExC,OAAO,CAAC,GAAG,CAAC,+CAA+C,gBAAgB,EAAE,CAAC,CAAC;IAE/E,8CAA8C;IAC9C,MAAM,sBAAsB,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,MAAM;IAClD,IAAI,OAAO,CAAC,MAAM,GAAG,sBAAsB,EAAE,CAAC;QAC5C,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,CAAC,4BAA4B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC;SACtF,CAAC;IACJ,CAAC;IAED,IAAI,mBAA2B,CAAC;IAChC,IAAI,CAAC;QACH,mBAAmB,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,CAAC,kBAAkB,gBAAgB,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC;SAC5G,CAAC;IACJ,CAAC;IAED,sBAAsB;IACtB,IAAI,QAA0B,CAAC;IAC/B,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,CAAC,mBAAmB,gBAAgB,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;SAC3G,CAAC;IACJ,CAAC;IAED,2BAA2B;IAC3B,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnB,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IAChD,CAAC;SAAM,CAAC;QACN,wCAAwC;QACxC,yEAAyE;QACzE,uFAAuF;QACvF,MAAM,WAAW,GAAG,+CAA+C,CAAC;QACpE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACrC,MAAM,CAAC,IAAI,CAAC,iCAAiC,QAAQ,CAAC,IAAI,4BAA4B,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IACnD,CAAC;SAAM,CAAC;QACN,4DAA4D;QAC5D,MAAM,cAAc,GAAG,gFAAgF,CAAC;QACxG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,4BAA4B,QAAQ,CAAC,OAAO,qCAAqC,CAAC,CAAC;QACjG,CAAC;IACH,CAAC;IAED,2CAA2C;IAC3C,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;QAClB,MAAM,UAAU,GAAG;YACjB,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,iBAAiB;YACtD,iBAAiB,EAAE,gBAAgB,EAAE,mBAAmB;YACxD,kBAAkB,EAAE,iBAAiB,EAAE,gBAAgB;YACvD,eAAe,EAAE,cAAc;SAChC,CAAC;QAEF,mDAAmD;QACnD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,oDAAoD,CAAC,EAAE,CAAC;YACtH,qDAAqD;YACrD,OAAO,CAAC,GAAG,CAAC,+BAA+B,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM;SACP,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI;QACb,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,OAAmB;IAC/C,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAEjC,MAAM,WAAW,GAAG;YAClB,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW;YAClD,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc;YAC9D,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY;SAC/C,CAAC;QAEF,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,MAAM,kBAAkB,GAAG,EAAE,CAAC;QAE9B,mDAAmD;QACnD,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACpD,YAAY,EAAE,CAAC;YACf,IAAI,YAAY,GAAG,kBAAkB,EAAE,CAAC;gBACtC,MAAM;YACR,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YAC7C,MAAM,aAAa,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;YAE7C,mBAAmB;YACnB,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;gBAC/E,6BAA6B;gBAC7B,IAAI,OAAO,CAAC,MAAM,GAAG,GAAG,GAAG,IAAI,EAAE,CAAC;oBAChC,OAAO,CAAC,IAAI,CAAC,qBAAqB,IAAI,KAAK,OAAO,CAAC,MAAM,SAAS,CAAC,CAAC;oBACpE,SAAS;gBACX,CAAC;gBACD,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|