zet-execute 1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ZET Digital
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,352 @@
1
+ # zet-execute
2
+
3
+ A project-level task runner for teams. Define dev commands in a config file, run them with `x <command>`.
4
+
5
+ Built for the team at ZET Digital for internal use. You're welcome to use it too.
6
+
7
+ > This is not a CLI framework like Commander or Yargs. Those help you build CLIs. This is a task runner — it runs your project's commands.
8
+
9
+ ## Install
10
+
11
+ ```sh
12
+ npm install -g zet-execute
13
+ ```
14
+
15
+ Requires Node.js ^18.19 or >=20.6.
16
+
17
+ ## Getting Started
18
+
19
+ ```sh
20
+ mkdir my-project && cd my-project
21
+ x init
22
+ x hello
23
+ ```
24
+
25
+ `x init` creates an `x.config.mjs` with a starter command. Edit it to add your own. Run `x` or `x --help` to see all registered commands.
26
+
27
+ ## Configuration File
28
+
29
+ `x` traverses up from the current directory looking for `x.config.mjs`. Commands are registered as side effects via named imports.
30
+
31
+ ```js
32
+ import { register } from 'zet-execute';
33
+
34
+ register('up', 'Start containers')
35
+ .run`docker compose up -d`;
36
+ ```
37
+
38
+ ## API Reference
39
+
40
+ ### Command Registration
41
+
42
+ ```js
43
+ import { register, group } from 'zet-execute';
44
+
45
+ // Simple command
46
+ register('up', 'Start containers')
47
+ .run`docker compose up -d`;
48
+
49
+ // With signature (args, options, rest)
50
+ register('deploy {env} {--Force}', 'Deploy to environment')
51
+ .callback(async ($) => {
52
+ const env = $.arg('env');
53
+ $.info(`Deploying to ${env}...`);
54
+ if ($.option('--force')) $.warn('Force deploy enabled');
55
+ await $.mustRun`deploy.sh ${env}`;
56
+ });
57
+
58
+ // Group
59
+ const db = group('db', 'Database');
60
+ db.register('migrate ...', 'Run migrations').run`docker compose exec app migrate ...`;
61
+ ```
62
+
63
+ ### Signature Syntax
64
+
65
+ ```
66
+ command-name {arg} {arg?} {arg desc} {--option} {--option=} {--Option} {--Opt-Name=} ...
67
+ ```
68
+
69
+ | Token | Meaning |
70
+ |---|---|
71
+ | `{name}` | Required positional argument |
72
+ | `{name?}` | Optional positional argument |
73
+ | `{name description}` | Required argument with description |
74
+ | `{name? description}` | Optional argument with description |
75
+ | `{--name}` | Boolean option (flag) |
76
+ | `{--name=}` | Option that accepts a value |
77
+ | `{--Name}` | Boolean option with short flag `-N` |
78
+ | `{--Preserve-Cache=}` | Value option with short flag `-PC` |
79
+ | `...` | Accept extra arguments (rest) |
80
+
81
+ Short flags are derived from uppercase letters at the start of hyphen-separated segments: `--Preserve-Cache` -> `-PC`. The long name is always stored lowercase.
82
+
83
+ ### `.run` — Defining Commands
84
+
85
+ `.run` works as both a tagged template (recommended) and a regular function call.
86
+
87
+ **Tagged template (recommended)** — whitespace in static parts is split into separate arguments. Interpolated values are kept as single tokens (safe for paths with spaces).
88
+
89
+ ```js
90
+ register('build', 'Build project').run`npm run build`;
91
+
92
+ // Interpolation keeps the value as one token
93
+ const target = 'my output dir';
94
+ register('clean', 'Clean output').run`rm -rf ${target}`;
95
+
96
+ // Rest args with ...
97
+ register('npm ...', 'Run npm').run`npm ...`;
98
+ // x npm install lodash -> npm install lodash
99
+ ```
100
+
101
+ **Function call** — also accepts variadic string arguments for programmatic use.
102
+
103
+ ```js
104
+ register('up', 'Start containers').run('docker', 'compose', 'up', '-d');
105
+ ```
106
+
107
+ ### `.userCwd()` Method
108
+
109
+ Run a command from the user's current working directory instead of the project root:
110
+
111
+ ```js
112
+ register('ls', 'List files')
113
+ .userCwd()
114
+ .run`ls -la`;
115
+ ```
116
+
117
+ ### Templates
118
+
119
+ Reuse common command prefixes:
120
+
121
+ ```js
122
+ import { register, template } from 'zet-execute';
123
+
124
+ const compose = template((service) => ['docker', 'compose', 'exec', '-it', service]);
125
+
126
+ register('shell', 'Open shell')
127
+ .run`${compose('app')} bash`;
128
+
129
+ register('migrate ...', 'Run migrations')
130
+ .run`${compose('app')} migrate ...`;
131
+ ```
132
+
133
+ Template functions can return an array of strings or a single string (which gets split on whitespace). Templates validate argument count based on `fn.length`. Zero-arg templates can be used without `()` — `${compose}` works the same as `${compose()}`.
134
+
135
+ ### Callback with `$` Context
136
+
137
+ Callbacks receive an `ExecutionContext` object (`$`) with everything needed to run commands and access parsed arguments:
138
+
139
+ ```js
140
+ register('deploy {env} {--Verbose}')
141
+ .callback(async ($) => {
142
+ const env = $.arg('env'); // string | null
143
+ const verbose = $.option('--verbose'); // string | true | null
144
+
145
+ // Run a command (output visible) — does not throw on failure
146
+ await $.run`deploy.sh ${env}`;
147
+
148
+ // Run and throw on failure
149
+ await $.mustRun`deploy.sh ${env}`;
150
+
151
+ // Run silently (capture output)
152
+ const result = await $.silent`git rev-parse HEAD`;
153
+ $.info(`Deployed ${result.stdout.trim()}`);
154
+ });
155
+ ```
156
+
157
+ `$.run` and `$.silent` also accept variadic args: `await $.run('docker', 'compose', 'up')`.
158
+
159
+ `$.run` does not throw on failure — use `$.mustRun` or chain `.throw()` to stop on errors.
160
+
161
+ #### `$` Methods
162
+
163
+ | Method | Description |
164
+ |---|---|
165
+ | `$.arg(name)` | Get parsed argument (`string \| null`) |
166
+ | `$.option('--name')` | Get option (`string \| true \| null`) |
167
+ | `$.run\`cmd\`` | Spawn with inherited stdio |
168
+ | `$.mustRun\`cmd\`` | Like `$.run` but throws on non-zero exit code |
169
+ | `$.silent\`cmd\`` | Spawn with piped stdio, returns `CommandOutput` |
170
+ | `$.mustSilent\`cmd\`` | Like `$.silent` but throws on non-zero exit code |
171
+ | `$.info(msg)` | Green message to stdout |
172
+ | `$.warn(msg)` | Yellow message to stderr |
173
+ | `$.error(msg)` | Red message to stderr |
174
+ | `$.confirm(msg)` | Yellow prompt `[y/N]`, returns `boolean` |
175
+ | `$.prompt(msg)` | Cyan prompt, returns the answer |
176
+ | `$.root` | Project root — callable: `$.root('src')`, or string: `` `${$.root}` `` |
177
+ | `$.user` | User CWD — callable: `$.user('test')`, or string: `` `${$.user}` `` |
178
+ | `$.cd(path)` | Change working directory for subsequent `run`/`silent` calls |
179
+
180
+ `$.root` and `$.user` are `PathHelper` objects — they work as both functions and strings via `Symbol.toPrimitive`.
181
+
182
+ #### `CommandOutput`
183
+
184
+ Returned by `$.silent`:
185
+
186
+ | Property | Type |
187
+ |---|---|
188
+ | `.code` | `number` |
189
+ | `.output` | `string \| null` (combined stdout+stderr) |
190
+ | `.stdout` | `string \| null` |
191
+ | `.stderr` | `string \| null` |
192
+ | `.succeeded` | `boolean` |
193
+ | `.failed` | `boolean` |
194
+ | `.throw()` | Throws if failed, returns `this` if succeeded |
195
+
196
+ ### Groups
197
+
198
+ Organize commands under a prefix:
199
+
200
+ ```js
201
+ import { group } from 'zet-execute';
202
+
203
+ const db = group('db', 'Database');
204
+ db.register('migrate ...', 'Run migrations').run`docker compose exec app migrate ...`;
205
+ db.register('seed', 'Seed database').run`docker compose exec app db-seed`;
206
+ ```
207
+
208
+ ```sh
209
+ x db migrate --fresh
210
+ x db seed
211
+ ```
212
+
213
+ The names `init` and `cli` are reserved and cannot be used as group prefixes or command names.
214
+
215
+ ### Splitting Config Files
216
+
217
+ Use standard ES module imports to split your config across multiple files:
218
+
219
+ ```js
220
+ // x.config.mjs
221
+ import { register } from 'zet-execute';
222
+ import './x/docker.mjs';
223
+ import './x/deploy.mjs';
224
+
225
+ register('hello', 'Say hello').run`echo hi`;
226
+ ```
227
+
228
+ ```js
229
+ // x/docker.mjs
230
+ import { register, template } from 'zet-execute';
231
+
232
+ const compose = template((service) => ['docker', 'compose', 'exec', '-it', service]);
233
+ register('shell', 'Open shell').run`${compose('app')} bash`;
234
+ ```
235
+
236
+ Templates and groups defined in one file are available to all files — they share the same module singleton. Export a template from a shared file and import it wherever needed:
237
+
238
+ ```js
239
+ // x/shared.mjs
240
+ import { template } from 'zet-execute';
241
+ export const compose = template((service) => ['docker', 'compose', 'exec', '-it', service]);
242
+ ```
243
+
244
+ ```js
245
+ // x/docker.mjs
246
+ import { register } from 'zet-execute';
247
+ import { compose } from './shared.mjs';
248
+
249
+ register('shell', 'Open shell').run`${compose('app')} bash`;
250
+ register('logs', 'View logs').run`docker compose logs -f`;
251
+ ```
252
+
253
+ ### Config Paths
254
+
255
+ ```js
256
+ import { setAiPublishPath, setIdePublishPath, autoPublishIde } from 'zet-execute';
257
+
258
+ setAiPublishPath('docs/'); // zet-execute.md -> docs/zet-execute.md
259
+ setAiPublishPath('.claude/skills/project/SKILL.md'); // exact file path
260
+ setIdePublishPath('.types/'); // .d.ts -> .types/.x/index.d.ts
261
+ autoPublishIde(); // auto-regenerate .x/index.d.ts on every run
262
+ ```
263
+
264
+ ## Built-in Commands
265
+
266
+ ### `x init`
267
+
268
+ Creates `x.config.mjs` in the current directory with a starter command.
269
+
270
+ ### `x cli publish ai`
271
+
272
+ Generates `zet-execute.md` — an AI agent reference for your project's commands. By default writes to the project root. Configure with `setAiPublishPath()`.
273
+
274
+ ### `x cli publish ide`
275
+
276
+ Generates TypeScript declarations for IDE autocompletion. By default writes to `.x/` (with `.gitignore`). Configure with `setIdePublishPath()`.
277
+
278
+ ### `x cli init-completion <bash|zsh>`
279
+
280
+ Outputs a shell completion script. Add to your shell profile:
281
+
282
+ ```sh
283
+ # bash
284
+ eval "$(x cli init-completion bash)"
285
+
286
+ # zsh
287
+ eval "$(x cli init-completion zsh)"
288
+ ```
289
+
290
+ Common shell profile locations:
291
+ - **bash**: `~/.bashrc` or `~/.bash_profile`
292
+ - **zsh**: `~/.zshrc`
293
+
294
+ ### Auto-generated Help
295
+
296
+ ```sh
297
+ x --help # global help
298
+ x <command> --help # command-specific help
299
+ ```
300
+
301
+ ### Auto-generated Types
302
+
303
+ When `autoPublishIde()` is called in your config, `x` regenerates `.x/index.d.ts` with TypeScript declarations for IDE support on every run. This happens silently and never breaks normal operation. You can also generate types on demand with `x cli publish ide`.
304
+
305
+ ## Full Example
306
+
307
+ ```js
308
+ import { register, group, template, setAiPublishPath } from 'zet-execute';
309
+
310
+ setAiPublishPath('docs/');
311
+
312
+ const compose = template((service) => ['docker', 'compose', 'exec', '-it', service]);
313
+
314
+ // Groups
315
+ const db = group('db', 'Database');
316
+ db.register('migrate ...', 'Run migrations')
317
+ .run`${compose('app')} db-migrate ...`;
318
+ db.register('seed', 'Seed database')
319
+ .run`${compose('app')} db-seed`;
320
+
321
+ // Root commands
322
+ register('up', 'Start all containers')
323
+ .run`docker compose up -d`;
324
+
325
+ register('down', 'Stop all containers')
326
+ .run`docker compose down`;
327
+
328
+ register('deploy {env} {--Force}', 'Deploy to environment')
329
+ .callback(async ($) => {
330
+ const env = $.arg('env');
331
+ if ($.option('--force')) {
332
+ $.warn('Force deploy — skipping checks');
333
+ } else if (!await $.confirm(`Deploy to ${env}?`)) {
334
+ return;
335
+ }
336
+ $.info(`Deploying to ${env}...`);
337
+ await $.mustRun`deploy.sh ${env}`;
338
+ });
339
+ ```
340
+
341
+ ## How It Works
342
+
343
+ 1. `x` binary traverses up from CWD to find `x.config.mjs`
344
+ 2. Sets up a module resolution hook so the config can `import { register } from 'zet-execute'`
345
+ 3. Imports the config (side effects register commands), then runs the matched command
346
+ 4. Commands run from the project root — use `$.root` and `$.user` in callbacks to resolve paths, or `.userCwd()` to run from the user's directory
347
+
348
+ ## Test
349
+
350
+ ```sh
351
+ npm test
352
+ ```
package/bin/x.mjs ADDED
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
4
+ import { join, dirname } from "node:path";
5
+ import { spawn } from "node:child_process";
6
+ import { fileURLToPath, pathToFileURL } from "node:url";
7
+
8
+ const CONFIG_NAME = "x.config.mjs";
9
+
10
+ const cliArgs = process.argv.slice(2);
11
+
12
+ if (cliArgs[0] === "--version" || cliArgs[0] === "-v") {
13
+ const pkg = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), "..", "package.json"), "utf8"));
14
+ process.stdout.write(pkg.version + "\n");
15
+ process.exit(0);
16
+ }
17
+
18
+ if (cliArgs[0] === "init") {
19
+ const configFile = join(process.cwd(), "x.config.mjs");
20
+ if (existsSync(configFile)) {
21
+ process.stderr.write("x is already initialized in this directory\n");
22
+ process.exit(1);
23
+ }
24
+ writeFileSync(
25
+ configFile,
26
+ `import { register } from 'zet-execute';
27
+
28
+ register('hello', 'Say hello')
29
+ .callback(($) => {
30
+ $.info('Hello from ZET Execute!');
31
+ });
32
+ `
33
+ );
34
+ process.stdout.write("Created x.config.mjs\n");
35
+ process.exit(0);
36
+ }
37
+
38
+
39
+ if (cliArgs[0] === "cli" && cliArgs[1] === "init-completion") {
40
+ const shell = cliArgs[2];
41
+ if (shell === "bash") {
42
+ process.stdout.write(`_x_completions() {
43
+ local cur=\${COMP_WORDS[COMP_CWORD]}
44
+ local completions
45
+ if [ $COMP_CWORD -eq 1 ]; then
46
+ completions=$(x --completions 2>/dev/null)
47
+ elif [ $COMP_CWORD -eq 2 ]; then
48
+ completions=$(x --completions "\${COMP_WORDS[1]}" 2>/dev/null)
49
+ elif [ $COMP_CWORD -eq 3 ]; then
50
+ completions=$(x --completions "\${COMP_WORDS[1]}" "\${COMP_WORDS[2]}" 2>/dev/null)
51
+ fi
52
+ COMPREPLY=( $(compgen -W "$completions" -- "$cur") )
53
+ }
54
+ complete -F _x_completions x
55
+ `);
56
+ process.exit(0);
57
+ } else if (shell === "zsh") {
58
+ process.stdout.write(`#compdef x
59
+ _x() {
60
+ local -a commands
61
+ if (( CURRENT == 2 )); then
62
+ commands=(\${(f)"$(x --completions 2>/dev/null)"})
63
+ _describe 'command' commands
64
+ elif (( CURRENT == 3 )); then
65
+ commands=(\${(f)"$(x --completions \${words[2]} 2>/dev/null)"})
66
+ _describe 'subcommand' commands
67
+ elif (( CURRENT == 4 )); then
68
+ commands=(\${(f)"$(x --completions \${words[2]} \${words[3]} 2>/dev/null)"})
69
+ _describe 'subcommand' commands
70
+ fi
71
+ }
72
+ _x "$@"
73
+ `);
74
+ process.exit(0);
75
+ } else {
76
+ process.stderr.write("Usage: x cli init-completion <bash|zsh>\n");
77
+ process.exit(1);
78
+ }
79
+ }
80
+
81
+
82
+ function findConfig(startDir) {
83
+ let dir = startDir;
84
+ while (true) {
85
+ const candidate = join(dir, CONFIG_NAME);
86
+ if (existsSync(candidate)) return candidate;
87
+ const parent = dirname(dir);
88
+ if (parent === dir) break;
89
+ dir = parent;
90
+ }
91
+ return null;
92
+ }
93
+
94
+ const configPath = findConfig(process.cwd());
95
+
96
+ if (!configPath) {
97
+ process.stderr.write(
98
+ "x: cannot find x.config.mjs in the current or any parent directory\n"
99
+ );
100
+ process.exit(1);
101
+ }
102
+
103
+ // Register a module resolution hook so configs can `import { register } from 'zet-execute'`
104
+ const pkgRoot = dirname(dirname(fileURLToPath(import.meta.url)));
105
+ const [major, minor] = process.versions.node.split(".").map(Number);
106
+
107
+ const supported = (major === 18 && minor >= 19) || (major === 20 && minor >= 6) || major > 20;
108
+ if (!supported) {
109
+ const y = !process.env.NO_COLOR && process.stderr.isTTY ? "\x1b[1;33m" : "";
110
+ const r = y ? "\x1b[0m" : "";
111
+ process.stderr.write(
112
+ `${y}x: Node.js ${process.versions.node} is not supported. Requires ^18.19 or >=20.6.${r}\n`
113
+ );
114
+ }
115
+
116
+ const nodeArgs = [];
117
+
118
+ if (major > 20 || (major === 20 && minor >= 6) || (major === 18 && minor >= 19)) {
119
+ nodeArgs.push(
120
+ "--import",
121
+ pathToFileURL(join(pkgRoot, "dist", "register.js")).href
122
+ );
123
+ } else {
124
+ nodeArgs.push(
125
+ "--loader",
126
+ pathToFileURL(join(pkgRoot, "dist", "loader.js")).href
127
+ );
128
+ }
129
+
130
+ const runnerPath = join(pkgRoot, "dist", "runner.js");
131
+ const projectRoot = dirname(configPath);
132
+
133
+ const child = spawn(
134
+ process.execPath,
135
+ [...nodeArgs, runnerPath, configPath, ...process.argv.slice(2)],
136
+ {
137
+ stdio: "inherit",
138
+ env: {
139
+ ...process.env,
140
+ X_ROOT_DIR: projectRoot,
141
+ },
142
+ }
143
+ );
144
+
145
+ process.on("SIGTERM", () => child.kill("SIGTERM"));
146
+ process.on("SIGINT", () => child.kill("SIGINT"));
147
+
148
+ child.on("close", (code, signal) => {
149
+ if (signal) {
150
+ process.kill(process.pid, signal);
151
+ } else {
152
+ process.exit(code ?? 1);
153
+ }
154
+ });
@@ -0,0 +1,40 @@
1
+ import { CommandOutput } from "./shared.js";
2
+ export declare const REST_SYMBOL: unique symbol;
3
+ export declare function buildRunParts(strings: TemplateStringsArray, values: unknown[]): (string | symbol)[];
4
+ export declare function expandRestSymbol(parts: (string | symbol)[], restArgs: string[]): string[];
5
+ export declare function spawnCommand(parts: string[], options: {
6
+ stdio: "inherit" | "pipe";
7
+ cwd?: string;
8
+ }): Promise<CommandOutput>;
9
+ export interface PathHelper {
10
+ (sub?: string): string;
11
+ [Symbol.toPrimitive](): string;
12
+ toString(): string;
13
+ }
14
+ export declare function createPathHelper(basePath: string): PathHelper;
15
+ export declare class ExecutionContext {
16
+ private _args;
17
+ private _options;
18
+ private _restArgs;
19
+ private _rootDir;
20
+ private _userDir;
21
+ private _cwd;
22
+ private _rootHelper;
23
+ private _userHelper;
24
+ constructor(args: Record<string, string>, options: Record<string, string | true>, restArgs: string[], rootDir: string, userDir: string, initialCwd: string);
25
+ arg(name: string): string | null;
26
+ option(name: string): string | true | null;
27
+ run(stringsOrParts: TemplateStringsArray | unknown, ...values: unknown[]): Promise<CommandOutput>;
28
+ mustRun(stringsOrParts: TemplateStringsArray | unknown, ...values: unknown[]): Promise<CommandOutput>;
29
+ silent(stringsOrParts: TemplateStringsArray | unknown, ...values: unknown[]): Promise<CommandOutput>;
30
+ mustSilent(stringsOrParts: TemplateStringsArray | unknown, ...values: unknown[]): Promise<CommandOutput>;
31
+ info(msg: string): void;
32
+ warn(msg: string): void;
33
+ error(msg: string): void;
34
+ confirm(msg: string): Promise<boolean>;
35
+ prompt(msg: string): Promise<string>;
36
+ get root(): PathHelper;
37
+ get user(): PathHelper;
38
+ cd(path: string): void;
39
+ }
40
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAgC,MAAM,aAAa,CAAC;AAG1E,eAAO,MAAM,WAAW,EAAE,OAAO,MAAuB,CAAC;AAGzD,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CA4BnG;AAGD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAUzF;AAGD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE;IAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CA6C1H;AAGD,MAAM,WAAW,UAAU;IACzB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,MAAM,CAAC;IAC/B,QAAQ,IAAI,MAAM,CAAC;CACpB;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAK7D;AAGD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,WAAW,CAAa;gBAG9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,EACtC,QAAQ,EAAE,MAAM,EAAE,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM;IAYpB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIhC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI;IAI1C,GAAG,CAAC,cAAc,EAAE,oBAAoB,GAAG,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC;IAW3F,OAAO,CAAC,cAAc,EAAE,oBAAoB,GAAG,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC;IAK3G,MAAM,CAAC,cAAc,EAAE,oBAAoB,GAAG,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC;IAW9F,UAAU,CAAC,cAAc,EAAE,oBAAoB,GAAG,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC;IAK9G,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIvB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIvB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIlB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAetC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAc1C,IAAI,IAAI,IAAI,UAAU,CAErB;IAED,IAAI,IAAI,IAAI,UAAU,CAErB;IAED,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAGvB"}