@lowlighter/run 3.0.0 → 3.4.1

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/README.md CHANGED
@@ -16,12 +16,12 @@
16
16
  ```ts
17
17
  import { command } from "./command.ts"
18
18
 
19
- // Commands are run asynchronously, and support Deno.command options alongside additional options
20
- // For example, stdio can also be set to a Logger level too or you can automatically append an extension when running on Windows
21
- await command("deno", ["version"], { stdout: "debug", stderr: "piped", winext: ".exe" })
19
+ // Commands are run asynchronously, and support Deno.Command options alongside additional options
20
+ // Piped channels are captured into the result and mirrored to a LogTape sub-logger; you can also automatically append an extension when running on Windows
21
+ await command("deno", ["--version"], { stdout: "piped", stderr: "piped", winext: ".exe" })
22
22
 
23
23
  // Commands can be run synchronously too, and can also throw an error automatically when the process exits with a non-zero code
24
- command("deno", ["version"], { sync: true, throw: true })
24
+ command("deno", ["--version"], { sync: true, throw: true })
25
25
  ```
26
26
 
27
27
  ### Writing to stdin
@@ -31,15 +31,16 @@ import { command } from "./command.ts"
31
31
 
32
32
  const { stdout } = await command("deno", ["repl"], {
33
33
  env: { NO_COLOR: "true" },
34
- // Passing a callback will automatically set `stdin` to `"piped"`
35
- // You can then write to the process using utility functions
36
- callback: async ({ i, stdio, write, close, wait }) => {
37
- if ((!stdio.stdout.includes("exit using")) || i) {
34
+ // Passing a callback automatically pipes stdin.
35
+ // The callback is an async generator: `for await` over `stdio` to react to output,
36
+ // `yield` to write to stdin (verbatim add your own newlines), and `return` to close it.
37
+ callback: async function* ({ stdio }) {
38
+ for await (const { stdout } of stdio) {
39
+ if (!stdout.includes("exit using"))
40
+ continue
41
+ yield "console.log('hello')\n"
38
42
  return
39
43
  }
40
- await write("console.log('hello')")
41
- await wait(1000)
42
- close()
43
44
  },
44
45
  })
45
46
  console.assert(stdout.includes("hello"))
@@ -47,12 +48,28 @@ console.assert(stdout.includes("hello"))
47
48
 
48
49
  ## ✨ Features
49
50
 
50
- - Supports `stdin` interactivity through callbacks.
51
- - Make it possible to monitor `stdout` and `stderr` content and react accordingly.
51
+ - Supports `stdin` interactivity through an async generator callback.
52
+ - `for await` over process output, `yield` to write to stdin, `return` to close it.
52
53
  - Auto-detects os and can automatically append an extension when running on Windows.
53
54
  - Supports both `sync` and `async` modes in a single function.
54
55
  - Optionally decide to throw an error when the process exits with a non-zero code.
56
+ - Background processes support `await using` for automatic cleanup (killed and awaited on scope exit).
55
57
  - Generates a `stdio` history that contains timestamped entries with configurable buffering
58
+ - Integrates with [`LogTape`](https://logtape.org): each piped channel is mirrored to a sub-logger (`stdin`/`stdout`/`stderr`).
59
+ - Logging defaults to the `["run"]` category, leaving output configuration to the host application.
60
+
61
+ ## 🕊️ Migrating from `3.x.x` to `4.x.x`
62
+
63
+ Version `4.x.x` replaces the [`@libs/logger`](https://jsr.io/@libs/logger) dependency with [`LogTape`](https://logtape.org) and reworks the stdin callback:
64
+
65
+ - The `logger` option is now a category (`string[]`) forwarded to `getLogger()`, defaulting to `["run"]`.
66
+ - As recommended for libraries, `command()` never calls `configure()` — the host application is in charge of setting up sinks and levels.
67
+ - Each channel is mirrored to a sub-logger: `stdin` at `debug`, `stdout` at `info`, `stderr` at `error`.
68
+ - The `stdin`, `stdout` and `stderr` options now only accept `"piped"`, `"inherit"` or `null` (log levels are no longer set per-channel).
69
+ - The `callback` option is now an **async generator** instead of a function:
70
+ - `for await (const { stdout } of stdio)` to react to output, `yield "text"` to write to stdin (verbatim, no automatic newline), and `return` to close it.
71
+ - The `write()`, `close()` and `wait()` helpers are gone — use `yield`, `return` and `await` respectively.
72
+ - If the generator throws, stdin is closed, the process is killed, and the result rejects with the error.
56
73
 
57
74
  ## 🕊️ Migrating from `2.x.x` to `3.x.x`
58
75
 
package/command.d.ts ADDED
@@ -0,0 +1,138 @@
1
+ import type { Nullable, Promisable } from "@lowlighter/typing";
2
+ import { type Logger } from "@logtape/logtape";
3
+ export type { Logger, Promisable };
4
+ /**
5
+ * Handling of a stdio channel.
6
+ * - `"piped"`: the channel is captured into the {@link Result} and mirrored to a {@link https://logtape.org | LogTape} sub-logger.
7
+ * - `"inherit"`: the channel is forwarded to the parent process.
8
+ * - `null`: the channel is discarded.
9
+ */ export type Channel = Nullable<"piped" | "inherit">;
10
+ /** Run options. */ export type Options = {
11
+ /**
12
+ * Logger categories forwarded to {@link https://logtape.org | LogTape}'s `getLogger()`.
13
+ * Each channel is mirrored through a sub-category (`stdin`, `stdout`, `stderr`) so the host application can route or filter them.
14
+ * Defaults to `["run"]`.
15
+ */ logger?: string[];
16
+ /** Environment variables. */ env?: Deno.CommandOptions["env"];
17
+ /** Current working directory. */ cwd?: Deno.CommandOptions["cwd"];
18
+ /** Raw arguments (Windows only). */ raw?: boolean;
19
+ /** Handling of stdin. */ stdin?: Channel;
20
+ /** Handling of stdout. */ stdout?: Channel;
21
+ /** Handling of stderr. */ stderr?: Channel;
22
+ /**
23
+ * Stdin interaction callback.
24
+ * Passing this option automatically pipes stdin.
25
+ * See {@link Callback} for the interaction protocol.
26
+ */ callback?: Callback;
27
+ /**
28
+ * Stdio buffering.
29
+ * This is used to merge messages that are received relatively closely.
30
+ * Buffering is skipped when a different channel is used in-between.
31
+ */ buffering?: number;
32
+ /** Abort signal. */ signal?: Deno.CommandOptions["signal"];
33
+ /**
34
+ * Execute process synchronously.
35
+ * Note that stdin is not usable in sync mode.
36
+ */ sync?: boolean;
37
+ /**
38
+ * Run process in background.
39
+ * This implies `sync: false`.
40
+ */ background?: boolean;
41
+ /** Process extension on Windows. */ winext?: string;
42
+ /** Operating system. */ os?: typeof Deno.build.os;
43
+ /** Throw an error if exit code is non-zero rather than returning a result. */ throw?: boolean;
44
+ /**
45
+ * Do not actually execute the command.
46
+ * In this case you will instead receive an empty successful result object.
47
+ */ dryrun?: boolean;
48
+ };
49
+ /** Run result. */ export type Result = {
50
+ /** Whether the process exited with a zero-code. */ success: Deno.CommandStatus["success"];
51
+ /** Process exit code. */ code: Deno.CommandStatus["code"];
52
+ /**
53
+ * Process stdio content.
54
+ * First element is the delta timestamp since process start, second element is the channel (0:stdin, 1:stdout, 2:stderr), third element is the content.
55
+ */ stdio: Array<[number, 0 | 1 | 2, string]>;
56
+ /** Process stdin content. */ stdin: string;
57
+ /** Process stdout content. */ stdout: string;
58
+ /** Process stderr content. */ stderr: string;
59
+ };
60
+ /** Handle to a process running in background. */ export type Background = {
61
+ /** Send a signal to the process (defaults to `"SIGTERM"`). */ kill: (signal?: Deno.Signal) => Promise<void>;
62
+ /** Prevent the process from keeping the parent process alive. */ unref: () => void;
63
+ /** Process identifier. */ pid: number;
64
+ /** Process result (resolves once the process exits). */ result: Promise<Result>;
65
+ /** Kill the process and wait for it to fully terminate. */ [Symbol.asyncDispose]: () => Promise<void>;
66
+ };
67
+ /** Snapshot of the accumulated process stdio content. */ export type Snapshot = Pick<Result, "stdin" | "stdout" | "stderr">;
68
+ /**
69
+ * Stdin interaction callback.
70
+ *
71
+ * It is an async generator that lets you drive an interactive process with plain language constructs:
72
+ * ```ts ignore
73
+ * // Iterate over process output to react to new data.
74
+ * // (one iteration per buffered event)
75
+ * for await (const { stdout } of stdio) {
76
+ * // Use await to pause or poll for a condition
77
+ * await delay(1000)
78
+ * // Use yield to write to stdin (verbatim)
79
+ * yield "content\n"
80
+ * // Use return to close stdin and end the interaction
81
+ * return
82
+ * }
83
+ * ```
84
+ *
85
+ * If the generator throws, stdin is closed, the process is killed and the returned {@link Result} rejects with the thrown error.
86
+ * When the process exits on its own, the `stdio` iterator ends, so a generator parked on `for await` completes naturally.
87
+ */ export type Callback = (options: {
88
+ stdio: AsyncIterable<Snapshot>;
89
+ }) => AsyncGenerator<string, void, unknown>;
90
+ /**
91
+ * Asynchronous version of {@link command} running in background.
92
+ *
93
+ * ```ts
94
+ * import { command } from "./command.ts"
95
+ * const process = command("deno", ["eval", "Deno.exit(0)"], { background: true })
96
+ * await process.kill()
97
+ * ```
98
+ */ export declare function command(bin: string, args: string[], options?: Options & {
99
+ sync?: false;
100
+ background: true;
101
+ }): Background;
102
+ /**
103
+ * Asynchronous version of {@link command}.
104
+ *
105
+ * ```ts
106
+ * import { command } from "./command.ts"
107
+ * try {
108
+ * await command("deno", ["eval", "Deno.exit(1)"], { throw: true })
109
+ * }
110
+ * catch (error) {
111
+ * console.log(error)
112
+ * }
113
+ * ```
114
+ */ export declare function command(bin: string, args: string[], options?: Options & {
115
+ sync?: false;
116
+ background?: false;
117
+ }): Promise<Result>;
118
+ /**
119
+ * Synchronous version of {@link command}.
120
+ *
121
+ * Note that stdin is not usable in sync mode and will always be empty.
122
+ *
123
+ * ```ts
124
+ * import { command } from "./command.ts"
125
+ * command("deno", ["--version"], { sync: true })
126
+ * ```
127
+ * ```ts
128
+ * import { command } from "./command.ts"
129
+ * try {
130
+ * command("deno", ["eval", "Deno.exit(1)"], { sync: true, throw: true })
131
+ * }
132
+ * catch (error) {
133
+ * console.log(error)
134
+ * }
135
+ * ```
136
+ */ export declare function command(bin: string, args: string[], options?: Options & {
137
+ sync: true;
138
+ }): Result;
package/command.js ADDED
@@ -0,0 +1,339 @@
1
+ // Imports
2
+ import { getLogger } from "@logtape/logtape";
3
+ import { TextLineStream } from "@std/streams";
4
+ import { debounce } from "@std/async/debounce";
5
+ /** Text encoder */ const encoder = new TextEncoder();
6
+ /** Text decoder */ const decoder = new TextDecoder();
7
+ /** Default interaction: an empty generator that closes stdin immediately. */ const noop = async function*() {};
8
+ /**
9
+ * Run a command.
10
+ *
11
+ * This is a wrapper around {@link https://docs.deno.com/api/deno/~/Deno.Command | Deno.Command} that provides a better handling of stdio for interactive processes.
12
+ *
13
+ * Like `Deno.Command`, the `env`, `cwd`, and `raw` (alias for `windowsRawArguments`) options are supported.
14
+ *
15
+ * The `stdin`, `stdout` and `stderr` options accept `"piped"` (captured into the result and mirrored to a {@link https://logtape.org | LogTape} sub-logger), `"inherit"` (forwarded to the parent process) or `null` (discarded).
16
+ *
17
+ * Logging is performed through {@link https://logtape.org | LogTape}.
18
+ * The `logger` option is a category forwarded to `getLogger()` (defaulting to `["run"]`), and each channel is mirrored through its own sub-category — `stdin` at `debug`, `stdout` at `info`, `stderr` at `error`.
19
+ * As recommended for libraries, `command()` never configures LogTape itself: the host application is in charge of the actual output (through {@link https://logtape.org/manual/config | LogTape configuration}).
20
+ *
21
+ * Set `winext` option to automatically append an extension to the binary path on Windows (like `.cmd` or `.exe`).
22
+ * This is useful when the binary path isn't automatically resolved on Windows.
23
+ *
24
+ * Pass a `callback` option (an async generator) to interact with the process stdin.
25
+ * See {@link Callback} for the interaction protocol: `for await` over `stdio` to read output, `yield` to write to stdin, `return` to close it.
26
+ *
27
+ * The `buffering` option is used to merge messages that are received relatively closely.
28
+ * Setting this option to a low value will also increase the rate at which the interaction generator is resumed.
29
+ *
30
+ * Resulting object contains the same properties as {@link https://docs.deno.com/api/deno/~/Deno.CommandStatus | Deno.CommandStatus}
31
+ * with an additional `stdio` property that contains an array of ordered tuples with the delta timestamp since process start, the channel idenfitier (0:stdin, 1:stdout, 2:stderr) and the content.
32
+ * This offers a proper history of exchanged content.
33
+ *
34
+ * ```ts
35
+ * import { command } from "./command.ts"
36
+ * await command("deno", ["--version"], { env: { NO_COLOR: "true" }, cwd: "/tmp", raw: true })
37
+ * await command("deno", ["--version"], { stdout: "piped" })
38
+ * await command("deno", ["--version"], { logger: ["my-app", "run"], stdout: "piped" })
39
+ * await command("deno", ["--version"], { winext: ".exe" })
40
+ * ```
41
+ *
42
+ * ```ts
43
+ * import { command } from "./command.ts"
44
+ *
45
+ * const { stdout } = await command("deno", ["repl"], {
46
+ * env: { NO_COLOR: "true" },
47
+ * // Passing a callback automatically pipes stdin.
48
+ * // Iterate `stdio` to react to output, `yield` to write to stdin (verbatim), `return` to close it.
49
+ * callback: async function* ({ stdio }) {
50
+ * for await (const { stdout } of stdio) {
51
+ * if (!stdout.includes("exit using")) {
52
+ * continue
53
+ * }
54
+ * yield "console.log('hello')\n"
55
+ * return
56
+ * }
57
+ * },
58
+ * })
59
+ * console.assert(stdout.includes("hello"))
60
+ * ```
61
+ *
62
+ * @author Simon Lecoq (lowlighter)
63
+ * @license MIT
64
+ * @module
65
+ */ export function command(bin, args, { logger: category = [
66
+ "run"
67
+ ], stdin = null, stdout = "piped", stderr = "piped", env, cwd, raw, callback, buffering, signal, sync, background, throw: _throw, dryrun, winext = "", os = Deno.build.os } = {}) {
68
+ if (os === "windows") bin = `${bin}${winext}`;
69
+ const log = getLogger(category).with({
70
+ bin
71
+ });
72
+ if (callback && handle(stdin) !== "piped") stdin = "piped";
73
+ const command1 = new Deno.Command(bin, {
74
+ args,
75
+ stdin: !sync ? handle(stdin) : "null",
76
+ stdout: handle(stdout),
77
+ stderr: handle(stderr),
78
+ clearEnv: true,
79
+ env,
80
+ cwd,
81
+ windowsRawArguments: raw,
82
+ signal,
83
+ detached: background
84
+ });
85
+ if (dryrun) {
86
+ log.warn("dryrun: {bin} not executed", {
87
+ bin
88
+ });
89
+ const result = {
90
+ success: true,
91
+ code: 0,
92
+ stdio: [],
93
+ stdin: "",
94
+ stdout: "",
95
+ stderr: ""
96
+ };
97
+ return sync ? result : Promise.resolve(result);
98
+ }
99
+ if (sync) return exec(command1, {
100
+ bin,
101
+ log,
102
+ throw: _throw,
103
+ stdout,
104
+ stderr
105
+ });
106
+ return spawn(command1, {
107
+ bin,
108
+ log,
109
+ callback,
110
+ buffering,
111
+ throw: _throw,
112
+ background,
113
+ stdin,
114
+ stdout,
115
+ stderr
116
+ });
117
+ }
118
+ /** Returns the handle type for a given mode. */ function handle(mode) {
119
+ return [
120
+ "inherit",
121
+ "null"
122
+ ].includes(`${mode}`) ? `${mode}` : "piped";
123
+ }
124
+ /** Execute a command synchronously. */ function exec(command, { bin, log, throw: _throw, stdout, stderr }) {
125
+ const start = Date.now();
126
+ const output = command.outputSync();
127
+ const { success, code } = output // Do not access stdout or stderr before "piped" status check
128
+ ;
129
+ const t = Date.now() - start;
130
+ const stdio = {
131
+ get stdio () {
132
+ return [
133
+ [
134
+ t,
135
+ 1,
136
+ this.stdout
137
+ ],
138
+ [
139
+ t,
140
+ 2,
141
+ this.stderr
142
+ ]
143
+ ];
144
+ },
145
+ stdin: "",
146
+ stdout: handle(stdout) === "piped" ? decoder.decode(output.stdout) : "",
147
+ stderr: handle(stderr) === "piped" ? decoder.decode(output.stderr) : ""
148
+ };
149
+ for (const { channel, mode } of [
150
+ {
151
+ channel: "stdout",
152
+ mode: stdout
153
+ },
154
+ {
155
+ channel: "stderr",
156
+ mode: stderr
157
+ }
158
+ ]){
159
+ if (handle(mode) === "piped" && stdio[channel]) logged(log, channel, t, stdio[channel]);
160
+ }
161
+ if (!success && _throw) throw new EvalError(`${bin} exited with non-zero code ${code}:\n${stdio.stdout}\n${stdio.stderr}`);
162
+ return {
163
+ success,
164
+ code,
165
+ ...stdio
166
+ };
167
+ }
168
+ /** Spawn a command. */ function spawn(command, { bin, log, callback = noop, buffering = 250, throw: _throw, background, ...channels }) {
169
+ const process = command.spawn();
170
+ const status = process.status;
171
+ const start = Date.now();
172
+ const stdio = {
173
+ stdio: [],
174
+ get stdin () {
175
+ return this.stdio.filter(([_, i])=>i === 0).map(([_, __, content])=>content).join("");
176
+ },
177
+ get stdout () {
178
+ return this.stdio.filter(([_, i])=>i === 1).map(([_, __, content])=>content).join("\n");
179
+ },
180
+ get stderr () {
181
+ return this.stdio.filter(([_, i])=>i === 2).map(([_, __, content])=>content).join("\n");
182
+ }
183
+ };
184
+ let last = "";
185
+ // Drive the interaction generator when stdin is piped
186
+ let release = ()=>{};
187
+ let notify = null;
188
+ let pending = true;
189
+ let ended = false;
190
+ let exited = false;
191
+ let interaction = Promise.resolve();
192
+ if (handle(channels.stdin) === "piped") {
193
+ const writer = process.stdin.getWriter();
194
+ const close = async ()=>{
195
+ try {
196
+ await writer.close();
197
+ log.with({
198
+ t: Date.now() - start
199
+ }).trace("closed stdin");
200
+ } catch {
201
+ // Ignore (stdin may already be closed if the process exited)
202
+ }
203
+ };
204
+ release = ()=>{
205
+ ended = true;
206
+ notify?.();
207
+ notify = null;
208
+ };
209
+ const input = {
210
+ async *[Symbol.asyncIterator] () {
211
+ while(true){
212
+ if (pending) {
213
+ pending = false;
214
+ yield stdio;
215
+ continue;
216
+ }
217
+ if (ended) return;
218
+ await new Promise((resolve)=>notify = resolve);
219
+ }
220
+ }
221
+ };
222
+ interaction = (async ()=>{
223
+ const generator = callback({
224
+ stdio: input
225
+ });
226
+ try {
227
+ for await (const content of generator){
228
+ if (exited) throw new EvalError("Cannot write to stdin: process already exited");
229
+ const t = Date.now() - start;
230
+ logged(log, "stdin", t, `${content}`);
231
+ stdio.stdio.push([
232
+ t,
233
+ 0,
234
+ `${content}`
235
+ ]);
236
+ await writer.write(encoder.encode(`${content}`));
237
+ last = "stdin";
238
+ }
239
+ await close();
240
+ } catch (error) {
241
+ await close();
242
+ abort(process);
243
+ await status;
244
+ throw error;
245
+ }
246
+ })();
247
+ }
248
+ // Buffer output and resume the interaction generator
249
+ const debounced = debounce(()=>{
250
+ last = "";
251
+ pending = true;
252
+ notify?.();
253
+ notify = null;
254
+ }, buffering);
255
+ const outputs = Promise.all([
256
+ "stdout",
257
+ "stderr"
258
+ ].filter((channel)=>handle(channels[channel]) === "piped").map(async (channel)=>{
259
+ for await (const line of process[channel].pipeThrough(new TextDecoderStream()).pipeThrough(new TextLineStream())){
260
+ const t = Date.now() - start;
261
+ const stdi = {
262
+ stdout: 1,
263
+ stderr: 2
264
+ }[channel];
265
+ logged(log, channel, t, line);
266
+ if (stdio.stdio.length && last === channel) {
267
+ const previous = stdio.stdio.at(-1);
268
+ if (previous[1] === stdi) previous[2] += `\n${line}`;
269
+ } else {
270
+ stdio.stdio.push([
271
+ t,
272
+ stdi,
273
+ line
274
+ ]);
275
+ }
276
+ last = channel;
277
+ debounced();
278
+ }
279
+ }));
280
+ const settle = ()=>{
281
+ exited = true;
282
+ release();
283
+ };
284
+ void status.then(settle, settle);
285
+ // Compute result
286
+ const result = (async ()=>{
287
+ const [output, interacted] = await Promise.allSettled([
288
+ outputs,
289
+ interaction
290
+ ]);
291
+ debounced.clear();
292
+ const { success, code } = await status;
293
+ if (output.status === "rejected" || interacted.status === "rejected") throw output.reason ?? interacted.reason;
294
+ if (!success && _throw) throw new EvalError(`${bin} exited with non-zero code ${code}:\n${stdio.stdout}\n${stdio.stderr}`);
295
+ return {
296
+ success,
297
+ code,
298
+ ...stdio
299
+ };
300
+ })();
301
+ const terminate = async (signal = "SIGTERM")=>{
302
+ abort(process, signal);
303
+ await result.catch(()=>{});
304
+ };
305
+ return background ? {
306
+ kill: terminate,
307
+ unref: ()=>process.unref(),
308
+ pid: process.pid,
309
+ result,
310
+ [Symbol.asyncDispose]: ()=>terminate()
311
+ } : result;
312
+ }
313
+ /** Send a signal to a process, ignoring the error raised when it has already terminated. */ function abort(process, signal = "SIGTERM") {
314
+ try {
315
+ process.kill(signal);
316
+ } catch {
317
+ // Already terminated
318
+ }
319
+ }
320
+ /** Mirror a stdio line through the channel's sub-logger. */ function logged(log, channel, t, content) {
321
+ const logger = log.getChild(channel).with({
322
+ t
323
+ });
324
+ switch(channel){
325
+ case "stdin":
326
+ return void logger.debug("{content}", {
327
+ content
328
+ });
329
+ case "stdout":
330
+ return void logger.info("{content}", {
331
+ content
332
+ });
333
+ case "stderr":
334
+ return void logger.error("{content}", {
335
+ content
336
+ });
337
+ }
338
+ }
339
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9saWJzL2xpYnMvQGxpYnMvcnVuL2NvbW1hbmQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gSW1wb3J0c1xuaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSwgUHJvbWlzYWJsZSB9IGZyb20gXCJAbGlicy90eXBpbmdcIlxuaW1wb3J0IHsgZ2V0TG9nZ2VyLCB0eXBlIExvZ2dlciB9IGZyb20gXCJAbG9ndGFwZS9sb2d0YXBlXCJcbmltcG9ydCB7IFRleHRMaW5lU3RyZWFtIH0gZnJvbSBcIkBzdGQvc3RyZWFtc1wiXG5pbXBvcnQgeyBkZWJvdW5jZSB9IGZyb20gXCJAc3RkL2FzeW5jL2RlYm91bmNlXCJcbmV4cG9ydCB0eXBlIHsgTG9nZ2VyLCBQcm9taXNhYmxlIH1cblxuLyoqXG4gKiBIYW5kbGluZyBvZiBhIHN0ZGlvIGNoYW5uZWwuXG4gKiAtIGBcInBpcGVkXCJgOiB0aGUgY2hhbm5lbCBpcyBjYXB0dXJlZCBpbnRvIHRoZSB7QGxpbmsgUmVzdWx0fSBhbmQgbWlycm9yZWQgdG8gYSB7QGxpbmsgaHR0cHM6Ly9sb2d0YXBlLm9yZyB8IExvZ1RhcGV9IHN1Yi1sb2dnZXIuXG4gKiAtIGBcImluaGVyaXRcImA6IHRoZSBjaGFubmVsIGlzIGZvcndhcmRlZCB0byB0aGUgcGFyZW50IHByb2Nlc3MuXG4gKiAtIGBudWxsYDogdGhlIGNoYW5uZWwgaXMgZGlzY2FyZGVkLlxuICovXG5leHBvcnQgdHlwZSBDaGFubmVsID0gTnVsbGFibGU8XCJwaXBlZFwiIHwgXCJpbmhlcml0XCI+XG5cbi8qKiBSdW4gb3B0aW9ucy4gKi9cbmV4cG9ydCB0eXBlIE9wdGlvbnMgPSB7XG4gIC8qKlxuICAgKiBMb2dnZXIgY2F0ZWdvcmllcyBmb3J3YXJkZWQgdG8ge0BsaW5rIGh0dHBzOi8vbG9ndGFwZS5vcmcgfCBMb2dUYXBlfSdzIGBnZXRMb2dnZXIoKWAuXG4gICAqIEVhY2ggY2hhbm5lbCBpcyBtaXJyb3JlZCB0aHJvdWdoIGEgc3ViLWNhdGVnb3J5IChgc3RkaW5gLCBgc3Rkb3V0YCwgYHN0ZGVycmApIHNvIHRoZSBob3N0IGFwcGxpY2F0aW9uIGNhbiByb3V0ZSBvciBmaWx0ZXIgdGhlbS5cbiAgICogRGVmYXVsdHMgdG8gYFtcInJ1blwiXWAuXG4gICAqL1xuICBsb2dnZXI/OiBzdHJpbmdbXVxuICAvKiogRW52aXJvbm1lbnQgdmFyaWFibGVzLiAqL1xuICBlbnY/OiBEZW5vLkNvbW1hbmRPcHRpb25zW1wiZW52XCJdXG4gIC8qKiBDdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5LiAqL1xuICBjd2Q/OiBEZW5vLkNvbW1hbmRPcHRpb25zW1wiY3dkXCJdXG4gIC8qKiBSYXcgYXJndW1lbnRzIChXaW5kb3dzIG9ubHkpLiAqL1xuICByYXc/OiBib29sZWFuXG4gIC8qKiBIYW5kbGluZyBvZiBzdGRpbi4gKi9cbiAgc3RkaW4/OiBDaGFubmVsXG4gIC8qKiBIYW5kbGluZyBvZiBzdGRvdXQuICovXG4gIHN0ZG91dD86IENoYW5uZWxcbiAgLyoqIEhhbmRsaW5nIG9mIHN0ZGVyci4gKi9cbiAgc3RkZXJyPzogQ2hhbm5lbFxuICAvKipcbiAgICogU3RkaW4gaW50ZXJhY3Rpb24gY2FsbGJhY2suXG4gICAqIFBhc3NpbmcgdGhpcyBvcHRpb24gYXV0b21hdGljYWxseSBwaXBlcyBzdGRpbi5cbiAgICogU2VlIHtAbGluayBDYWxsYmFja30gZm9yIHRoZSBpbnRlcmFjdGlvbiBwcm90b2NvbC5cbiAgICovXG4gIGNhbGxiYWNrPzogQ2FsbGJhY2tcbiAgLyoqXG4gICAqIFN0ZGlvIGJ1ZmZlcmluZy5cbiAgICogVGhpcyBpcyB1c2VkIHRvIG1lcmdlIG1lc3NhZ2VzIHRoYXQgYXJlIHJlY2VpdmVkIHJlbGF0aXZlbHkgY2xvc2VseS5cbiAgICogQnVmZmVyaW5nIGlzIHNraXBwZWQgd2hlbiBhIGRpZmZlcmVudCBjaGFubmVsIGlzIHVzZWQgaW4tYmV0d2Vlbi5cbiAgICovXG4gIGJ1ZmZlcmluZz86IG51bWJlclxuICAvKiogQWJvcnQgc2lnbmFsLiAqL1xuICBzaWduYWw/OiBEZW5vLkNvbW1hbmRPcHRpb25zW1wic2lnbmFsXCJdXG4gIC8qKlxuICAgKiBFeGVjdXRlIHByb2Nlc3Mgc3luY2hyb25vdXNseS5cbiAgICogTm90ZSB0aGF0IHN0ZGluIGlzIG5vdCB1c2FibGUgaW4gc3luYyBtb2RlLlxuICAgKi9cbiAgc3luYz86IGJvb2xlYW5cbiAgLyoqXG4gICAqIFJ1biBwcm9jZXNzIGluIGJhY2tncm91bmQuXG4gICAqIFRoaXMgaW1wbGllcyBgc3luYzogZmFsc2VgLlxuICAgKi9cbiAgYmFja2dyb3VuZD86IGJvb2xlYW5cbiAgLyoqIFByb2Nlc3MgZXh0ZW5zaW9uIG9uIFdpbmRvd3MuICovXG4gIHdpbmV4dD86IHN0cmluZ1xuICAvKiogT3BlcmF0aW5nIHN5c3RlbS4gKi9cbiAgb3M/OiB0eXBlb2YgRGVuby5idWlsZC5vc1xuICAvKiogVGhyb3cgYW4gZXJyb3IgaWYgZXhpdCBjb2RlIGlzIG5vbi16ZXJvIHJhdGhlciB0aGFuIHJldHVybmluZyBhIHJlc3VsdC4gKi9cbiAgdGhyb3c/OiBib29sZWFuXG4gIC8qKlxuICAgKiBEbyBub3QgYWN0dWFsbHkgZXhlY3V0ZSB0aGUgY29tbWFuZC5cbiAgICogSW4gdGhpcyBjYXNlIHlvdSB3aWxsIGluc3RlYWQgcmVjZWl2ZSBhbiBlbXB0eSBzdWNjZXNzZnVsIHJlc3VsdCBvYmplY3QuXG4gICAqL1xuICBkcnlydW4/OiBib29sZWFuXG59XG5cbi8qKiBSdW4gcmVzdWx0LiAqL1xuZXhwb3J0IHR5cGUgUmVzdWx0ID0ge1xuICAvKiogV2hldGhlciB0aGUgcHJvY2VzcyBleGl0ZWQgd2l0aCBhIHplcm8tY29kZS4gKi9cbiAgc3VjY2VzczogRGVuby5Db21tYW5kU3RhdHVzW1wic3VjY2Vzc1wiXVxuICAvKiogUHJvY2VzcyBleGl0IGNvZGUuICovXG4gIGNvZGU6IERlbm8uQ29tbWFuZFN0YXR1c1tcImNvZGVcIl1cbiAgLyoqXG4gICAqIFByb2Nlc3Mgc3RkaW8gY29udGVudC5cbiAgICogRmlyc3QgZWxlbWVudCBpcyB0aGUgZGVsdGEgdGltZXN0YW1wIHNpbmNlIHByb2Nlc3Mgc3RhcnQsIHNlY29uZCBlbGVtZW50IGlzIHRoZSBjaGFubmVsICgwOnN0ZGluLCAxOnN0ZG91dCwgMjpzdGRlcnIpLCB0aGlyZCBlbGVtZW50IGlzIHRoZSBjb250ZW50LlxuICAgKi9cbiAgc3RkaW86IEFycmF5PFtudW1iZXIsIDAgfCAxIHwgMiwgc3RyaW5nXT5cbiAgLyoqIFByb2Nlc3Mgc3RkaW4gY29udGVudC4gKi9cbiAgc3RkaW46IHN0cmluZ1xuICAvKiogUHJvY2VzcyBzdGRvdXQgY29udGVudC4gKi9cbiAgc3Rkb3V0OiBzdHJpbmdcbiAgLyoqIFByb2Nlc3Mgc3RkZXJyIGNvbnRlbnQuICovXG4gIHN0ZGVycjogc3RyaW5nXG59XG5cbi8qKiBIYW5kbGUgdG8gYSBwcm9jZXNzIHJ1bm5pbmcgaW4gYmFja2dyb3VuZC4gKi9cbmV4cG9ydCB0eXBlIEJhY2tncm91bmQgPSB7XG4gIC8qKiBTZW5kIGEgc2lnbmFsIHRvIHRoZSBwcm9jZXNzIChkZWZhdWx0cyB0byBgXCJTSUdURVJNXCJgKS4gKi9cbiAga2lsbDogKHNpZ25hbD86IERlbm8uU2lnbmFsKSA9PiBQcm9taXNlPHZvaWQ+XG4gIC8qKiBQcmV2ZW50IHRoZSBwcm9jZXNzIGZyb20ga2VlcGluZyB0aGUgcGFyZW50IHByb2Nlc3MgYWxpdmUuICovXG4gIHVucmVmOiAoKSA9PiB2b2lkXG4gIC8qKiBQcm9jZXNzIGlkZW50aWZpZXIuICovXG4gIHBpZDogbnVtYmVyXG4gIC8qKiBQcm9jZXNzIHJlc3VsdCAocmVzb2x2ZXMgb25jZSB0aGUgcHJvY2VzcyBleGl0cykuICovXG4gIHJlc3VsdDogUHJvbWlzZTxSZXN1bHQ+XG4gIC8qKiBLaWxsIHRoZSBwcm9jZXNzIGFuZCB3YWl0IGZvciBpdCB0byBmdWxseSB0ZXJtaW5hdGUuICovXG4gIFtTeW1ib2wuYXN5bmNEaXNwb3NlXTogKCkgPT4gUHJvbWlzZTx2b2lkPlxufVxuXG4vKiogU25hcHNob3Qgb2YgdGhlIGFjY3VtdWxhdGVkIHByb2Nlc3Mgc3RkaW8gY29udGVudC4gKi9cbmV4cG9ydCB0eXBlIFNuYXBzaG90ID0gUGljazxSZXN1bHQsIFwic3RkaW5cIiB8IFwic3Rkb3V0XCIgfCBcInN0ZGVyclwiPlxuXG4vKipcbiAqIFN0ZGluIGludGVyYWN0aW9uIGNhbGxiYWNrLlxuICpcbiAqIEl0IGlzIGFuIGFzeW5jIGdlbmVyYXRvciB0aGF0IGxldHMgeW91IGRyaXZlIGFuIGludGVyYWN0aXZlIHByb2Nlc3Mgd2l0aCBwbGFpbiBsYW5ndWFnZSBjb25zdHJ1Y3RzOlxuICogYGBgdHMgaWdub3JlXG4gKiAvLyBJdGVyYXRlIG92ZXIgcHJvY2VzcyBvdXRwdXQgdG8gcmVhY3QgdG8gbmV3IGRhdGEuXG4gKiAvLyAob25lIGl0ZXJhdGlvbiBwZXIgYnVmZmVyZWQgZXZlbnQpXG4gKiBmb3IgYXdhaXQgKGNvbnN0IHsgc3Rkb3V0IH0gb2Ygc3RkaW8pIHtcbiAqICAgLy8gVXNlIGF3YWl0IHRvIHBhdXNlIG9yIHBvbGwgZm9yIGEgY29uZGl0aW9uXG4gKiAgIGF3YWl0IGRlbGF5KDEwMDApXG4gKiAgIC8vIFVzZSB5aWVsZCB0byB3cml0ZSB0byBzdGRpbiAodmVyYmF0aW0pXG4gKiAgIHlpZWxkIFwiY29udGVudFxcblwiXG4gKiAgIC8vIFVzZSByZXR1cm4gdG8gY2xvc2Ugc3RkaW4gYW5kIGVuZCB0aGUgaW50ZXJhY3Rpb25cbiAqICAgcmV0dXJuXG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBJZiB0aGUgZ2VuZXJhdG9yIHRocm93cywgc3RkaW4gaXMgY2xvc2VkLCB0aGUgcHJvY2VzcyBpcyBraWxsZWQgYW5kIHRoZSByZXR1cm5lZCB7QGxpbmsgUmVzdWx0fSByZWplY3RzIHdpdGggdGhlIHRocm93biBlcnJvci5cbiAqIFdoZW4gdGhlIHByb2Nlc3MgZXhpdHMgb24gaXRzIG93biwgdGhlIGBzdGRpb2AgaXRlcmF0b3IgZW5kcywgc28gYSBnZW5lcmF0b3IgcGFya2VkIG9uIGBmb3IgYXdhaXRgIGNvbXBsZXRlcyBuYXR1cmFsbHkuXG4gKi9cbmV4cG9ydCB0eXBlIENhbGxiYWNrID0gKG9wdGlvbnM6IHsgc3RkaW86IEFzeW5jSXRlcmFibGU8U25hcHNob3Q+IH0pID0+IEFzeW5jR2VuZXJhdG9yPHN0cmluZywgdm9pZCwgdW5rbm93bj5cblxuLyoqIFRleHQgZW5jb2RlciAqL1xuY29uc3QgZW5jb2RlciA9IG5ldyBUZXh0RW5jb2RlcigpXG5cbi8qKiBUZXh0IGRlY29kZXIgKi9cbmNvbnN0IGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoKVxuXG4vKiogRGVmYXVsdCBpbnRlcmFjdGlvbjogYW4gZW1wdHkgZ2VuZXJhdG9yIHRoYXQgY2xvc2VzIHN0ZGluIGltbWVkaWF0ZWx5LiAqL1xuY29uc3Qgbm9vcDogQ2FsbGJhY2sgPSBhc3luYyBmdW5jdGlvbiogKCkge31cblxuLyoqXG4gKiBBc3luY2hyb25vdXMgdmVyc2lvbiBvZiB7QGxpbmsgY29tbWFuZH0gcnVubmluZyBpbiBiYWNrZ3JvdW5kLlxuICpcbiAqIGBgYHRzXG4gKiBpbXBvcnQgeyBjb21tYW5kIH0gZnJvbSBcIi4vY29tbWFuZC50c1wiXG4gKiBjb25zdCBwcm9jZXNzID0gY29tbWFuZChcImRlbm9cIiwgW1wiZXZhbFwiLCBcIkRlbm8uZXhpdCgwKVwiXSwgeyBiYWNrZ3JvdW5kOiB0cnVlIH0pXG4gKiBhd2FpdCBwcm9jZXNzLmtpbGwoKVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21tYW5kKGJpbjogc3RyaW5nLCBhcmdzOiBzdHJpbmdbXSwgb3B0aW9ucz86IE9wdGlvbnMgJiB7IHN5bmM/OiBmYWxzZTsgYmFja2dyb3VuZDogdHJ1ZSB9KTogQmFja2dyb3VuZFxuLyoqXG4gKiBBc3luY2hyb25vdXMgdmVyc2lvbiBvZiB7QGxpbmsgY29tbWFuZH0uXG4gKlxuICogYGBgdHNcbiAqIGltcG9ydCB7IGNvbW1hbmQgfSBmcm9tIFwiLi9jb21tYW5kLnRzXCJcbiAqIHRyeSB7XG4gKiAgIGF3YWl0IGNvbW1hbmQoXCJkZW5vXCIsIFtcImV2YWxcIiwgXCJEZW5vLmV4aXQoMSlcIl0sIHsgdGhyb3c6IHRydWUgfSlcbiAqIH1cbiAqIGNhdGNoIChlcnJvcikge1xuICogICBjb25zb2xlLmxvZyhlcnJvcilcbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tbWFuZChiaW46IHN0cmluZywgYXJnczogc3RyaW5nW10sIG9wdGlvbnM/OiBPcHRpb25zICYgeyBzeW5jPzogZmFsc2U7IGJhY2tncm91bmQ/OiBmYWxzZSB9KTogUHJvbWlzZTxSZXN1bHQ+XG4vKipcbiAqIFN5bmNocm9ub3VzIHZlcnNpb24gb2Yge0BsaW5rIGNvbW1hbmR9LlxuICpcbiAqIE5vdGUgdGhhdCBzdGRpbiBpcyBub3QgdXNhYmxlIGluIHN5bmMgbW9kZSBhbmQgd2lsbCBhbHdheXMgYmUgZW1wdHkuXG4gKlxuICogYGBgdHNcbiAqIGltcG9ydCB7IGNvbW1hbmQgfSBmcm9tIFwiLi9jb21tYW5kLnRzXCJcbiAqIGNvbW1hbmQoXCJkZW5vXCIsIFtcIi0tdmVyc2lvblwiXSwgeyBzeW5jOiB0cnVlIH0pXG4gKiBgYGBcbiAqIGBgYHRzXG4gKiBpbXBvcnQgeyBjb21tYW5kIH0gZnJvbSBcIi4vY29tbWFuZC50c1wiXG4gKiB0cnkge1xuICogICBjb21tYW5kKFwiZGVub1wiLCBbXCJldmFsXCIsIFwiRGVuby5leGl0KDEpXCJdLCB7IHN5bmM6IHRydWUsIHRocm93OiB0cnVlIH0pXG4gKiB9XG4gKiBjYXRjaCAoZXJyb3IpIHtcbiAqICAgY29uc29sZS5sb2coZXJyb3IpXG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbW1hbmQoYmluOiBzdHJpbmcsIGFyZ3M6IHN0cmluZ1tdLCBvcHRpb25zPzogT3B0aW9ucyAmIHsgc3luYzogdHJ1ZSB9KTogUmVzdWx0XG4vKipcbiAqIFJ1biBhIGNvbW1hbmQuXG4gKlxuICogVGhpcyBpcyBhIHdyYXBwZXIgYXJvdW5kIHtAbGluayBodHRwczovL2RvY3MuZGVuby5jb20vYXBpL2Rlbm8vfi9EZW5vLkNvbW1hbmQgfCBEZW5vLkNvbW1hbmR9IHRoYXQgcHJvdmlkZXMgYSBiZXR0ZXIgaGFuZGxpbmcgb2Ygc3RkaW8gZm9yIGludGVyYWN0aXZlIHByb2Nlc3Nlcy5cbiAqXG4gKiBMaWtlIGBEZW5vLkNvbW1hbmRgLCB0aGUgYGVudmAsIGBjd2RgLCBhbmQgYHJhd2AgKGFsaWFzIGZvciBgd2luZG93c1Jhd0FyZ3VtZW50c2ApIG9wdGlvbnMgYXJlIHN1cHBvcnRlZC5cbiAqXG4gKiBUaGUgYHN0ZGluYCwgYHN0ZG91dGAgYW5kIGBzdGRlcnJgIG9wdGlvbnMgYWNjZXB0IGBcInBpcGVkXCJgIChjYXB0dXJlZCBpbnRvIHRoZSByZXN1bHQgYW5kIG1pcnJvcmVkIHRvIGEge0BsaW5rIGh0dHBzOi8vbG9ndGFwZS5vcmcgfCBMb2dUYXBlfSBzdWItbG9nZ2VyKSwgYFwiaW5oZXJpdFwiYCAoZm9yd2FyZGVkIHRvIHRoZSBwYXJlbnQgcHJvY2Vzcykgb3IgYG51bGxgIChkaXNjYXJkZWQpLlxuICpcbiAqIExvZ2dpbmcgaXMgcGVyZm9ybWVkIHRocm91Z2gge0BsaW5rIGh0dHBzOi8vbG9ndGFwZS5vcmcgfCBMb2dUYXBlfS5cbiAqIFRoZSBgbG9nZ2VyYCBvcHRpb24gaXMgYSBjYXRlZ29yeSBmb3J3YXJkZWQgdG8gYGdldExvZ2dlcigpYCAoZGVmYXVsdGluZyB0byBgW1wicnVuXCJdYCksIGFuZCBlYWNoIGNoYW5uZWwgaXMgbWlycm9yZWQgdGhyb3VnaCBpdHMgb3duIHN1Yi1jYXRlZ29yeSDigJQgYHN0ZGluYCBhdCBgZGVidWdgLCBgc3Rkb3V0YCBhdCBgaW5mb2AsIGBzdGRlcnJgIGF0IGBlcnJvcmAuXG4gKiBBcyByZWNvbW1lbmRlZCBmb3IgbGlicmFyaWVzLCBgY29tbWFuZCgpYCBuZXZlciBjb25maWd1cmVzIExvZ1RhcGUgaXRzZWxmOiB0aGUgaG9zdCBhcHBsaWNhdGlvbiBpcyBpbiBjaGFyZ2Ugb2YgdGhlIGFjdHVhbCBvdXRwdXQgKHRocm91Z2gge0BsaW5rIGh0dHBzOi8vbG9ndGFwZS5vcmcvbWFudWFsL2NvbmZpZyB8IExvZ1RhcGUgY29uZmlndXJhdGlvbn0pLlxuICpcbiAqIFNldCBgd2luZXh0YCBvcHRpb24gdG8gYXV0b21hdGljYWxseSBhcHBlbmQgYW4gZXh0ZW5zaW9uIHRvIHRoZSBiaW5hcnkgcGF0aCBvbiBXaW5kb3dzIChsaWtlIGAuY21kYCBvciBgLmV4ZWApLlxuICogVGhpcyBpcyB1c2VmdWwgd2hlbiB0aGUgYmluYXJ5IHBhdGggaXNuJ3QgYXV0b21hdGljYWxseSByZXNvbHZlZCBvbiBXaW5kb3dzLlxuICpcbiAqIFBhc3MgYSBgY2FsbGJhY2tgIG9wdGlvbiAoYW4gYXN5bmMgZ2VuZXJhdG9yKSB0byBpbnRlcmFjdCB3aXRoIHRoZSBwcm9jZXNzIHN0ZGluLlxuICogU2VlIHtAbGluayBDYWxsYmFja30gZm9yIHRoZSBpbnRlcmFjdGlvbiBwcm90b2NvbDogYGZvciBhd2FpdGAgb3ZlciBgc3RkaW9gIHRvIHJlYWQgb3V0cHV0LCBgeWllbGRgIHRvIHdyaXRlIHRvIHN0ZGluLCBgcmV0dXJuYCB0byBjbG9zZSBpdC5cbiAqXG4gKiBUaGUgYGJ1ZmZlcmluZ2Agb3B0aW9uIGlzIHVzZWQgdG8gbWVyZ2UgbWVzc2FnZXMgdGhhdCBhcmUgcmVjZWl2ZWQgcmVsYXRpdmVseSBjbG9zZWx5LlxuICogU2V0dGluZyB0aGlzIG9wdGlvbiB0byBhIGxvdyB2YWx1ZSB3aWxsIGFsc28gaW5jcmVhc2UgdGhlIHJhdGUgYXQgd2hpY2ggdGhlIGludGVyYWN0aW9uIGdlbmVyYXRvciBpcyByZXN1bWVkLlxuICpcbiAqIFJlc3VsdGluZyBvYmplY3QgY29udGFpbnMgdGhlIHNhbWUgcHJvcGVydGllcyBhcyB7QGxpbmsgaHR0cHM6Ly9kb2NzLmRlbm8uY29tL2FwaS9kZW5vL34vRGVuby5Db21tYW5kU3RhdHVzIHwgRGVuby5Db21tYW5kU3RhdHVzfVxuICogd2l0aCBhbiBhZGRpdGlvbmFsIGBzdGRpb2AgcHJvcGVydHkgdGhhdCBjb250YWlucyBhbiBhcnJheSBvZiBvcmRlcmVkIHR1cGxlcyB3aXRoIHRoZSBkZWx0YSB0aW1lc3RhbXAgc2luY2UgcHJvY2VzcyBzdGFydCwgdGhlIGNoYW5uZWwgaWRlbmZpdGllciAoMDpzdGRpbiwgMTpzdGRvdXQsIDI6c3RkZXJyKSBhbmQgdGhlIGNvbnRlbnQuXG4gKiBUaGlzIG9mZmVycyBhIHByb3BlciBoaXN0b3J5IG9mIGV4Y2hhbmdlZCBjb250ZW50LlxuICpcbiAqIGBgYHRzXG4gKiBpbXBvcnQgeyBjb21tYW5kIH0gZnJvbSBcIi4vY29tbWFuZC50c1wiXG4gKiBhd2FpdCBjb21tYW5kKFwiZGVub1wiLCBbXCItLXZlcnNpb25cIl0sIHsgZW52OiB7IE5PX0NPTE9SOiBcInRydWVcIiB9LCBjd2Q6IFwiL3RtcFwiLCByYXc6IHRydWUgfSlcbiAqIGF3YWl0IGNvbW1hbmQoXCJkZW5vXCIsIFtcIi0tdmVyc2lvblwiXSwgeyBzdGRvdXQ6IFwicGlwZWRcIiB9KVxuICogYXdhaXQgY29tbWFuZChcImRlbm9cIiwgW1wiLS12ZXJzaW9uXCJdLCB7IGxvZ2dlcjogW1wibXktYXBwXCIsIFwicnVuXCJdLCBzdGRvdXQ6IFwicGlwZWRcIiB9KVxuICogYXdhaXQgY29tbWFuZChcImRlbm9cIiwgW1wiLS12ZXJzaW9uXCJdLCB7IHdpbmV4dDogXCIuZXhlXCIgfSlcbiAqIGBgYFxuICpcbiAqIGBgYHRzXG4gKiBpbXBvcnQgeyBjb21tYW5kIH0gZnJvbSBcIi4vY29tbWFuZC50c1wiXG4gKlxuICogY29uc3QgeyBzdGRvdXQgfSA9IGF3YWl0IGNvbW1hbmQoXCJkZW5vXCIsIFtcInJlcGxcIl0sIHtcbiAqICAgZW52OiB7IE5PX0NPTE9SOiBcInRydWVcIiB9LFxuICogICAvLyBQYXNzaW5nIGEgY2FsbGJhY2sgYXV0b21hdGljYWxseSBwaXBlcyBzdGRpbi5cbiAqICAgLy8gSXRlcmF0ZSBgc3RkaW9gIHRvIHJlYWN0IHRvIG91dHB1dCwgYHlpZWxkYCB0byB3cml0ZSB0byBzdGRpbiAodmVyYmF0aW0pLCBgcmV0dXJuYCB0byBjbG9zZSBpdC5cbiAqICAgY2FsbGJhY2s6IGFzeW5jIGZ1bmN0aW9uKiAoeyBzdGRpbyB9KSB7XG4gKiAgICAgZm9yIGF3YWl0IChjb25zdCB7IHN0ZG91dCB9IG9mIHN0ZGlvKSB7XG4gKiAgICAgICBpZiAoIXN0ZG91dC5pbmNsdWRlcyhcImV4aXQgdXNpbmdcIikpIHtcbiAqICAgICAgICAgY29udGludWVcbiAqICAgICAgIH1cbiAqICAgICAgIHlpZWxkIFwiY29uc29sZS5sb2coJ2hlbGxvJylcXG5cIlxuICogICAgICAgcmV0dXJuXG4gKiAgICAgfVxuICogICB9LFxuICogfSlcbiAqIGNvbnNvbGUuYXNzZXJ0KHN0ZG91dC5pbmNsdWRlcyhcImhlbGxvXCIpKVxuICogYGBgXG4gKlxuICogQGF1dGhvciBTaW1vbiBMZWNvcSAobG93bGlnaHRlcilcbiAqIEBsaWNlbnNlIE1JVFxuICogQG1vZHVsZVxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tbWFuZChcbiAgYmluOiBzdHJpbmcsXG4gIGFyZ3M6IHN0cmluZ1tdLFxuICB7IGxvZ2dlcjogY2F0ZWdvcnkgPSBbXCJydW5cIl0sIHN0ZGluID0gbnVsbCwgc3Rkb3V0ID0gXCJwaXBlZFwiLCBzdGRlcnIgPSBcInBpcGVkXCIsIGVudiwgY3dkLCByYXcsIGNhbGxiYWNrLCBidWZmZXJpbmcsIHNpZ25hbCwgc3luYywgYmFja2dyb3VuZCwgdGhyb3c6IF90aHJvdywgZHJ5cnVuLCB3aW5leHQgPSBcIlwiLCBvcyA9IERlbm8uYnVpbGQub3MgfSA9IHt9IGFzIE9wdGlvbnMsXG4pOiBQcm9taXNhYmxlPFJlc3VsdD4gfCBCYWNrZ3JvdW5kIHtcbiAgaWYgKG9zID09PSBcIndpbmRvd3NcIilcbiAgICBiaW4gPSBgJHtiaW59JHt3aW5leHR9YFxuICBjb25zdCBsb2cgPSBnZXRMb2dnZXIoY2F0ZWdvcnkpLndpdGgoeyBiaW4gfSlcbiAgaWYgKGNhbGxiYWNrICYmIChoYW5kbGUoc3RkaW4pICE9PSBcInBpcGVkXCIpKVxuICAgIHN0ZGluID0gXCJwaXBlZFwiXG4gIGNvbnN0IGNvbW1hbmQgPSBuZXcgRGVuby5Db21tYW5kKGJpbiwgeyBhcmdzLCBzdGRpbjogIXN5bmMgPyBoYW5kbGUoc3RkaW4pIDogXCJudWxsXCIsIHN0ZG91dDogaGFuZGxlKHN0ZG91dCksIHN0ZGVycjogaGFuZGxlKHN0ZGVyciksIGNsZWFyRW52OiB0cnVlLCBlbnYsIGN3ZCwgd2luZG93c1Jhd0FyZ3VtZW50czogcmF3LCBzaWduYWwsIGRldGFjaGVkOiBiYWNrZ3JvdW5kIH0pXG4gIGlmIChkcnlydW4pIHtcbiAgICBsb2cud2FybihcImRyeXJ1bjoge2Jpbn0gbm90IGV4ZWN1dGVkXCIsIHsgYmluIH0pXG4gICAgY29uc3QgcmVzdWx0ID0geyBzdWNjZXNzOiB0cnVlLCBjb2RlOiAwLCBzdGRpbzogW10sIHN0ZGluOiBcIlwiLCBzdGRvdXQ6IFwiXCIsIHN0ZGVycjogXCJcIiB9XG4gICAgcmV0dXJuIHN5bmMgPyByZXN1bHQgOiBQcm9taXNlLnJlc29sdmUocmVzdWx0KVxuICB9XG4gIGlmIChzeW5jKVxuICAgIHJldHVybiBleGVjKGNvbW1hbmQsIHsgYmluLCBsb2csIHRocm93OiBfdGhyb3csIHN0ZG91dCwgc3RkZXJyIH0pXG4gIHJldHVybiBzcGF3bihjb21tYW5kLCB7IGJpbiwgbG9nLCBjYWxsYmFjaywgYnVmZmVyaW5nLCB0aHJvdzogX3Rocm93LCBiYWNrZ3JvdW5kLCBzdGRpbiwgc3Rkb3V0LCBzdGRlcnIgfSlcbn1cblxuLyoqIFJldHVybnMgdGhlIGhhbmRsZSB0eXBlIGZvciBhIGdpdmVuIG1vZGUuICovXG5mdW5jdGlvbiBoYW5kbGUobW9kZTogQ2hhbm5lbCkge1xuICByZXR1cm4gW1wiaW5oZXJpdFwiLCBcIm51bGxcIl0uaW5jbHVkZXMoYCR7bW9kZX1gKSA/IGAke21vZGV9YCBhcyBcImluaGVyaXRcIiB8IFwibnVsbFwiIDogXCJwaXBlZFwiXG59XG5cbi8qKiBFeGVjdXRlIGEgY29tbWFuZCBzeW5jaHJvbm91c2x5LiAqL1xuZnVuY3Rpb24gZXhlYyhjb21tYW5kOiBEZW5vLkNvbW1hbmQsIHsgYmluLCBsb2csIHRocm93OiBfdGhyb3csIHN0ZG91dCwgc3RkZXJyIH06IHsgYmluOiBzdHJpbmc7IGxvZzogTG9nZ2VyOyB0aHJvdz86IGJvb2xlYW47IHN0ZG91dDogQ2hhbm5lbDsgc3RkZXJyOiBDaGFubmVsIH0pIHtcbiAgY29uc3Qgc3RhcnQgPSBEYXRlLm5vdygpXG4gIGNvbnN0IG91dHB1dCA9IGNvbW1hbmQub3V0cHV0U3luYygpXG4gIGNvbnN0IHsgc3VjY2VzcywgY29kZSB9ID0gb3V0cHV0IC8vIERvIG5vdCBhY2Nlc3Mgc3Rkb3V0IG9yIHN0ZGVyciBiZWZvcmUgXCJwaXBlZFwiIHN0YXR1cyBjaGVja1xuICBjb25zdCB0ID0gRGF0ZS5ub3coKSAtIHN0YXJ0XG4gIGNvbnN0IHN0ZGlvID0ge1xuICAgIGdldCBzdGRpbygpIHtcbiAgICAgIHJldHVybiBbW3QsIDEsIHRoaXMuc3Rkb3V0XSwgW3QsIDIsIHRoaXMuc3RkZXJyXV1cbiAgICB9LFxuICAgIHN0ZGluOiBcIlwiLFxuICAgIHN0ZG91dDogaGFuZGxlKHN0ZG91dCkgPT09IFwicGlwZWRcIiA/IGRlY29kZXIuZGVjb2RlKG91dHB1dC5zdGRvdXQpIDogXCJcIixcbiAgICBzdGRlcnI6IGhhbmRsZShzdGRlcnIpID09PSBcInBpcGVkXCIgPyBkZWNvZGVyLmRlY29kZShvdXRwdXQuc3RkZXJyKSA6IFwiXCIsXG4gIH0gYXMgU25hcHNob3QgJiBQaWNrPFJlc3VsdCwgXCJzdGRpb1wiPlxuICBmb3IgKGNvbnN0IHsgY2hhbm5lbCwgbW9kZSB9IG9mIFt7IGNoYW5uZWw6IFwic3Rkb3V0XCIsIG1vZGU6IHN0ZG91dCB9LCB7IGNoYW5uZWw6IFwic3RkZXJyXCIsIG1vZGU6IHN0ZGVyciB9XSBhcyBjb25zdCkge1xuICAgIGlmICgoaGFuZGxlKG1vZGUpID09PSBcInBpcGVkXCIpICYmIChzdGRpb1tjaGFubmVsXSkpXG4gICAgICBsb2dnZWQobG9nLCBjaGFubmVsLCB0LCBzdGRpb1tjaGFubmVsXSlcbiAgfVxuICBpZiAoKCFzdWNjZXNzKSAmJiBfdGhyb3cpXG4gICAgdGhyb3cgbmV3IEV2YWxFcnJvcihgJHtiaW59IGV4aXRlZCB3aXRoIG5vbi16ZXJvIGNvZGUgJHtjb2RlfTpcXG4ke3N0ZGlvLnN0ZG91dH1cXG4ke3N0ZGlvLnN0ZGVycn1gKVxuICByZXR1cm4geyBzdWNjZXNzLCBjb2RlLCAuLi5zdGRpbyB9XG59XG5cbi8qKiBTcGF3biBhIGNvbW1hbmQgYXN5bmNocm9ub3VzbHkgaW4gYmFja2dyb3VuZC4gKi9cbmZ1bmN0aW9uIHNwYXduKFxuICBjb21tYW5kOiBEZW5vLkNvbW1hbmQsXG4gIG9wdGlvbnM6IHsgYmluOiBzdHJpbmc7IGxvZzogTG9nZ2VyOyBjYWxsYmFjaz86IENhbGxiYWNrOyBidWZmZXJpbmc/OiBudW1iZXI7IHRocm93PzogYm9vbGVhbjsgYmFja2dyb3VuZDogdHJ1ZTsgc3RkaW46IENoYW5uZWw7IHN0ZG91dDogQ2hhbm5lbDsgc3RkZXJyOiBDaGFubmVsIH0sXG4pOiBCYWNrZ3JvdW5kXG4vKiogU3Bhd24gYSBjb21tYW5kIGFzeW5jaHJvbm91c2x5LiAqL1xuZnVuY3Rpb24gc3Bhd24oY29tbWFuZDogRGVuby5Db21tYW5kLCBvcHRpb25zOiB7IGJpbjogc3RyaW5nOyBsb2c6IExvZ2dlcjsgY2FsbGJhY2s/OiBDYWxsYmFjazsgYnVmZmVyaW5nPzogbnVtYmVyOyB0aHJvdz86IGJvb2xlYW47IGJhY2tncm91bmQ/OiBib29sZWFuOyBzdGRpbjogQ2hhbm5lbDsgc3Rkb3V0OiBDaGFubmVsOyBzdGRlcnI6IENoYW5uZWwgfSk6IFByb21pc2U8UmVzdWx0PlxuLyoqIFNwYXduIGEgY29tbWFuZC4gKi9cbmZ1bmN0aW9uIHNwYXduKFxuICBjb21tYW5kOiBEZW5vLkNvbW1hbmQsXG4gIHsgYmluLCBsb2csIGNhbGxiYWNrID0gbm9vcCwgYnVmZmVyaW5nID0gMjUwLCB0aHJvdzogX3Rocm93LCBiYWNrZ3JvdW5kLCAuLi5jaGFubmVscyB9OiB7XG4gICAgYmluOiBzdHJpbmdcbiAgICBsb2c6IExvZ2dlclxuICAgIGNhbGxiYWNrPzogQ2FsbGJhY2tcbiAgICBidWZmZXJpbmc/OiBudW1iZXJcbiAgICB0aHJvdz86IGJvb2xlYW5cbiAgICBiYWNrZ3JvdW5kPzogYm9vbGVhblxuICAgIHN0ZGluOiBDaGFubmVsXG4gICAgc3Rkb3V0OiBDaGFubmVsXG4gICAgc3RkZXJyOiBDaGFubmVsXG4gIH0sXG4pIHtcbiAgY29uc3QgcHJvY2VzcyA9IGNvbW1hbmQuc3Bhd24oKVxuICBjb25zdCBzdGF0dXMgPSBwcm9jZXNzLnN0YXR1c1xuICBjb25zdCBzdGFydCA9IERhdGUubm93KClcbiAgY29uc3Qgc3RkaW8gPSB7XG4gICAgc3RkaW86IFtdLFxuICAgIGdldCBzdGRpbigpIHtcbiAgICAgIHJldHVybiB0aGlzLnN0ZGlvLmZpbHRlcigoW18sIGldKSA9PiBpID09PSAwKS5tYXAoKFtfLCBfXywgY29udGVudF0pID0+IGNvbnRlbnQpLmpvaW4oXCJcIilcbiAgICB9LFxuICAgIGdldCBzdGRvdXQoKSB7XG4gICAgICByZXR1cm4gdGhpcy5zdGRpby5maWx0ZXIoKFtfLCBpXSkgPT4gaSA9PT0gMSkubWFwKChbXywgX18sIGNvbnRlbnRdKSA9PiBjb250ZW50KS5qb2luKFwiXFxuXCIpXG4gICAgfSxcbiAgICBnZXQgc3RkZXJyKCkge1xuICAgICAgcmV0dXJuIHRoaXMuc3RkaW8uZmlsdGVyKChbXywgaV0pID0+IGkgPT09IDIpLm1hcCgoW18sIF9fLCBjb250ZW50XSkgPT4gY29udGVudCkuam9pbihcIlxcblwiKVxuICAgIH0sXG4gIH0gYXMgU25hcHNob3QgJiBQaWNrPFJlc3VsdCwgXCJzdGRpb1wiPlxuICBsZXQgbGFzdCA9IFwiXCJcblxuICAvLyBEcml2ZSB0aGUgaW50ZXJhY3Rpb24gZ2VuZXJhdG9yIHdoZW4gc3RkaW4gaXMgcGlwZWRcbiAgbGV0IHJlbGVhc2UgPSAoKSA9PiB7fVxuICBsZXQgbm90aWZ5ID0gbnVsbCBhcyBOdWxsYWJsZTwoKSA9PiB2b2lkPlxuICBsZXQgcGVuZGluZyA9IHRydWVcbiAgbGV0IGVuZGVkID0gZmFsc2VcbiAgbGV0IGV4aXRlZCA9IGZhbHNlXG4gIGxldCBpbnRlcmFjdGlvbiA9IFByb21pc2UucmVzb2x2ZSgpXG4gIGlmIChoYW5kbGUoY2hhbm5lbHMuc3RkaW4pID09PSBcInBpcGVkXCIpIHtcbiAgICBjb25zdCB3cml0ZXIgPSBwcm9jZXNzLnN0ZGluLmdldFdyaXRlcigpXG4gICAgY29uc3QgY2xvc2UgPSBhc3luYyAoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB3cml0ZXIuY2xvc2UoKVxuICAgICAgICBsb2cud2l0aCh7IHQ6IERhdGUubm93KCkgLSBzdGFydCB9KS50cmFjZShcImNsb3NlZCBzdGRpblwiKVxuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIElnbm9yZSAoc3RkaW4gbWF5IGFscmVhZHkgYmUgY2xvc2VkIGlmIHRoZSBwcm9jZXNzIGV4aXRlZClcbiAgICAgIH1cbiAgICB9XG4gICAgcmVsZWFzZSA9ICgpID0+IHtcbiAgICAgIGVuZGVkID0gdHJ1ZVxuICAgICAgbm90aWZ5Py4oKVxuICAgICAgbm90aWZ5ID0gbnVsbFxuICAgIH1cbiAgICBjb25zdCBpbnB1dCA9IHtcbiAgICAgIGFzeW5jICpbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCkge1xuICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgIGlmIChwZW5kaW5nKSB7XG4gICAgICAgICAgICBwZW5kaW5nID0gZmFsc2VcbiAgICAgICAgICAgIHlpZWxkIHN0ZGlvIGFzIFNuYXBzaG90XG4gICAgICAgICAgICBjb250aW51ZVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZW5kZWQpXG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4gbm90aWZ5ID0gcmVzb2x2ZSlcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICB9XG4gICAgaW50ZXJhY3Rpb24gPSAoYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZ2VuZXJhdG9yID0gY2FsbGJhY2soeyBzdGRpbzogaW5wdXQgfSlcbiAgICAgIHRyeSB7XG4gICAgICAgIGZvciBhd2FpdCAoY29uc3QgY29udGVudCBvZiBnZW5lcmF0b3IpIHtcbiAgICAgICAgICBpZiAoZXhpdGVkKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEV2YWxFcnJvcihcIkNhbm5vdCB3cml0ZSB0byBzdGRpbjogcHJvY2VzcyBhbHJlYWR5IGV4aXRlZFwiKVxuICAgICAgICAgIGNvbnN0IHQgPSBEYXRlLm5vdygpIC0gc3RhcnRcbiAgICAgICAgICBsb2dnZWQobG9nLCBcInN0ZGluXCIsIHQsIGAke2NvbnRlbnR9YClcbiAgICAgICAgICBzdGRpby5zdGRpby5wdXNoKFt0LCAwLCBgJHtjb250ZW50fWBdKVxuICAgICAgICAgIGF3YWl0IHdyaXRlci53cml0ZShlbmNvZGVyLmVuY29kZShgJHtjb250ZW50fWApKVxuICAgICAgICAgIGxhc3QgPSBcInN0ZGluXCJcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCBjbG9zZSgpXG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBhd2FpdCBjbG9zZSgpXG4gICAgICAgIGFib3J0KHByb2Nlc3MpXG4gICAgICAgIGF3YWl0IHN0YXR1c1xuICAgICAgICB0aHJvdyBlcnJvclxuICAgICAgfVxuICAgIH0pKClcbiAgfVxuXG4gIC8vIEJ1ZmZlciBvdXRwdXQgYW5kIHJlc3VtZSB0aGUgaW50ZXJhY3Rpb24gZ2VuZXJhdG9yXG4gIGNvbnN0IGRlYm91bmNlZCA9IGRlYm91bmNlKCgpID0+IHtcbiAgICBsYXN0ID0gXCJcIlxuICAgIHBlbmRpbmcgPSB0cnVlXG4gICAgbm90aWZ5Py4oKVxuICAgIG5vdGlmeSA9IG51bGxcbiAgfSwgYnVmZmVyaW5nKVxuICBjb25zdCBvdXRwdXRzID0gUHJvbWlzZS5hbGwoXG4gICAgKFtcInN0ZG91dFwiLCBcInN0ZGVyclwiXSBhcyBjb25zdCkuZmlsdGVyKChjaGFubmVsKSA9PiBoYW5kbGUoY2hhbm5lbHNbY2hhbm5lbF0pID09PSBcInBpcGVkXCIpLm1hcChhc3luYyAoY2hhbm5lbCkgPT4ge1xuICAgICAgZm9yIGF3YWl0IChjb25zdCBsaW5lIG9mIHByb2Nlc3NbY2hhbm5lbF0ucGlwZVRocm91Z2gobmV3IFRleHREZWNvZGVyU3RyZWFtKCkpLnBpcGVUaHJvdWdoKG5ldyBUZXh0TGluZVN0cmVhbSgpKSkge1xuICAgICAgICBjb25zdCB0ID0gRGF0ZS5ub3coKSAtIHN0YXJ0XG4gICAgICAgIGNvbnN0IHN0ZGkgPSB7IHN0ZG91dDogMSwgc3RkZXJyOiAyIH1bY2hhbm5lbF0gYXMgMSB8IDJcbiAgICAgICAgbG9nZ2VkKGxvZywgY2hhbm5lbCwgdCwgbGluZSlcbiAgICAgICAgaWYgKChzdGRpby5zdGRpby5sZW5ndGgpICYmIChsYXN0ID09PSBjaGFubmVsKSkge1xuICAgICAgICAgIGNvbnN0IHByZXZpb3VzID0gc3RkaW8uc3RkaW8uYXQoLTEpIVxuICAgICAgICAgIGlmIChwcmV2aW91c1sxXSA9PT0gc3RkaSlcbiAgICAgICAgICAgIHByZXZpb3VzWzJdICs9IGBcXG4ke2xpbmV9YFxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN0ZGlvLnN0ZGlvLnB1c2goW3QsIHN0ZGksIGxpbmVdKVxuICAgICAgICB9XG4gICAgICAgIGxhc3QgPSBjaGFubmVsXG4gICAgICAgIGRlYm91bmNlZCgpXG4gICAgICB9XG4gICAgfSksXG4gIClcbiAgY29uc3Qgc2V0dGxlID0gKCkgPT4ge1xuICAgIGV4aXRlZCA9IHRydWVcbiAgICByZWxlYXNlKClcbiAgfVxuICB2b2lkIHN0YXR1cy50aGVuKHNldHRsZSwgc2V0dGxlKVxuXG4gIC8vIENvbXB1dGUgcmVzdWx0XG4gIGNvbnN0IHJlc3VsdCA9IChhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgW291dHB1dCwgaW50ZXJhY3RlZF0gPSBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoW291dHB1dHMsIGludGVyYWN0aW9uXSlcbiAgICBkZWJvdW5jZWQuY2xlYXIoKVxuICAgIGNvbnN0IHsgc3VjY2VzcywgY29kZSB9ID0gYXdhaXQgc3RhdHVzXG4gICAgaWYgKChvdXRwdXQuc3RhdHVzID09PSBcInJlamVjdGVkXCIpIHx8IChpbnRlcmFjdGVkLnN0YXR1cyA9PT0gXCJyZWplY3RlZFwiKSlcbiAgICAgIHRocm93ICgob3V0cHV0IGFzIHsgcmVhc29uPzogdW5rbm93biB9KS5yZWFzb24gPz8gKGludGVyYWN0ZWQgYXMgeyByZWFzb24/OiB1bmtub3duIH0pLnJlYXNvbilcbiAgICBpZiAoKCFzdWNjZXNzKSAmJiBfdGhyb3cpXG4gICAgICB0aHJvdyBuZXcgRXZhbEVycm9yKGAke2Jpbn0gZXhpdGVkIHdpdGggbm9uLXplcm8gY29kZSAke2NvZGV9OlxcbiR7c3RkaW8uc3Rkb3V0fVxcbiR7c3RkaW8uc3RkZXJyfWApXG4gICAgcmV0dXJuIHsgc3VjY2VzcywgY29kZSwgLi4uc3RkaW8gfVxuICB9KSgpXG4gIGNvbnN0IHRlcm1pbmF0ZSA9IGFzeW5jIChzaWduYWw6IERlbm8uU2lnbmFsID0gXCJTSUdURVJNXCIpID0+IHtcbiAgICBhYm9ydChwcm9jZXNzLCBzaWduYWwpXG4gICAgYXdhaXQgcmVzdWx0LmNhdGNoKCgpID0+IHt9KVxuICB9XG4gIHJldHVybiBiYWNrZ3JvdW5kXG4gICAgPyB7XG4gICAgICBraWxsOiB0ZXJtaW5hdGUsXG4gICAgICB1bnJlZjogKCkgPT4gcHJvY2Vzcy51bnJlZigpLFxuICAgICAgcGlkOiBwcm9jZXNzLnBpZCxcbiAgICAgIHJlc3VsdCxcbiAgICAgIFtTeW1ib2wuYXN5bmNEaXNwb3NlXTogKCkgPT4gdGVybWluYXRlKCksXG4gICAgfVxuICAgIDogcmVzdWx0XG59XG5cbi8qKiBTZW5kIGEgc2lnbmFsIHRvIGEgcHJvY2VzcywgaWdub3JpbmcgdGhlIGVycm9yIHJhaXNlZCB3aGVuIGl0IGhhcyBhbHJlYWR5IHRlcm1pbmF0ZWQuICovXG5mdW5jdGlvbiBhYm9ydChwcm9jZXNzOiBEZW5vLkNoaWxkUHJvY2Vzcywgc2lnbmFsOiBEZW5vLlNpZ25hbCA9IFwiU0lHVEVSTVwiKSB7XG4gIHRyeSB7XG4gICAgcHJvY2Vzcy5raWxsKHNpZ25hbClcbiAgfSBjYXRjaCB7XG4gICAgLy8gQWxyZWFkeSB0ZXJtaW5hdGVkXG4gIH1cbn1cblxuLyoqIE1pcnJvciBhIHN0ZGlvIGxpbmUgdGhyb3VnaCB0aGUgY2hhbm5lbCdzIHN1Yi1sb2dnZXIuICovXG5mdW5jdGlvbiBsb2dnZWQobG9nOiBMb2dnZXIsIGNoYW5uZWw6IFwic3RkaW5cIiB8IFwic3Rkb3V0XCIgfCBcInN0ZGVyclwiLCB0OiBudW1iZXIsIGNvbnRlbnQ6IHN0cmluZykge1xuICBjb25zdCBsb2dnZXIgPSBsb2cuZ2V0Q2hpbGQoY2hhbm5lbCkud2l0aCh7IHQgfSlcbiAgc3dpdGNoIChjaGFubmVsKSB7XG4gICAgY2FzZSBcInN0ZGluXCI6XG4gICAgICByZXR1cm4gdm9pZCBsb2dnZXIuZGVidWcoXCJ7Y29udGVudH1cIiwgeyBjb250ZW50IH0pXG4gICAgY2FzZSBcInN0ZG91dFwiOlxuICAgICAgcmV0dXJuIHZvaWQgbG9nZ2VyLmluZm8oXCJ7Y29udGVudH1cIiwgeyBjb250ZW50IH0pXG4gICAgY2FzZSBcInN0ZGVyclwiOlxuICAgICAgcmV0dXJuIHZvaWQgbG9nZ2VyLmVycm9yKFwie2NvbnRlbnR9XCIsIHsgY29udGVudCB9KVxuICB9XG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsVUFBVTtBQUVWLFNBQVMsU0FBUyxRQUFxQixtQkFBa0I7QUFDekQsU0FBUyxjQUFjLFFBQVEsZUFBYztBQUM3QyxTQUFTLFFBQVEsUUFBUSxzQkFBcUI7QUE4SDlDLGlCQUFpQixHQUNqQixNQUFNLFVBQVUsSUFBSTtBQUVwQixpQkFBaUIsR0FDakIsTUFBTSxVQUFVLElBQUk7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
package/mod.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./command.js";
package/mod.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./command.js";
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9saWJzL2xpYnMvQGxpYnMvcnVuL21vZC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tIFwiLi9jb21tYW5kLmpzXCJcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLGVBQWMifQ==
package/package.json CHANGED
@@ -1,25 +1,25 @@
1
1
  {
2
2
  "name": "@lowlighter/run",
3
- "version": "3.0.0",
3
+ "version": "3.4.1",
4
4
  "type": "module",
5
- "scripts": {},
6
- "dependencies": {},
7
- "devDependencies": {},
8
- "description": "Utilities to run subprocess.",
9
- "keywords": [
10
- "subprocess",
11
- "esm"
12
- ],
13
- "license": "MIT",
14
- "author": "lowlighter (Simon Lecoq)",
15
- "homepage": "https://github.com/lowlighter/libs",
16
- "repository": {
17
- "type": "git",
18
- "url": "git+https://github.com/lowlighter/libs.git"
19
- },
20
- "funding": "https://github.com/sponsors/lowlighter",
5
+ "main": "./mod.js",
6
+ "types": "./mod.d.ts",
21
7
  "exports": {
22
- ".": "./mod.mjs",
23
- "./command": "./command.mjs"
8
+ ".": {
9
+ "types": "./mod.d.ts",
10
+ "import": "./mod.js",
11
+ "default": "./mod.js"
12
+ },
13
+ "./command": {
14
+ "types": "./command.d.ts",
15
+ "import": "./command.js",
16
+ "default": "./command.js"
17
+ }
18
+ },
19
+ "dependencies": {
20
+ "@logtape/logtape": "npm:@jsr/logtape__logtape@^2.2.0",
21
+ "@std/async": "npm:@jsr/std__async@^1.2.0",
22
+ "@std/streams": "npm:@jsr/std__streams@^1.0.17",
23
+ "@lowlighter/typing": "^4.1.0"
24
24
  }
25
- }
25
+ }