@nodetool-ai/deploy 0.7.0-rc.11

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 (133) hide show
  1. package/dist/admin-client.d.ts +58 -0
  2. package/dist/admin-client.d.ts.map +1 -0
  3. package/dist/admin-client.js +275 -0
  4. package/dist/admin-client.js.map +1 -0
  5. package/dist/admin-operations.d.ts +197 -0
  6. package/dist/admin-operations.d.ts.map +1 -0
  7. package/dist/admin-operations.js +433 -0
  8. package/dist/admin-operations.js.map +1 -0
  9. package/dist/admin-routes.d.ts +306 -0
  10. package/dist/admin-routes.d.ts.map +1 -0
  11. package/dist/admin-routes.js +383 -0
  12. package/dist/admin-routes.js.map +1 -0
  13. package/dist/api-user-manager.d.ts +72 -0
  14. package/dist/api-user-manager.d.ts.map +1 -0
  15. package/dist/api-user-manager.js +89 -0
  16. package/dist/api-user-manager.js.map +1 -0
  17. package/dist/auth.d.ts +67 -0
  18. package/dist/auth.d.ts.map +1 -0
  19. package/dist/auth.js +142 -0
  20. package/dist/auth.js.map +1 -0
  21. package/dist/collection-routes.d.ts +37 -0
  22. package/dist/collection-routes.d.ts.map +1 -0
  23. package/dist/collection-routes.js +43 -0
  24. package/dist/collection-routes.js.map +1 -0
  25. package/dist/compose.d.ts +52 -0
  26. package/dist/compose.d.ts.map +1 -0
  27. package/dist/compose.js +153 -0
  28. package/dist/compose.js.map +1 -0
  29. package/dist/configure.d.ts +87 -0
  30. package/dist/configure.d.ts.map +1 -0
  31. package/dist/configure.js +104 -0
  32. package/dist/configure.js.map +1 -0
  33. package/dist/deploy-to-gcp.d.ts +67 -0
  34. package/dist/deploy-to-gcp.d.ts.map +1 -0
  35. package/dist/deploy-to-gcp.js +268 -0
  36. package/dist/deploy-to-gcp.js.map +1 -0
  37. package/dist/deploy-to-runpod.d.ts +53 -0
  38. package/dist/deploy-to-runpod.d.ts.map +1 -0
  39. package/dist/deploy-to-runpod.js +207 -0
  40. package/dist/deploy-to-runpod.js.map +1 -0
  41. package/dist/deploy.d.ts +54 -0
  42. package/dist/deploy.d.ts.map +1 -0
  43. package/dist/deploy.js +82 -0
  44. package/dist/deploy.js.map +1 -0
  45. package/dist/deployment-config.d.ts +1073 -0
  46. package/dist/deployment-config.d.ts.map +1 -0
  47. package/dist/deployment-config.js +536 -0
  48. package/dist/deployment-config.js.map +1 -0
  49. package/dist/docker-run.d.ts +85 -0
  50. package/dist/docker-run.d.ts.map +1 -0
  51. package/dist/docker-run.js +202 -0
  52. package/dist/docker-run.js.map +1 -0
  53. package/dist/docker.d.ts +98 -0
  54. package/dist/docker.d.ts.map +1 -0
  55. package/dist/docker.js +396 -0
  56. package/dist/docker.js.map +1 -0
  57. package/dist/fly.d.ts +40 -0
  58. package/dist/fly.d.ts.map +1 -0
  59. package/dist/fly.js +291 -0
  60. package/dist/fly.js.map +1 -0
  61. package/dist/gcp.d.ts +59 -0
  62. package/dist/gcp.d.ts.map +1 -0
  63. package/dist/gcp.js +339 -0
  64. package/dist/gcp.js.map +1 -0
  65. package/dist/google-cloud-run-api.d.ts +134 -0
  66. package/dist/google-cloud-run-api.d.ts.map +1 -0
  67. package/dist/google-cloud-run-api.js +532 -0
  68. package/dist/google-cloud-run-api.js.map +1 -0
  69. package/dist/huggingface.d.ts +69 -0
  70. package/dist/huggingface.d.ts.map +1 -0
  71. package/dist/huggingface.js +346 -0
  72. package/dist/huggingface.js.map +1 -0
  73. package/dist/image-builder.d.ts +35 -0
  74. package/dist/image-builder.d.ts.map +1 -0
  75. package/dist/image-builder.js +157 -0
  76. package/dist/image-builder.js.map +1 -0
  77. package/dist/image-spec.d.ts +41 -0
  78. package/dist/image-spec.d.ts.map +1 -0
  79. package/dist/image-spec.js +49 -0
  80. package/dist/image-spec.js.map +1 -0
  81. package/dist/index.d.ts +33 -0
  82. package/dist/index.d.ts.map +1 -0
  83. package/dist/index.js +45 -0
  84. package/dist/index.js.map +1 -0
  85. package/dist/manager.d.ts +121 -0
  86. package/dist/manager.d.ts.map +1 -0
  87. package/dist/manager.js +225 -0
  88. package/dist/manager.js.map +1 -0
  89. package/dist/progress.d.ts +91 -0
  90. package/dist/progress.d.ts.map +1 -0
  91. package/dist/progress.js +262 -0
  92. package/dist/progress.js.map +1 -0
  93. package/dist/railway.d.ts +65 -0
  94. package/dist/railway.d.ts.map +1 -0
  95. package/dist/railway.js +284 -0
  96. package/dist/railway.js.map +1 -0
  97. package/dist/remote-users.d.ts +74 -0
  98. package/dist/remote-users.d.ts.map +1 -0
  99. package/dist/remote-users.js +172 -0
  100. package/dist/remote-users.js.map +1 -0
  101. package/dist/runpod-api.d.ts +206 -0
  102. package/dist/runpod-api.d.ts.map +1 -0
  103. package/dist/runpod-api.js +703 -0
  104. package/dist/runpod-api.js.map +1 -0
  105. package/dist/runpod.d.ts +82 -0
  106. package/dist/runpod.d.ts.map +1 -0
  107. package/dist/runpod.js +188 -0
  108. package/dist/runpod.js.map +1 -0
  109. package/dist/self-hosted.d.ts +157 -0
  110. package/dist/self-hosted.d.ts.map +1 -0
  111. package/dist/self-hosted.js +799 -0
  112. package/dist/self-hosted.js.map +1 -0
  113. package/dist/ssh.d.ts +166 -0
  114. package/dist/ssh.d.ts.map +1 -0
  115. package/dist/ssh.js +430 -0
  116. package/dist/ssh.js.map +1 -0
  117. package/dist/state.d.ts +83 -0
  118. package/dist/state.d.ts.map +1 -0
  119. package/dist/state.js +368 -0
  120. package/dist/state.js.map +1 -0
  121. package/dist/storage-routes.d.ts +55 -0
  122. package/dist/storage-routes.d.ts.map +1 -0
  123. package/dist/storage-routes.js +160 -0
  124. package/dist/storage-routes.js.map +1 -0
  125. package/dist/sync.d.ts +38 -0
  126. package/dist/sync.d.ts.map +1 -0
  127. package/dist/sync.js +130 -0
  128. package/dist/sync.js.map +1 -0
  129. package/dist/workflow-syncer.d.ts +51 -0
  130. package/dist/workflow-syncer.d.ts.map +1 -0
  131. package/dist/workflow-syncer.js +192 -0
  132. package/dist/workflow-syncer.js.map +1 -0
  133. package/package.json +58 -0
