@chanomhub/sdk 1.3.12 → 1.3.13
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.
|
@@ -17,6 +17,22 @@ export interface UploadResponse {
|
|
|
17
17
|
/** Storage bucket used */
|
|
18
18
|
bucket: string;
|
|
19
19
|
}
|
|
20
|
+
/** Multipart upload initiation response */
|
|
21
|
+
export interface InitiateMultipartResponse {
|
|
22
|
+
uploadId: string;
|
|
23
|
+
key: string;
|
|
24
|
+
bucket: string;
|
|
25
|
+
isVideo: boolean;
|
|
26
|
+
}
|
|
27
|
+
/** Multipart upload part response */
|
|
28
|
+
export interface UploadPartResponse {
|
|
29
|
+
etag: string;
|
|
30
|
+
}
|
|
31
|
+
/** Completed part for multipart upload */
|
|
32
|
+
export interface CompletedPart {
|
|
33
|
+
partNumber: number;
|
|
34
|
+
etag: string;
|
|
35
|
+
}
|
|
20
36
|
export interface UploadOptions {
|
|
21
37
|
/**
|
|
22
38
|
* Target bucket.
|
|
@@ -36,15 +52,42 @@ export interface UploadOptions {
|
|
|
36
52
|
game?: string;
|
|
37
53
|
/** Progress callback (browser only) */
|
|
38
54
|
onProgress?: (percent: number) => void;
|
|
55
|
+
/** Chunk size for multipart upload (default 5MB) */
|
|
56
|
+
chunkSize?: number;
|
|
57
|
+
/** Number of concurrent chunk uploads (default 3) */
|
|
58
|
+
concurrentUploads?: number;
|
|
39
59
|
}
|
|
40
60
|
export interface StorageRepository {
|
|
41
61
|
/**
|
|
42
|
-
* Upload a file to the storage service
|
|
62
|
+
* Upload a file to the storage service (Simple upload, <100MB recommended)
|
|
43
63
|
* @param file - File or Blob to upload
|
|
44
64
|
* @param options - Upload options (bucket, path, progress callback)
|
|
45
65
|
* @returns Upload response with URL and metadata
|
|
46
66
|
*/
|
|
47
67
|
upload(file: File | Blob, options?: UploadOptions): Promise<UploadResponse>;
|
|
68
|
+
/**
|
|
69
|
+
* High-level multipart upload (Recommended for files >100MB)
|
|
70
|
+
* @param file - File or Blob to upload
|
|
71
|
+
* @param options - Upload options (bucket, path, chunkSize, progress callback)
|
|
72
|
+
* @returns Upload response with URL and metadata
|
|
73
|
+
*/
|
|
74
|
+
uploadMultipart(file: File | Blob, options?: UploadOptions): Promise<UploadResponse>;
|
|
75
|
+
/**
|
|
76
|
+
* Initiate a multipart upload
|
|
77
|
+
*/
|
|
78
|
+
initiateMultipartUpload(filename: string, contentType: string, options?: UploadOptions): Promise<InitiateMultipartResponse>;
|
|
79
|
+
/**
|
|
80
|
+
* Upload a single part of a multipart upload
|
|
81
|
+
*/
|
|
82
|
+
uploadPart(partData: Blob | ArrayBuffer, partNumber: number, initiateData: InitiateMultipartResponse, options?: UploadOptions): Promise<UploadPartResponse>;
|
|
83
|
+
/**
|
|
84
|
+
* Complete a multipart upload
|
|
85
|
+
*/
|
|
86
|
+
completeMultipartUpload(initiateData: InitiateMultipartResponse, parts: CompletedPart[], options?: UploadOptions): Promise<UploadResponse>;
|
|
87
|
+
/**
|
|
88
|
+
* Abort a multipart upload
|
|
89
|
+
*/
|
|
90
|
+
abortMultipartUpload(initiateData: InitiateMultipartResponse, options?: UploadOptions): Promise<void>;
|
|
48
91
|
/**
|
|
49
92
|
* Construct a protected download URL for premium content
|
|
50
93
|
* @param path - File path (e.g. 'premium/hash.zip')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storageRepository.d.ts","sourceRoot":"","sources":["../../repositories/storageRepository.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGjD,2CAA2C;AAC3C,MAAM,WAAW,cAAc;IAC3B,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC1B;;;;OAIG;IACH,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC9B;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"storageRepository.d.ts","sourceRoot":"","sources":["../../repositories/storageRepository.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGjD,2CAA2C;AAC3C,MAAM,WAAW,cAAc;IAC3B,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,2CAA2C;AAC3C,MAAM,WAAW,yBAAyB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CACpB;AAED,qCAAqC;AACrC,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,0CAA0C;AAC1C,MAAM,WAAW,aAAa;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC1B;;;;OAIG;IACH,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC9B;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAC9B;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAE5E;;;;;OAKG;IACH,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAErF;;OAEG;IACH,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAE5H;;OAEG;IACH,UAAU,CACN,QAAQ,EAAE,IAAI,GAAG,WAAW,EAC5B,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,yBAAyB,EACvC,OAAO,CAAC,EAAE,aAAa,GACxB,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAE/B;;OAEG;IACH,uBAAuB,CACnB,YAAY,EAAE,yBAAyB,EACvC,KAAK,EAAE,aAAa,EAAE,EACtB,OAAO,CAAC,EAAE,aAAa,GACxB,OAAO,CAAC,cAAc,CAAC,CAAC;IAE3B;;OAEG;IACH,oBAAoB,CAAC,YAAY,EAAE,yBAAyB,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtG;;;;;OAKG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CACtE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,eAAe,GAAG,iBAAiB,CAqQlF"}
|
|
@@ -14,45 +14,179 @@ function createStorageRepository(config) {
|
|
|
14
14
|
throw new errors_1.AuthenticationError('Authentication required for storage operations. Use createAuthenticatedClient() or provide a token.');
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
+
function getAuthHeaders() {
|
|
18
|
+
return {
|
|
19
|
+
'Authorization': `Bearer Bearer ${config.token}`,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
17
22
|
async function upload(file, options = {}) {
|
|
18
23
|
requireAuth();
|
|
19
24
|
const { bucket = 'images', path, game } = options;
|
|
20
25
|
const storageUrl = config.storageServiceUrl || 'https://oi.chanomhub.com';
|
|
21
26
|
const formData = new FormData();
|
|
22
|
-
|
|
27
|
+
// GOR2 expects 'image' or 'file' key
|
|
28
|
+
const fieldName = (file instanceof File && file.type.startsWith('image/')) ? 'image' : 'file';
|
|
29
|
+
formData.append(fieldName, file);
|
|
23
30
|
const url = new URL(`${storageUrl}/upload`);
|
|
24
|
-
if (bucket)
|
|
31
|
+
if (bucket)
|
|
25
32
|
url.searchParams.append('bucket', bucket);
|
|
26
|
-
|
|
27
|
-
if (path) {
|
|
33
|
+
if (path)
|
|
28
34
|
url.searchParams.append('path', path);
|
|
29
|
-
|
|
30
|
-
if (game) {
|
|
35
|
+
if (game)
|
|
31
36
|
url.searchParams.append('game', game);
|
|
32
|
-
}
|
|
33
|
-
const headers = {
|
|
34
|
-
// NOTE: We use double prefix to match GOR2 middleware expectations: Bearer Bearer {token}
|
|
35
|
-
// This is for compatibility with existing client behavior
|
|
36
|
-
'Authorization': `Bearer Bearer ${config.token}`,
|
|
37
|
-
};
|
|
38
37
|
try {
|
|
39
38
|
const response = await fetch(url.toString(), {
|
|
40
39
|
method: 'POST',
|
|
41
|
-
headers,
|
|
40
|
+
headers: getAuthHeaders(),
|
|
42
41
|
body: formData,
|
|
43
42
|
});
|
|
44
43
|
if (!response.ok) {
|
|
45
44
|
const errorData = await response.json().catch(() => ({}));
|
|
46
|
-
throw new Error(errorData.message || `Upload failed with status ${response.status}`);
|
|
45
|
+
throw new Error(errorData.error || errorData.message || `Upload failed with status ${response.status}`);
|
|
47
46
|
}
|
|
48
|
-
|
|
49
|
-
return data;
|
|
47
|
+
return await response.json();
|
|
50
48
|
}
|
|
51
49
|
catch (error) {
|
|
52
50
|
console.error('Storage upload error:', error);
|
|
53
51
|
throw error;
|
|
54
52
|
}
|
|
55
53
|
}
|
|
54
|
+
async function initiateMultipartUpload(filename, contentType, options = {}) {
|
|
55
|
+
requireAuth();
|
|
56
|
+
const { bucket = 'storage', path, game } = options;
|
|
57
|
+
const storageUrl = config.storageServiceUrl || 'https://oi.chanomhub.com';
|
|
58
|
+
const url = new URL(`${storageUrl}/upload/initiate`);
|
|
59
|
+
url.searchParams.append('filename', filename);
|
|
60
|
+
url.searchParams.append('contentType', contentType);
|
|
61
|
+
if (bucket)
|
|
62
|
+
url.searchParams.append('bucket', bucket);
|
|
63
|
+
if (path)
|
|
64
|
+
url.searchParams.append('path', path);
|
|
65
|
+
if (game)
|
|
66
|
+
url.searchParams.append('game', game);
|
|
67
|
+
const response = await fetch(url.toString(), {
|
|
68
|
+
method: 'POST',
|
|
69
|
+
headers: getAuthHeaders(),
|
|
70
|
+
});
|
|
71
|
+
if (!response.ok) {
|
|
72
|
+
const errorData = await response.json().catch(() => ({}));
|
|
73
|
+
throw new Error(errorData.error || `Failed to initiate multipart upload: ${response.status}`);
|
|
74
|
+
}
|
|
75
|
+
return await response.json();
|
|
76
|
+
}
|
|
77
|
+
async function uploadPart(partData, partNumber, initiateData, options = {}) {
|
|
78
|
+
requireAuth();
|
|
79
|
+
const storageUrl = config.storageServiceUrl || 'https://oi.chanomhub.com';
|
|
80
|
+
const { bucket: bucketType = 'storage' } = options;
|
|
81
|
+
const url = new URL(`${storageUrl}/upload/part`);
|
|
82
|
+
url.searchParams.append('uploadId', initiateData.uploadId);
|
|
83
|
+
url.searchParams.append('key', initiateData.key);
|
|
84
|
+
url.searchParams.append('bucket', initiateData.bucket);
|
|
85
|
+
url.searchParams.append('partNumber', partNumber.toString());
|
|
86
|
+
url.searchParams.append('isVideo', initiateData.isVideo.toString());
|
|
87
|
+
url.searchParams.append('bucketType', bucketType);
|
|
88
|
+
const response = await fetch(url.toString(), {
|
|
89
|
+
method: 'POST',
|
|
90
|
+
headers: {
|
|
91
|
+
...getAuthHeaders(),
|
|
92
|
+
'Content-Type': 'application/octet-stream',
|
|
93
|
+
},
|
|
94
|
+
body: partData,
|
|
95
|
+
});
|
|
96
|
+
if (!response.ok) {
|
|
97
|
+
const errorData = await response.json().catch(() => ({}));
|
|
98
|
+
throw new Error(errorData.error || `Failed to upload part ${partNumber}: ${response.status}`);
|
|
99
|
+
}
|
|
100
|
+
return await response.json();
|
|
101
|
+
}
|
|
102
|
+
async function completeMultipartUpload(initiateData, parts, options = {}) {
|
|
103
|
+
requireAuth();
|
|
104
|
+
const storageUrl = config.storageServiceUrl || 'https://oi.chanomhub.com';
|
|
105
|
+
const { bucket: bucketType = 'storage' } = options;
|
|
106
|
+
const url = new URL(`${storageUrl}/upload/complete`);
|
|
107
|
+
const response = await fetch(url.toString(), {
|
|
108
|
+
method: 'POST',
|
|
109
|
+
headers: {
|
|
110
|
+
...getAuthHeaders(),
|
|
111
|
+
'Content-Type': 'application/json',
|
|
112
|
+
},
|
|
113
|
+
body: JSON.stringify({
|
|
114
|
+
uploadId: initiateData.uploadId,
|
|
115
|
+
key: initiateData.key,
|
|
116
|
+
bucket: initiateData.bucket,
|
|
117
|
+
parts,
|
|
118
|
+
isVideo: initiateData.isVideo,
|
|
119
|
+
bucketType,
|
|
120
|
+
}),
|
|
121
|
+
});
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
const errorData = await response.json().catch(() => ({}));
|
|
124
|
+
throw new Error(errorData.error || `Failed to complete multipart upload: ${response.status}`);
|
|
125
|
+
}
|
|
126
|
+
return await response.json();
|
|
127
|
+
}
|
|
128
|
+
async function abortMultipartUpload(initiateData, options = {}) {
|
|
129
|
+
requireAuth();
|
|
130
|
+
const storageUrl = config.storageServiceUrl || 'https://oi.chanomhub.com';
|
|
131
|
+
const { bucket: bucketType = 'storage' } = options;
|
|
132
|
+
const url = new URL(`${storageUrl}/upload/abort`);
|
|
133
|
+
url.searchParams.append('uploadId', initiateData.uploadId);
|
|
134
|
+
url.searchParams.append('key', initiateData.key);
|
|
135
|
+
url.searchParams.append('bucket', initiateData.bucket);
|
|
136
|
+
url.searchParams.append('isVideo', initiateData.isVideo.toString());
|
|
137
|
+
url.searchParams.append('bucketType', bucketType);
|
|
138
|
+
const response = await fetch(url.toString(), {
|
|
139
|
+
method: 'POST',
|
|
140
|
+
headers: getAuthHeaders(),
|
|
141
|
+
});
|
|
142
|
+
if (!response.ok) {
|
|
143
|
+
const errorData = await response.json().catch(() => ({}));
|
|
144
|
+
throw new Error(errorData.error || `Failed to abort multipart upload: ${response.status}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async function uploadMultipart(file, options = {}) {
|
|
148
|
+
const { chunkSize = 5 * 1024 * 1024, // 5MB default chunk size
|
|
149
|
+
onProgress, concurrentUploads = 3 } = options;
|
|
150
|
+
const filename = file.name || 'blob';
|
|
151
|
+
const contentType = file.type || 'application/octet-stream';
|
|
152
|
+
// 1. Initiate
|
|
153
|
+
const initiateData = await initiateMultipartUpload(filename, contentType, options);
|
|
154
|
+
try {
|
|
155
|
+
const totalChunks = Math.ceil(file.size / chunkSize);
|
|
156
|
+
const completedParts = [];
|
|
157
|
+
let uploadedBytes = 0;
|
|
158
|
+
// Simple worker-pool approach for concurrent uploads
|
|
159
|
+
const uploadChunk = async (chunkIndex) => {
|
|
160
|
+
const start = chunkIndex * chunkSize;
|
|
161
|
+
const end = Math.min(start + chunkSize, file.size);
|
|
162
|
+
const chunk = file.slice(start, end);
|
|
163
|
+
const partNumber = chunkIndex + 1;
|
|
164
|
+
const { etag } = await uploadPart(chunk, partNumber, initiateData, options);
|
|
165
|
+
completedParts.push({ partNumber, etag });
|
|
166
|
+
uploadedBytes += (end - start);
|
|
167
|
+
if (onProgress) {
|
|
168
|
+
onProgress(Math.round((uploadedBytes / file.size) * 100));
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
// Process chunks in batches
|
|
172
|
+
for (let i = 0; i < totalChunks; i += concurrentUploads) {
|
|
173
|
+
const batch = [];
|
|
174
|
+
for (let j = 0; j < concurrentUploads && i + j < totalChunks; j++) {
|
|
175
|
+
batch.push(uploadChunk(i + j));
|
|
176
|
+
}
|
|
177
|
+
await Promise.all(batch);
|
|
178
|
+
}
|
|
179
|
+
// 2. Complete
|
|
180
|
+
// Parts must be sorted by partNumber
|
|
181
|
+
completedParts.sort((a, b) => a.partNumber - b.partNumber);
|
|
182
|
+
return await completeMultipartUpload(initiateData, completedParts, options);
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
// 3. Abort on failure
|
|
186
|
+
await abortMultipartUpload(initiateData, options).catch(console.error);
|
|
187
|
+
throw error;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
56
190
|
function getProtectedUrl(path, articleId) {
|
|
57
191
|
const gatewayUrl = config.downloadGatewayUrl || 'https://dl.chanomhub.com';
|
|
58
192
|
// Clean path (remove leading slash if present)
|
|
@@ -70,6 +204,11 @@ function createStorageRepository(config) {
|
|
|
70
204
|
}
|
|
71
205
|
return {
|
|
72
206
|
upload,
|
|
207
|
+
uploadMultipart,
|
|
208
|
+
initiateMultipartUpload,
|
|
209
|
+
uploadPart,
|
|
210
|
+
completeMultipartUpload,
|
|
211
|
+
abortMultipartUpload,
|
|
73
212
|
getProtectedUrl,
|
|
74
213
|
};
|
|
75
214
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storageRepository.js","sourceRoot":"","sources":["../../repositories/storageRepository.ts"],"names":[],"mappings":";AAAA;;GAEG;;
|
|
1
|
+
{"version":3,"file":"storageRepository.js","sourceRoot":"","sources":["../../repositories/storageRepository.ts"],"names":[],"mappings":";AAAA;;GAEG;;AA2HH,0DAqQC;AA7XD,sCAAgD;AAqHhD;;GAEG;AACH,SAAgB,uBAAuB,CAAC,MAAuB;IAC3D,SAAS,WAAW;QAChB,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,4BAAmB,CACzB,qGAAqG,CACxG,CAAC;QACN,CAAC;IACL,CAAC;IAED,SAAS,cAAc;QACnB,OAAO;YACH,eAAe,EAAE,iBAAiB,MAAM,CAAC,KAAK,EAAE;SACnD,CAAC;IACN,CAAC;IAED,KAAK,UAAU,MAAM,CAAC,IAAiB,EAAE,UAAyB,EAAE;QAChE,WAAW,EAAE,CAAC;QAEd,MAAM,EAAE,MAAM,GAAG,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;QAClD,MAAM,UAAU,GAAG,MAAM,CAAC,iBAAiB,IAAI,0BAA0B,CAAC;QAE1E,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;QAChC,qCAAqC;QACrC,MAAM,SAAS,GAAG,CAAC,IAAI,YAAY,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;QAC9F,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAEjC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,UAAU,SAAS,CAAC,CAAC;QAC5C,IAAI,MAAM;YAAE,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACtD,IAAI,IAAI;YAAE,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAChD,IAAI,IAAI;YAAE,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAEhD,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;gBACzC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,cAAc,EAAE;gBACzB,IAAI,EAAE,QAAQ;aACjB,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACf,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC1D,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,IAAI,SAAS,CAAC,OAAO,IAAI,6BAA6B,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YAC5G,CAAC;YAED,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACjC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;YAC9C,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;IAED,KAAK,UAAU,uBAAuB,CAClC,QAAgB,EAChB,WAAmB,EACnB,UAAyB,EAAE;QAE3B,WAAW,EAAE,CAAC;QACd,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;QACnD,MAAM,UAAU,GAAG,MAAM,CAAC,iBAAiB,IAAI,0BAA0B,CAAC;QAE1E,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,UAAU,kBAAkB,CAAC,CAAC;QACrD,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC9C,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;QACpD,IAAI,MAAM;YAAE,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACtD,IAAI,IAAI;YAAE,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAChD,IAAI,IAAI;YAAE,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAEhD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;YACzC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,cAAc,EAAE;SAC5B,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,IAAI,wCAAwC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAClG,CAAC;QAED,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACjC,CAAC;IAED,KAAK,UAAU,UAAU,CACrB,QAA4B,EAC5B,UAAkB,EAClB,YAAuC,EACvC,UAAyB,EAAE;QAE3B,WAAW,EAAE,CAAC;QACd,MAAM,UAAU,GAAG,MAAM,CAAC,iBAAiB,IAAI,0BAA0B,CAAC;QAC1E,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,SAAS,EAAE,GAAG,OAAO,CAAC;QAEnD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,UAAU,cAAc,CAAC,CAAC;QACjD,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC3D,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC;QACjD,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;QACvD,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC7D,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;QACpE,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QAElD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;YACzC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACL,GAAG,cAAc,EAAE;gBACnB,cAAc,EAAE,0BAA0B;aAC7C;YACD,IAAI,EAAE,QAAQ;SACjB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,IAAI,yBAAyB,UAAU,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAClG,CAAC;QAED,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACjC,CAAC;IAED,KAAK,UAAU,uBAAuB,CAClC,YAAuC,EACvC,KAAsB,EACtB,UAAyB,EAAE;QAE3B,WAAW,EAAE,CAAC;QACd,MAAM,UAAU,GAAG,MAAM,CAAC,iBAAiB,IAAI,0BAA0B,CAAC;QAC1E,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,SAAS,EAAE,GAAG,OAAO,CAAC;QAEnD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,UAAU,kBAAkB,CAAC,CAAC;QAErD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;YACzC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACL,GAAG,cAAc,EAAE;gBACnB,cAAc,EAAE,kBAAkB;aACrC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACjB,QAAQ,EAAE,YAAY,CAAC,QAAQ;gBAC/B,GAAG,EAAE,YAAY,CAAC,GAAG;gBACrB,MAAM,EAAE,YAAY,CAAC,MAAM;gBAC3B,KAAK;gBACL,OAAO,EAAE,YAAY,CAAC,OAAO;gBAC7B,UAAU;aACb,CAAC;SACL,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,IAAI,wCAAwC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAClG,CAAC;QAED,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACjC,CAAC;IAED,KAAK,UAAU,oBAAoB,CAC/B,YAAuC,EACvC,UAAyB,EAAE;QAE3B,WAAW,EAAE,CAAC;QACd,MAAM,UAAU,GAAG,MAAM,CAAC,iBAAiB,IAAI,0BAA0B,CAAC;QAC1E,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,SAAS,EAAE,GAAG,OAAO,CAAC;QAEnD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,UAAU,eAAe,CAAC,CAAC;QAClD,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC3D,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC;QACjD,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;QACvD,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;QACpE,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QAElD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;YACzC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,cAAc,EAAE;SAC5B,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,IAAI,qCAAqC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/F,CAAC;IACL,CAAC;IAED,KAAK,UAAU,eAAe,CAAC,IAAiB,EAAE,UAAyB,EAAE;QACzE,MAAM,EACF,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,yBAAyB;QACtD,UAAU,EACV,iBAAiB,GAAG,CAAC,EACxB,GAAG,OAAO,CAAC;QAEZ,MAAM,QAAQ,GAAI,IAAa,CAAC,IAAI,IAAI,MAAM,CAAC;QAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,IAAI,0BAA0B,CAAC;QAE5D,cAAc;QACd,MAAM,YAAY,GAAG,MAAM,uBAAuB,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;QAEnF,IAAI,CAAC;YACD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC;YACrD,MAAM,cAAc,GAAoB,EAAE,CAAC;YAC3C,IAAI,aAAa,GAAG,CAAC,CAAC;YAEtB,qDAAqD;YACrD,MAAM,WAAW,GAAG,KAAK,EAAE,UAAkB,EAAE,EAAE;gBAC7C,MAAM,KAAK,GAAG,UAAU,GAAG,SAAS,CAAC;gBACrC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;gBACnD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAErC,MAAM,UAAU,GAAG,UAAU,GAAG,CAAC,CAAC;gBAClC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;gBAE5E,cAAc,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;gBAE1C,aAAa,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;gBAC/B,IAAI,UAAU,EAAE,CAAC;oBACb,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;gBAC9D,CAAC;YACL,CAAC,CAAC;YAEF,4BAA4B;YAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,IAAI,iBAAiB,EAAE,CAAC;gBACtD,MAAM,KAAK,GAAG,EAAE,CAAC;gBACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,iBAAiB,IAAI,CAAC,GAAG,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;oBAChE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBACnC,CAAC;gBACD,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC7B,CAAC;YAED,cAAc;YACd,qCAAqC;YACrC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;YAC3D,OAAO,MAAM,uBAAuB,CAAC,YAAY,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QAEhF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,sBAAsB;YACtB,MAAM,oBAAoB,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACvE,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;IAED,SAAS,eAAe,CAAC,IAAY,EAAE,SAA2B;QAC9D,MAAM,UAAU,GAAG,MAAM,CAAC,kBAAkB,IAAI,0BAA0B,CAAC;QAE3E,+CAA+C;QAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAE9D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,UAAU,IAAI,SAAS,EAAE,CAAC,CAAC;QAElD,2EAA2E;QAC3E,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QACnD,CAAC;QAED,oDAAoD;QACpD,IAAI,SAAS,EAAE,CAAC;YACZ,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IAED,OAAO;QACH,MAAM;QACN,eAAe;QACf,uBAAuB;QACvB,UAAU;QACV,uBAAuB;QACvB,oBAAoB;QACpB,eAAe;KAClB,CAAC;AACN,CAAC"}
|