@axeth/create-cli 2.1.5 → 3.0.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/.turbo/turbo-build.log +14 -2
- package/CHANGELOG.md +7 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +326 -0
- package/package.json +9 -3
- package/src/class/AxethCLI.ts +290 -224
- package/src/index.ts +5 -0
- package/tsconfig.json +3 -15
- package/tsup.config.ts +6 -0
- package/index.ts +0 -5
- package/src/class/AxethCLI.d.ts +0 -25
- package/src/class/AxethCLI.d.ts.map +0 -1
- package/src/class/AxethCLI.js +0 -199
- package/src/class/AxethCLI.js.map +0 -1
- package/src/class/TemplateGenerators.d.ts +0 -14
- package/src/class/TemplateGenerators.d.ts.map +0 -1
- package/src/class/TemplateGenerators.js +0 -95
- package/src/class/TemplateGenerators.js.map +0 -1
package/src/class/AxethCLI.ts
CHANGED
|
@@ -1,224 +1,290 @@
|
|
|
1
|
-
import * as prompt from "@clack/prompts";
|
|
2
|
-
import color from "colors";
|
|
3
|
-
import { TemplateGenerators } from "./TemplateGenerators
|
|
4
|
-
import fs from "fs-extra";
|
|
5
|
-
import path from "path";
|
|
6
|
-
import { exec, spawn } from "child_process";
|
|
7
|
-
|
|
8
|
-
class AxethCLI {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
1
|
+
import * as prompt from "@clack/prompts";
|
|
2
|
+
import color from "colors";
|
|
3
|
+
import { TemplateGenerators } from "./TemplateGenerators";
|
|
4
|
+
import fs from "fs-extra";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import { exec, spawn } from "child_process";
|
|
7
|
+
|
|
8
|
+
class AxethCLI {
|
|
9
|
+
private promptGroups: Record<string, Record<string, (opts?: any) => any>> =
|
|
10
|
+
{};
|
|
11
|
+
private promptDefaults: Record<string, Record<string, any>> = {};
|
|
12
|
+
private template: TemplateGenerators;
|
|
13
|
+
|
|
14
|
+
private readonly axethAPI = `@axeth/api`;
|
|
15
|
+
private readonly axethCore = `@axeth/core`;
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
console.clear();
|
|
19
|
+
this.template = new TemplateGenerators();
|
|
20
|
+
this.init();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private async version() {
|
|
24
|
+
const url = new URL("../../package.json", import.meta.url);
|
|
25
|
+
const pkgData = await Bun.file(url).json();
|
|
26
|
+
return pkgData.version;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private async init() {
|
|
30
|
+
const version = await this.version();
|
|
31
|
+
const addonInfo = await this.addonInfoPrompt(version, () => {
|
|
32
|
+
process.exit(0);
|
|
33
|
+
});
|
|
34
|
+
const config = await this.configPrompt();
|
|
35
|
+
const minecraftServerVersion = await this.getMinecraftServerVersion();
|
|
36
|
+
const minecraftServerUIVersion = await this.getMinecraftServerUIVersion();
|
|
37
|
+
const spinner = prompt.spinner({ indicator: "dots" });
|
|
38
|
+
|
|
39
|
+
await this.generateTemplate(
|
|
40
|
+
addonInfo,
|
|
41
|
+
config,
|
|
42
|
+
minecraftServerVersion,
|
|
43
|
+
minecraftServerUIVersion,
|
|
44
|
+
spinner,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const projectDir = path.join(
|
|
48
|
+
process.cwd(),
|
|
49
|
+
(addonInfo.addonName as string).replace(/\s+/g, "-").toLowerCase(),
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
//cd and bun run lint
|
|
53
|
+
spinner.start("Linting generated add-on...");
|
|
54
|
+
await this.runCommand("bun run lint", projectDir).catch((err) => {
|
|
55
|
+
spinner.stop("Linting failed.");
|
|
56
|
+
console.error(color.red(err));
|
|
57
|
+
process.exit(1);
|
|
58
|
+
});
|
|
59
|
+
spinner.stop("Add-on linted successfully.");
|
|
60
|
+
const openVSCode = await prompt.confirm({
|
|
61
|
+
message: "Open on VSCode?",
|
|
62
|
+
initialValue: false,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (openVSCode === true) {
|
|
66
|
+
spinner.start("Opening VSCode...");
|
|
67
|
+
await this.runCommand(`code "${projectDir}"`);
|
|
68
|
+
spinner.stop("VSCode opened.");
|
|
69
|
+
}
|
|
70
|
+
prompt.outro(
|
|
71
|
+
color.green(`\n Successfully created add-on: ${addonInfo.addonName}\n`),
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private async generateTemplate(
|
|
76
|
+
addonInfo: { [x: string]: any },
|
|
77
|
+
config: { [x: string]: any },
|
|
78
|
+
minecraftServerVersion: string,
|
|
79
|
+
minecraftServerUIVersion: string,
|
|
80
|
+
spinner: any,
|
|
81
|
+
) {
|
|
82
|
+
await this.template.generate(
|
|
83
|
+
{
|
|
84
|
+
project_name: (addonInfo.addonName as string)
|
|
85
|
+
.replace(/\s+/g, "-")
|
|
86
|
+
.toLowerCase(),
|
|
87
|
+
axethApiVersion: config.axethApiVersion,
|
|
88
|
+
pack_name: addonInfo.addonName,
|
|
89
|
+
pack_description: addonInfo.description,
|
|
90
|
+
author_name: (addonInfo.authors as string)
|
|
91
|
+
.split(",")
|
|
92
|
+
.map((name: string) => name.trim()),
|
|
93
|
+
version: addonInfo.version
|
|
94
|
+
.split(".")
|
|
95
|
+
.map((num: string) => parseInt(num, 10)),
|
|
96
|
+
seed: Math.floor(Math.random() * 1000000),
|
|
97
|
+
axethApiName: this.axethAPI,
|
|
98
|
+
axethCoreName: this.axethCore,
|
|
99
|
+
axethCoreVersion: config.axethCoreVersion,
|
|
100
|
+
minecraftServerUIVersion: minecraftServerUIVersion,
|
|
101
|
+
minecraftServerVersion: minecraftServerVersion,
|
|
102
|
+
},
|
|
103
|
+
spinner,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private async addonInfoPrompt(version: string, onCancel?: () => void) {
|
|
108
|
+
return await new Promise<{ [x: string]: any }>((resolve) => {
|
|
109
|
+
this.registerIntro(
|
|
110
|
+
"\n _ _ \n /_\\ __ _____| |_ \n / _ \\ \\ \\ / -_) _|\n /_/ \\_\\/\\_\\_\\___|\\__|\n ",
|
|
111
|
+
"Axeth CLI",
|
|
112
|
+
version,
|
|
113
|
+
);
|
|
114
|
+
this.registerPrompt("addonInfo", "addonName", "Add-on Name", "text", {
|
|
115
|
+
placeholder: "My-Addon",
|
|
116
|
+
});
|
|
117
|
+
this.registerPrompt("addonInfo", "description", "Description", "text", {
|
|
118
|
+
placeholder: "This addon create for Minecraft Bedrock (Axeth)",
|
|
119
|
+
});
|
|
120
|
+
this.registerPrompt("addonInfo", "version", "Version", "text", {
|
|
121
|
+
placeholder: "1.0.0",
|
|
122
|
+
});
|
|
123
|
+
this.registerPrompt("addonInfo", "authors", "Authors", "text", {
|
|
124
|
+
placeholder: "YourName,Axeth",
|
|
125
|
+
});
|
|
126
|
+
this.runPrompts("addonInfo", onCancel).then((responses) => {
|
|
127
|
+
resolve(responses);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
private async configPrompt() {
|
|
133
|
+
return new Promise<{ [x: string]: any }>(async (resolve) => {
|
|
134
|
+
const spinner = prompt.spinner({ indicator: "dots" });
|
|
135
|
+
spinner.start("Fetching latest Axeth API version...");
|
|
136
|
+
const versions = await this.getAxethApiVersion();
|
|
137
|
+
spinner.stop(`Fetched @axeth/api ${versions.length} versions.`);
|
|
138
|
+
this.registerPrompt(
|
|
139
|
+
"config",
|
|
140
|
+
"axethApiVersion",
|
|
141
|
+
"Select Axeth API version",
|
|
142
|
+
"select",
|
|
143
|
+
{
|
|
144
|
+
options: versions
|
|
145
|
+
.slice(0, 10)
|
|
146
|
+
.map((ver) => ({ label: ver, value: ver })),
|
|
147
|
+
initial: versions[0],
|
|
148
|
+
},
|
|
149
|
+
);
|
|
150
|
+
const axethCoreVersion = await this.getAxethCoreVersion();
|
|
151
|
+
await this.runPrompts("config", () => {
|
|
152
|
+
process.exit(0);
|
|
153
|
+
}).then((response) => {
|
|
154
|
+
resolve({
|
|
155
|
+
axethApiVersion: response.axethApiVersion,
|
|
156
|
+
axethCoreVersion: axethCoreVersion,
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private async getMinecraftServerVersion() {
|
|
163
|
+
const moduleData: any = await fetch(
|
|
164
|
+
`https://registry.npmjs.org/@minecraft/server`,
|
|
165
|
+
).then((res) => res.json());
|
|
166
|
+
|
|
167
|
+
const distTag = moduleData["dist-tags"];
|
|
168
|
+
return distTag.latest;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private async getMinecraftServerUIVersion() {
|
|
172
|
+
const moduleData: any = await fetch(
|
|
173
|
+
`https://registry.npmjs.org/@minecraft/server-ui`,
|
|
174
|
+
).then((res) => res.json());
|
|
175
|
+
const distTag = moduleData["dist-tags"];
|
|
176
|
+
return distTag.latest;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private registerPrompt(
|
|
180
|
+
groupId: string,
|
|
181
|
+
key: string,
|
|
182
|
+
message: string,
|
|
183
|
+
type: "text" | "password" | "confirm" | "select" | "multiselect" = "text",
|
|
184
|
+
options: any = {},
|
|
185
|
+
) {
|
|
186
|
+
if (!this.promptGroups[groupId]) this.promptGroups[groupId] = {};
|
|
187
|
+
this.promptDefaults[groupId] = this.promptDefaults[groupId] || {};
|
|
188
|
+
switch (type) {
|
|
189
|
+
case "text":
|
|
190
|
+
this.promptGroups[groupId][key] = () =>
|
|
191
|
+
prompt.text({ message, ...options });
|
|
192
|
+
this.promptDefaults[groupId][key] = options.placeholder || undefined;
|
|
193
|
+
break;
|
|
194
|
+
case "password":
|
|
195
|
+
this.promptGroups[groupId][key] = () =>
|
|
196
|
+
prompt.password({ message, ...options });
|
|
197
|
+
this.promptDefaults[groupId][key] = options.placeholder || undefined;
|
|
198
|
+
break;
|
|
199
|
+
case "confirm":
|
|
200
|
+
this.promptGroups[groupId][key] = () =>
|
|
201
|
+
prompt.confirm({ message, ...options });
|
|
202
|
+
this.promptDefaults[groupId][key] = options.initial || undefined;
|
|
203
|
+
break;
|
|
204
|
+
case "select":
|
|
205
|
+
this.promptGroups[groupId][key] = () =>
|
|
206
|
+
prompt.select({ message, ...options });
|
|
207
|
+
this.promptDefaults[groupId][key] = options.initial || undefined;
|
|
208
|
+
break;
|
|
209
|
+
case "multiselect":
|
|
210
|
+
this.promptGroups[groupId][key] = () =>
|
|
211
|
+
prompt.multiselect({ message, ...options });
|
|
212
|
+
this.promptDefaults[groupId][key] = options.initial || undefined;
|
|
213
|
+
break;
|
|
214
|
+
default:
|
|
215
|
+
throw new Error(`Unknown prompt type: ${type}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private async getAxethCoreVersion() {
|
|
220
|
+
const moduleData: any = await fetch(
|
|
221
|
+
`https://registry.npmjs.org/${this.axethCore}`,
|
|
222
|
+
).then((res) => res.json());
|
|
223
|
+
|
|
224
|
+
const versions = Object.keys(moduleData.versions);
|
|
225
|
+
return versions.reverse()[0];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
private async getAxethApiVersion() {
|
|
229
|
+
const moduleData: any = await fetch(
|
|
230
|
+
`https://registry.npmjs.org/${this.axethAPI}`,
|
|
231
|
+
).then((res) => res.json());
|
|
232
|
+
|
|
233
|
+
const versions = Object.keys(moduleData.versions);
|
|
234
|
+
return versions.reverse();
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async runPrompts(groupId: string, onCancel?: () => void) {
|
|
238
|
+
if (
|
|
239
|
+
!this.promptGroups[groupId] ||
|
|
240
|
+
Object.keys(this.promptGroups[groupId]).length === 0
|
|
241
|
+
) {
|
|
242
|
+
throw new Error(`No prompts to run for group: ${groupId}`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const responses: { [x: string]: any } = {};
|
|
246
|
+
for (const key of Object.keys(this.promptGroups[groupId])) {
|
|
247
|
+
const response = await this.promptGroups[groupId][key]!();
|
|
248
|
+
if (String(response).includes("clack:cancel")) {
|
|
249
|
+
prompt.cancel("Operation cancelled.");
|
|
250
|
+
if (onCancel) onCancel();
|
|
251
|
+
return {};
|
|
252
|
+
}
|
|
253
|
+
if (response === undefined) {
|
|
254
|
+
if (
|
|
255
|
+
this.promptDefaults[groupId] &&
|
|
256
|
+
this.promptDefaults[groupId][key] !== undefined
|
|
257
|
+
) {
|
|
258
|
+
responses[key] = this.promptDefaults[groupId][key];
|
|
259
|
+
} else {
|
|
260
|
+
responses[key] = undefined;
|
|
261
|
+
}
|
|
262
|
+
} else {
|
|
263
|
+
responses[key] = response;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return responses;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
private registerIntro(logo: string, title: string, version: string) {
|
|
270
|
+
prompt.intro(color.cyan(logo) + `\n ${title} - v${version}\n`);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
private async runCommand(command: string, cwd?: string): Promise<void> {
|
|
274
|
+
return new Promise((resolve, reject) => {
|
|
275
|
+
const options: any = {};
|
|
276
|
+
if (cwd) {
|
|
277
|
+
options.cwd = cwd;
|
|
278
|
+
}
|
|
279
|
+
exec(command, options, (error, stdout, stderr) => {
|
|
280
|
+
if (error) {
|
|
281
|
+
reject(error);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
resolve();
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export { AxethCLI };
|
package/src/index.ts
ADDED
package/tsconfig.json
CHANGED
|
@@ -1,16 +1,4 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
"moduleResolution": "NodeNext",
|
|
6
|
-
"declaration": true,
|
|
7
|
-
"declarationMap": true,
|
|
8
|
-
"sourceMap": true,
|
|
9
|
-
"strict": true,
|
|
10
|
-
"esModuleInterop": true,
|
|
11
|
-
"skipLibCheck": true,
|
|
12
|
-
"forceConsistentCasingInFileNames": true
|
|
13
|
-
},
|
|
14
|
-
"include": ["src/**/*"],
|
|
15
|
-
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
|
16
|
-
}
|
|
2
|
+
"extends": "../../config/tsconfig.default.json",
|
|
3
|
+
"include": ["src"],
|
|
4
|
+
}
|
package/tsup.config.ts
ADDED
package/index.ts
DELETED
package/src/class/AxethCLI.d.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
declare class AxethCLI {
|
|
2
|
-
private promptGroups;
|
|
3
|
-
private promptDefaults;
|
|
4
|
-
private template;
|
|
5
|
-
private readonly axethAPI;
|
|
6
|
-
private readonly axethCore;
|
|
7
|
-
constructor();
|
|
8
|
-
private version;
|
|
9
|
-
private init;
|
|
10
|
-
private generateTemplate;
|
|
11
|
-
private addonInfoPrompt;
|
|
12
|
-
private configPrompt;
|
|
13
|
-
private getMinecraftServerVersion;
|
|
14
|
-
private getMinecraftServerUIVersion;
|
|
15
|
-
private registerPrompt;
|
|
16
|
-
private getAxethCoreVersion;
|
|
17
|
-
private getAxethApiVersion;
|
|
18
|
-
runPrompts(groupId: string, onCancel?: () => void): Promise<{
|
|
19
|
-
[x: string]: any;
|
|
20
|
-
}>;
|
|
21
|
-
private registerIntro;
|
|
22
|
-
private runCommand;
|
|
23
|
-
}
|
|
24
|
-
export { AxethCLI };
|
|
25
|
-
//# sourceMappingURL=AxethCLI.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AxethCLI.d.ts","sourceRoot":"","sources":["AxethCLI.ts"],"names":[],"mappings":"AAOA,cAAM,QAAQ;IACV,OAAO,CAAC,YAAY,CAA2D;IAC/E,OAAO,CAAC,cAAc,CAA2C;IACjE,OAAO,CAAC,QAAQ,CAAqB;IAErC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;;YAQ7B,OAAO;YAMP,IAAI;YAmCJ,gBAAgB;YAiBhB,eAAe;YAiBf,YAAY;YAoBZ,yBAAyB;YAQzB,2BAA2B;IAOzC,OAAO,CAAC,cAAc;YA6BR,mBAAmB;YAQnB,kBAAkB;IAQ1B,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,IAAI;;;IA0BvD,OAAO,CAAC,aAAa;YAIP,UAAU;CAe3B;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|