package/dist/docker.js ADDED
@@ -0,0 +1,396 @@
1
+ /**
2
+ * Docker utilities for NodeTool deployment.
3
+ *
4
+ * This module contains all Docker-related functionality for building, pushing,
5
+ * and managing Docker images for NodeTool deployments.
6
+ */
7
+ import { execSync, execFileSync, execFile } from "node:child_process";
8
+ import { promisify } from "node:util";
9
+ import * as crypto from "node:crypto";
10
+ import * as fs from "node:fs";
11
+ import * as os from "node:os";
12
+ import * as path from "node:path";
13
+ /**
14
+ * Promisified `child_process.execFile` — runs a command with an argument array
15
+ * and no shell, returning `{ stdout, stderr }`.
16
+ */
17
+ export const execFileAsync = promisify(execFile);
18
+ // ---------------------------------------------------------------------------
19
+ // Shell helpers
20
+ // ---------------------------------------------------------------------------
21
+ /**
22
+ * Escape a string for safe shell inclusion (single-quote wrapping).
23
+ */
24
+ export function shellEscape(value) {
25
+ // Equivalent to Python shlex.quote: wrap in single quotes, escape embedded
26
+ // single quotes with '\'' technique.
27
+ if (value === "")
28
+ return "''";
29
+ if (/[^\w@%+=:,./-]/i.test(value)) {
30
+ return "'" + value.replace(/'/g, "'\"'\"'") + "'";
31
+ }
32
+ return value;
33
+ }
34
+ // ---------------------------------------------------------------------------
35
+ // Run command
36
+ // ---------------------------------------------------------------------------
37
+ /**
38
+ * Run a command safely without shell expansion.
39
+ *
40
+ * @param command Shell command string to run.
41
+ * @param captureOutput If true, capture and return output. If false, stream output.
42
+ * @returns Captured output if captureOutput=true, empty string otherwise.
43
+ */
44
+ export function runCommand(command, captureOutput = false) {
45
+ try {
46
+ const result = execSync(command, {
47
+ encoding: "utf-8",
48
+ stdio: ["pipe", "pipe", "pipe"],
49
+ shell: "/bin/sh"
50
+ });
51
+ const output = (result ?? "").trim();
52
+ if (captureOutput) {
53
+ if (output)
54
+ console.log(output);
55
+ return output;
56
+ }
57
+ // Stream mode: print lines
58
+ if (output) {
59
+ for (const line of output.split("\n")) {
60
+ console.log(line);
61
+ }
62
+ }
63
+ return "";
64
+ }
65
+ catch (err) {
66
+ const code = err.status ?? 1;
67
+ throw new Error(`Command failed with return code ${code}: ${command}`);
68
+ }
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // Run command (args array – no shell)
72
+ // ---------------------------------------------------------------------------
73
+ /**
74
+ * Run a command safely using execFileSync with an argument array (no shell).
75
+ *
76
+ * @param program The executable to run (e.g. "docker").
77
+ * @param args Array of arguments passed directly to the program.
78
+ * @param options.captureOutput If true, capture and return stdout.
79
+ * @returns Captured output if captureOutput=true, empty string otherwise.
80
+ */
81
+ export function runCommandArgs(program, args, options) {
82
+ const captureOutput = options?.captureOutput ?? false;
83
+ try {
84
+ const result = execFileSync(program, args, {
85
+ encoding: "utf-8",
86
+ stdio: ["pipe", "pipe", "pipe"]
87
+ });
88
+ const output = (result ?? "").trim();
89
+ if (captureOutput) {
90
+ if (output)
91
+ console.log(output);
92
+ return output;
93
+ }
94
+ // Stream mode: print lines
95
+ if (output) {
96
+ for (const line of output.split("\n")) {
97
+ console.log(line);
98
+ }
99
+ }
100
+ return "";
101
+ }
102
+ catch (err) {
103
+ const code = err.status ?? 1;
104
+ throw new Error(`Command failed with return code ${code}: ${program} ${args.join(" ")}`);
105
+ }
106
+ }
107
+ // ---------------------------------------------------------------------------
108
+ // Docker authentication
109
+ // ---------------------------------------------------------------------------
110
+ /**
111
+ * Check if user is authenticated with the Docker registry.
112
+ */
113
+ export function checkDockerAuth(_registry = "docker.io") {
114
+ try {
115
+ execSync("docker system info --format '{{.RegistryConfig.IndexConfigs}}'", {
116
+ encoding: "utf-8",
117
+ stdio: ["pipe", "pipe", "pipe"]
118
+ });
119
+ return true;
120
+ }
121
+ catch {
122
+ try {
123
+ execSync("docker login --get-login", {
124
+ encoding: "utf-8",
125
+ stdio: ["pipe", "pipe", "pipe"]
126
+ });
127
+ return true;
128
+ }
129
+ catch {
130
+ return false;
131
+ }
132
+ }
133
+ }
134
+ /**
135
+ * Ensure user is authenticated with Docker registry.
136
+ * Note: interactive login prompt is not supported in this TS port;
137
+ * the function will throw if not authenticated.
138
+ */
139
+ export function ensureDockerAuth(registry = "docker.io") {
140
+ if (!checkDockerAuth(registry)) {
141
+ throw new Error(`Not authenticated with Docker registry: ${registry}. Please run 'docker login' manually and try again.`);
142
+ }
143
+ }
144
+ // ---------------------------------------------------------------------------
145
+ // Image naming & tagging
146
+ // ---------------------------------------------------------------------------
147
+ /**
148
+ * Format the image name with proper registry and username prefix.
149
+ *
150
+ * @example
151
+ * formatImageName("my-workflow", "myuser") // "myuser/my-workflow"
152
+ * formatImageName("my-workflow", "myuser", "ghcr.io") // "ghcr.io/myuser/my-workflow"
153
+ */
154
+ export function formatImageName(baseName, dockerUsername, registry = "docker.io") {
155
+ if (registry === "docker.io") {
156
+ return `${dockerUsername}/${baseName}`;
157
+ }
158
+ return `${registry}/${dockerUsername}/${baseName}`;
159
+ }
160
+ /**
161
+ * Generate a unique image tag based on current timestamp and random hash.
162
+ *
163
+ * @returns A unique tag in format 'YYYYMMDD-HHMMSS-abcdef'
164
+ */
165
+ export function generateImageTag() {
166
+ const now = new Date();
167
+ const pad = (n, len = 2) => String(n).padStart(len, "0");
168
+ const timestamp = [
169
+ now.getFullYear(),
170
+ pad(now.getMonth() + 1),
171
+ pad(now.getDate()),
172
+ "-",
173
+ pad(now.getHours()),
174
+ pad(now.getMinutes()),
175
+ pad(now.getSeconds())
176
+ ].join("");
177
+ const randomData = `${Date.now()}${process.pid}${crypto.randomBytes(8).toString("hex")}`;
178
+ const shortHash = crypto
179
+ .createHash("md5")
180
+ .update(randomData)
181
+ .digest("hex")
182
+ .slice(0, 6);
183
+ return `${timestamp}-${shortHash}`;
184
+ }
185
+ /**
186
+ * Build a Docker image for deployment.
187
+ *
188
+ * @returns true if the image was pushed to registry, false if only built locally.
189
+ */
190
+ export function buildDockerImage(options) {
191
+ const { imageName, tag, platform = "linux/amd64", useCache = true, autoPush = true } = options;
192
+ console.log("Building Docker image");
193
+ console.log(`Platform: ${platform}`);
194
+ // Get paths to build inputs
195
+ const scriptDir = path.dirname(new URL(import.meta.url).pathname);
196
+ // The Dockerfile is at the project root, which is 3 levels up
197
+ const projectRoot = path.resolve(scriptDir, "../../..");
198
+ const deployDockerfilePath = path.join(projectRoot, "Dockerfile");
199
+ // Create a temporary build directory
200
+ const buildDir = fs.mkdtempSync(path.join(os.tmpdir(), "nodetool_build_"));
201
+ console.log(`Using build directory: ${buildDir}`);
202
+ try {
203
+ fs.copyFileSync(deployDockerfilePath, path.join(buildDir, "Dockerfile"));
204
+ // Build using project root as context
205
+ const dockerfileForBuild = path.join(buildDir, "Dockerfile");
206
+ const buildContext = projectRoot;
207
+ const originalDir = process.cwd();
208
+ process.chdir(projectRoot);
209
+ let imagePushed = false;
210
+ try {
211
+ if (useCache) {
212
+ console.log("Building with Docker Hub cache optimization...");
213
+ // Ensure docker buildx builder exists
214
+ try {
215
+ runCommandArgs("docker", [
216
+ "buildx",
217
+ "create",
218
+ "--use",
219
+ "--name",
220
+ "nodetool-builder",
221
+ "--driver",
222
+ "docker-container"
223
+ ]);
224
+ }
225
+ catch {
226
+ console.log("Warning: docker buildx create failed; continuing with existing/default builder.");
227
+ }
228
+ const cacheFrom = `type=registry,ref=${imageName}:buildcache`;
229
+ const cacheTo = `type=registry,ref=${imageName}:buildcache,mode=max`;
230
+ const pushFlag = autoPush ? "--push" : "--load";
231
+ const buildxArgs = [
232
+ "buildx",
233
+ "build",
234
+ "-f",
235
+ dockerfileForBuild,
236
+ "--platform",
237
+ platform,
238
+ "-t",
239
+ `${imageName}:${tag}`,
240
+ `--cache-from=${cacheFrom}`,
241
+ `--cache-to=${cacheTo}`,
242
+ pushFlag,
243
+ buildContext
244
+ ];
245
+ console.log(`Cache image: ${imageName}:buildcache`);
246
+ try {
247
+ runCommandArgs("docker", buildxArgs);
248
+ imagePushed = autoPush;
249
+ }
250
+ catch {
251
+ console.log("Cache/buildx build failed, falling back to standard docker build...");
252
+ runCommandArgs("docker", [
253
+ "build",
254
+ "-f",
255
+ dockerfileForBuild,
256
+ "--platform",
257
+ platform,
258
+ "-t",
259
+ `${imageName}:${tag}`,
260
+ buildContext
261
+ ]);
262
+ imagePushed = false;
263
+ }
264
+ }
265
+ else {
266
+ console.log("Building without cache optimization...");
267
+ runCommandArgs("docker", [
268
+ "build",
269
+ "-f",
270
+ dockerfileForBuild,
271
+ "--platform",
272
+ platform,
273
+ "-t",
274
+ `${imageName}:${tag}`,
275
+ buildContext
276
+ ]);
277
+ imagePushed = false;
278
+ }
279
+ }
280
+ finally {
281
+ process.chdir(originalDir);
282
+ }
283
+ console.log("Docker image built successfully");
284
+ return imagePushed;
285
+ }
286
+ finally {
287
+ // Clean up temporary build directory
288
+ fs.rmSync(buildDir, { recursive: true, force: true });
289
+ }
290
+ }
291
+ // ---------------------------------------------------------------------------
292
+ // Push to registry
293
+ // ---------------------------------------------------------------------------
294
+ /**
295
+ * Push Docker image to a registry with proper authentication checks.
296
+ */
297
+ export function pushToRegistry(imageName, tag, registry = "docker.io") {
298
+ console.log(`Pushing Docker image ${imageName}:${tag} to registry ${registry}...`);
299
+ ensureDockerAuth(registry);
300
+ try {
301
+ runCommandArgs("docker", ["push", `${imageName}:${tag}`]);
302
+ console.log(`Docker image ${imageName}:${tag} pushed successfully`);
303
+ }
304
+ catch {
305
+ throw new Error(`Failed to push image ${imageName}:${tag}. Common issues: ` +
306
+ `1. Check your Docker registry authentication: docker login. ` +
307
+ `2. Verify the image name includes your username: username/image-name. ` +
308
+ `3. Ensure you have push permissions to the repository.`);
309
+ }
310
+ }
311
+ // ---------------------------------------------------------------------------
312
+ // Get Docker username from config
313
+ // ---------------------------------------------------------------------------
314
+ /**
315
+ * Get Docker username from Docker's configuration file.
316
+ */
317
+ export function getDockerUsernameFromConfig(registry = "docker.io") {
318
+ try {
319
+ const dockerConfigPath = path.join(os.homedir(), ".docker", "config.json");
320
+ if (!fs.existsSync(dockerConfigPath)) {
321
+ return null;
322
+ }
323
+ const config = JSON.parse(fs.readFileSync(dockerConfigPath, "utf-8"));
324
+ const auths = config.auths ?? {};
325
+ const possibleRegistryKeys = [
326
+ registry,
327
+ `https://${registry}/v1/`,
328
+ registry === "docker.io"
329
+ ? "https://index.docker.io/v1/"
330
+ : `https://${registry}/v1/`,
331
+ registry === "docker.io" ? "index.docker.io" : registry
332
+ ];
333
+ for (const regKey of possibleRegistryKeys) {
334
+ const authData = auths[regKey];
335
+ if (!authData)
336
+ continue;
337
+ if (authData.username) {
338
+ return authData.username;
339
+ }
340
+ if (authData.auth) {
341
+ try {
342
+ const decoded = Buffer.from(authData.auth, "base64").toString("utf-8");
343
+ const [username] = decoded.split(":", 2);
344
+ return username;
345
+ }
346
+ catch {
347
+ continue;
348
+ }
349
+ }
350
+ }
351
+ return null;
352
+ }
353
+ catch (err) {
354
+ console.warn(`Warning: Could not read Docker config: ${err}`);
355
+ return null;
356
+ }
357
+ }
358
+ /**
359
+ * Run a Docker image and map it to a given host port.
360
+ */
361
+ export function runDockerImage(options) {
362
+ const { imageName, tag, hostPort, containerPort = 80, containerName, env, volumes, detach = true, gpus, remove = true, extraArgs } = options;
363
+ const args = ["run"];
364
+ if (remove)
365
+ args.push("--rm");
366
+ if (detach)
367
+ args.push("-d");
368
+ if (containerName)
369
+ args.push("--name", containerName);
370
+ // Port mapping
371
+ args.push("-p", `${hostPort}:${containerPort}`);
372
+ // Environment variables — passed as-is, no shell escaping needed
373
+ if (env) {
374
+ for (const [key, value] of Object.entries(env)) {
375
+ args.push("-e", `${key}=${String(value)}`);
376
+ }
377
+ }
378
+ // Volumes
379
+ if (volumes) {
380
+ for (const [hostPath, containerPath] of volumes) {
381
+ args.push("-v", `${hostPath}:${containerPath}`);
382
+ }
383
+ }
384
+ // GPUs
385
+ if (gpus) {
386
+ const gpuArg = gpus === true ? "all" : String(gpus);
387
+ args.push("--gpus", gpuArg);
388
+ }
389
+ if (extraArgs) {
390
+ args.push(...extraArgs);
391
+ }
392
+ // Image reference
393
+ args.push(`${imageName}:${tag}`);
394
+ runCommandArgs("docker", args);
395
+ }
396
+ //# sourceMappingURL=docker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.js","sourceRoot":"","sources":["../src/docker.ts"],"names":[],"mappings":"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"}
package/dist/fly.d.ts ADDED
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Fly.io deployment implementation for NodeTool.
3
+ *
4
+ * Handles deployment to Fly.io using the `flyctl` CLI, including:
5
+ * - Docker image building from nodetool-image.yaml specs
6
+ * - Fly app creation and management
7
+ * - Volume provisioning
8
+ * - Secret/environment variable configuration
9
+ * - Service deployment and monitoring
10
+ */
11
+ import { StateManager } from "./state.js";
12
+ import type { FlyDeployment } from "./deployment-config.js";
13
+ import type { DeployResult, DeployPlan, DeployStatus } from "./self-hosted.js";
14
+ /**
15
+ * Deploys NodeTool to Fly.io using the flyctl CLI.
16
+ *
17
+ * Lifecycle:
18
+ * plan() — check what will be created/updated
19
+ * apply() — build image, create app, set secrets, deploy
20
+ * destroy() — tear down the Fly app
21
+ * status() — query current app status
22
+ * logs() — stream or tail app logs
23
+ */
24
+ export declare class FlyDeployer {
25
+ readonly deploymentName: string;
26
+ readonly deployment: FlyDeployment;
27
+ readonly stateManager: StateManager;
28
+ constructor(deploymentName: string, deployment: FlyDeployment, stateManager?: StateManager);
29
+ plan(): Promise<DeployPlan>;
30
+ apply(opts?: {
31
+ dryRun?: boolean;
32
+ }): Promise<DeployResult>;
33
+ destroy(): Promise<DeployResult>;
34
+ status(): Promise<DeployStatus>;
35
+ logs(opts?: {
36
+ follow?: boolean;
37
+ tail?: number;
38
+ }): Promise<string>;
39
+ }
40
+ //# sourceMappingURL=fly.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fly.d.ts","sourceRoot":"","sources":["../src/fly.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAiE/E;;;;;;;;;GASG;AACH,qBAAa,WAAW;IACtB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;gBAGlC,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,aAAa,EACzB,YAAY,CAAC,EAAE,YAAY;IASvB,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;IA2C3B,KAAK,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC;IAyHzD,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC;IAkChC,MAAM,IAAI,OAAO,CAAC,YAAY,CAAC;IAoC/B,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CAqBxE"}