@dbx-tools/cli 0.6.75 → 0.6.77

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
@@ -1,16 +1,20 @@
1
1
  # @dbx-tools/cli
2
2
 
3
- Bootstrap CLI for the dbx-tools projen workspace engine.
3
+ The single `dbx` CLI: workspace lifecycle, Model Serving proxy, and AppKit env.
4
4
 
5
- Run the `dbx-tools` command (aliased `dbxt`) to turn a folder that has no
6
- `.projenrc.ts` or toolchain yet into a working dbx-tools workspace. Once that
7
- workspace exists, everything else is a projen task you run with
8
- `bun run <task>` - the CLI only forwards to projen from that point on. Import
9
- the package modules when custom tooling needs the same root detection, bun
10
- delegation, or CLI program behavior.
5
+ This package installs one command, `dbx` (aliased `dbx-tools`), with three
6
+ groups:
7
+
8
+ | Command | What it does |
9
+ | ----------------- | ------------------------------------------------------------------------ |
10
+ | `dbx dev` | Bootstrap or repair a dbx-tools workspace, then forward to projen. |
11
+ | `dbx model-proxy` | Local OpenAI-compatible proxy in front of Databricks Model Serving. |
12
+ | `dbx appkit env` | Print the environment an AppKit app resolves, as eval-able shell output. |
11
13
 
12
14
  Key features:
13
15
 
16
+ - One installed command for every dbx-tools CLI surface, so there is a single
17
+ thing to install and a single `--help` to discover.
14
18
  - Bootstrap path that scaffolds bun/projen into an empty or partially-set-up
15
19
  folder, including the initial install and synth.
16
20
  - Toolchain repair for a cloned repo whose generated files and `node_modules`
@@ -20,10 +24,17 @@ Key features:
20
24
  when the effective registry is not npmjs.
21
25
  - Importable CLI/root/bun helpers for tests and thin wrapper commands.
22
26
 
27
+ `model-proxy` and `appkit` live in
28
+ [`@dbx-tools/cli-model-proxy`](../model-proxy) and
29
+ [`@dbx-tools/cli-appkit-env`](../appkit-env) and are imported LAZILY, only once
30
+ their name is matched - so `dbx dev` never pays to load the Databricks SDK or
31
+ AppKit. Run `dbx <group> --help` for a group's own flags; each forwards `--help`
32
+ to the child program rather than answering it at the root.
33
+
23
34
  ## Bootstrap A Workspace
24
35
 
25
36
  ```sh
26
- dbx-tools sync
37
+ dbx dev sync
27
38
  ```
28
39
 
29
40
  In an empty folder this creates the minimum bun/projen structure needed for
@@ -31,7 +42,7 @@ In an empty folder this creates the minimum bun/projen structure needed for
31
42
  freshly cloned repo it seeds the missing toolchain and synthesizes. This is the
32
43
  case projen cannot handle on its own, because there are no tasks to run yet.
33
44
 
34
- The three cases the bin dispatches on, in order:
45
+ The three cases `dbx dev` dispatches on, in order:
35
46
 
36
47
  | Workspace state | What happens |
37
48
  | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -39,6 +50,11 @@ The three cases the bin dispatches on, in order:
39
50
  | `.projenrc.ts` but no installed toolchain | Seed the toolchain, run the initial synth, then install. Task args are not forwarded, because the tasks they name do not exist until the first synth. |
40
51
  | Established workspace | Ensure deps, bring the engine up to this CLI's version, forward the args to projen. |
41
52
 
53
+ Everything after `dev` is forwarded verbatim, flags included - `dbx dev sync
54
+ --watch` runs the `sync` task with `--watch`. `dev` is an explicit subcommand
55
+ rather than the bare root action so a projen task name can never collide with a
56
+ sibling command group.
57
+
42
58
  ## After Bootstrap, Use The Projen Tasks
43
59
 
44
60
  The engine registers its commands as projen tasks on the workspace root, so run
@@ -52,25 +68,37 @@ bun run openapi # generate the openapi packages from tsoa controllers
52
68
  bun run clean # remove generated (read-only) files; -y to skip the picker
53
69
  ```
54
70
 
55
- `dbx-tools <task>` still works and forwards to the same projen task, but the
71
+ `dbx dev <task>` still works and forwards to the same projen task, but the
56
72
  `bun run` form is the documented one for an established workspace.
57
73
 
74
+ ## Proxy Model Serving And Resolve AppKit Env
75
+
76
+ ```sh
77
+ dbx model-proxy --profile my-workspace --port 4000
78
+ eval "$(dbx appkit env --quiet)"
79
+ ```
80
+
81
+ See [`@dbx-tools/cli-model-proxy`](../model-proxy) and
82
+ [`@dbx-tools/cli-appkit-env`](../appkit-env) for the full flag surface, auth
83
+ resolution, and output formats.
84
+
58
85
  ## Use The CLI Internals
59
86
 
60
87
  ```ts
61
88
  import { cli, root, bun } from "@dbx-tools/cli";
62
89
 
63
- await cli.runCli(["sync"]);
90
+ await cli.prepareAndRunProjen(["sync"]);
64
91
  const workspaceRoot = await root.findWorkspaceRoot();
65
92
  bun.runProjen(["barrels"], workspaceRoot);
66
93
  ```
67
94
 
68
95
  Importing internals is mainly useful for tests or wrapper scripts; most users
69
- should run the `dbx-tools` bin.
96
+ should run the `dbx` bin.
70
97
 
71
98
  ## Modules
72
99
 
73
- - `cli` - Commander entrypoint and `runCli()`.
100
+ - `cli` - the root commander program (`buildProgram()`, `runCli()`) and the
101
+ `dev` implementation `prepareAndRunProjen()`.
74
102
  - `bootstrap` - empty-workspace bootstrap, toolchain seeding, and the initial synth.
75
103
  - `root` - workspace-root detection and bootstrap/install checks.
76
104
  - `bun` - bun discovery, workspace install, registry forcing, and projen delegation.
@@ -1,12 +1,11 @@
1
1
  /**
2
2
  * Upgrade an established workspace whose installed engine predates this CLI.
3
3
  *
4
- * Bootstrapping pins the engine once, and nothing afterwards revisits it - so a
5
- * workspace created months ago kept resolving its original engine no matter how
6
- * current the CLI invoking it was, and failed inside the OLD engine's code
7
- * (`sync --watch` dying on a `concurrently` that engine never declared). The two
8
- * are released in lockstep, so this CLI's version is exactly the engine it
9
- * expects.
4
+ * Bootstrapping pins the engine once, so without this a workspace created months ago
5
+ * would keep resolving its original engine no matter how current the CLI invoking it
6
+ * is, and would fail inside THAT engine's code (`sync --watch` dying on a
7
+ * `concurrently` it never declared). The two are released in lockstep, so this CLI's
8
+ * version is exactly the engine it expects.
10
9
  *
11
10
  * Only ever moves FORWARD: an engine at or ahead of this CLI is left alone, so
12
11
  * an older CLI cannot downgrade a workspace.
@@ -66,12 +66,11 @@ function installedEngineVersion(root) {
66
66
  /**
67
67
  * Upgrade an established workspace whose installed engine predates this CLI.
68
68
  *
69
- * Bootstrapping pins the engine once, and nothing afterwards revisits it - so a
70
- * workspace created months ago kept resolving its original engine no matter how
71
- * current the CLI invoking it was, and failed inside the OLD engine's code
72
- * (`sync --watch` dying on a `concurrently` that engine never declared). The two
73
- * are released in lockstep, so this CLI's version is exactly the engine it
74
- * expects.
69
+ * Bootstrapping pins the engine once, so without this a workspace created months ago
70
+ * would keep resolving its original engine no matter how current the CLI invoking it
71
+ * is, and would fail inside THAT engine's code (`sync --watch` dying on a
72
+ * `concurrently` it never declared). The two are released in lockstep, so this CLI's
73
+ * version is exactly the engine it expects.
75
74
  *
76
75
  * Only ever moves FORWARD: an engine at or ahead of this CLI is left alone, so
77
76
  * an older CLI cannot downgrade a workspace.
@@ -211,4 +210,4 @@ export function runInitialSynth(root) {
211
210
  check: true,
212
211
  });
213
212
  }
214
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9vdHN0cmFwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Jvb3RzdHJhcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDNUMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNqQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDaEQsT0FBTyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNuRCxPQUFPLEVBQUUsUUFBUSxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDNUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUV0QyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLHFCQUFxQixDQUFDLENBQUM7QUFFakQsaUZBQWlGO0FBQ2pGLE1BQU0sV0FBVyxHQUFHLGdCQUFnQixDQUFDO0FBRXJDLHNGQUFzRjtBQUN0RixNQUFNLHlCQUF5QixHQUFHLDBCQUEwQixDQUFDO0FBRTdEOzs7Ozs7Ozs7R0FTRztBQUNILFNBQVMsc0JBQXNCO0lBQzdCLE1BQU0sT0FBTyxHQUFHLFVBQVUsRUFBRSxDQUFDO0lBQzdCLE9BQU8sT0FBTyxDQUFDLENBQUMsQ0FBQyxzQkFBc0IsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLHlCQUF5QixDQUFDO0FBQy9FLENBQUM7QUFFRCxvRkFBb0Y7QUFDcEYsU0FBUyxVQUFVO0lBQ2pCLElBQUksQ0FBQztRQUNILDRFQUE0RTtRQUM1RSx3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YUFBYSxDQUFDLFlBQVksRUFBRSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDeEUsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLGdGQUFnRjtJQUNsRixDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLGVBQWUsQ0FBQyxJQUFZO0lBQzFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsR0FBRyxNQUFNLENBQUMsR0FBRyxjQUFjLEVBQUUsQ0FBQztJQUM5Qyw0RUFBNEU7SUFDNUUsc0NBQXNDO0lBQ3RDLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBRyxNQUFNLEVBQUUsY0FBYyxDQUFDLEVBQUU7UUFDbkQsR0FBRyxFQUFFLElBQUk7UUFDVCxHQUFHLEVBQUUsUUFBUSxDQUFDLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxFQUFFLENBQUM7UUFDOUMsS0FBSyxFQUFFLElBQUk7S0FDWixDQUFDLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBCb290c3RyYXAgYSBicmFuZC1uZXcgZm9sZGVyIGludG8gYSB3b3JraW5nIGRieC10b29scyB3b3Jrc3BhY2UgYmVmb3JlIHByb2plbiBydW5zLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuaW1wb3J0IHsgZXhpc3RzU3luYywgcmVhZEZpbGVTeW5jLCB3cml0ZUZpbGVTeW5jIH0gZnJvbSBcIm5vZGU6ZnNcIjtcbmltcG9ydCB7IGNyZWF0ZVJlcXVpcmUgfSBmcm9tIFwibm9kZTptb2R1bGVcIjtcbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBpbnRybywgb3V0cm8gfSBmcm9tIFwiQGNsYWNrL3Byb21wdHNcIjtcbmltcG9ydCB7IGV4ZWMsIHByb2plY3QgfSBmcm9tIFwiQGRieC10b29scy9jb3JlXCI7XG5pbXBvcnQgeyBqc29uLCBsb2cgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgY2hpbGRFbnYsIHJlc29sdmVCdW5Bcmd2LCBydW5CdW4gfSBmcm9tIFwiLi9idW4udHNcIjtcbmltcG9ydCB7IHJvb3RMYWJlbCB9IGZyb20gXCIuL3Jvb3QudHNcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcImRieC10b29sczpib290c3RyYXBcIik7XG5cbi8qKiBQdWJsaXNoZWQgcGFja2FnZSBuYW1lIHVzZWQgZm9yIE5vZGUncyBzZWxmLXJlZmVyZW5jZSBtYW5pZmVzdCByZXNvbHV0aW9uLiAqL1xuY29uc3QgQ0xJX1BBQ0tBR0UgPSBcIkBkYngtdG9vbHMvY2xpXCI7XG5cbi8qKiBGYWxsYmFjayB3aGVuIHRoaXMgQ0xJJ3Mgb3duIHZlcnNpb24gaXNuJ3QgYSByZWFsIHJlbGVhc2UgKGFuIGluLXJlcG8gYDAuMC4wYCkuICovXG5jb25zdCBGQUxMQkFDS19QUk9KRU5fU1BFQ0lGSUVSID0gXCJAZGJ4LXRvb2xzL3Byb2plbkBsYXRlc3RcIjtcblxuLyoqXG4gKiBJbnN0YWxsIHRoZSBlbmdpbmUgYXQgVEhJUyBDTEkncyBvd24gdmVyc2lvbi4gVGhlIHR3byBhcmUgcmVsZWFzZWQgdG9nZXRoZXIgYnlcbiAqIHRoZSByb290IGBidW1wYCwgc28gdGhlIG1hdGNoaW5nIGVuZ2luZSBhbHdheXMgZXhpc3RzIG9uIHRoZSByZWdpc3RyeS5cbiAqXG4gKiBOb3QgYEBsYXRlc3RgLCBhbmQgbm90IGEgYmFyZSBgQGRieC10b29scy9wcm9qZW5gLiBBIGJhcmUgc3BlY2lmaWVyIGNhbiBsYW5kIG9uXG4gKiBhIHN0cmF5IGAwLjAuMGAsIHdob3NlIGBeMC4wLjBgIGNhcmV0IHRoZW4gcmVhY2hlcyBubyByZWFsIHJlbGVhc2UuIEFuIGV4cGxpY2l0XG4gKiByYW5nZSBwaW5uZWQgdG8gdGhpcyBDTEkncyBvd24gdmVyc2lvbiBhZG1pdHMgb25seSB0aGUgbWF0Y2hpbmcgZW5naW5lLCBzbyB0aGVcbiAqIENMSSBhbmQgdGhlIGVuZ2luZSBpdCBkcml2ZXMgbmV2ZXIgZHJpZnQgYWNyb3NzIGEgcmVsZWFzZSAodGhleSBhcmUgY3V0XG4gKiB0b2dldGhlciBieSB0aGUgcm9vdCBgYnVtcGApLlxuICovXG5mdW5jdGlvbiBkZWZhdWx0UHJvamVuU3BlY2lmaWVyKCk6IHN0cmluZyB7XG4gIGNvbnN0IHZlcnNpb24gPSBvd25WZXJzaW9uKCk7XG4gIHJldHVybiB2ZXJzaW9uID8gYEBkYngtdG9vbHMvcHJvamVuQF4ke3ZlcnNpb259YCA6IEZBTExCQUNLX1BST0pFTl9TUEVDSUZJRVI7XG59XG5cbi8qKiBUaGlzIENMSSdzIG93biByZWxlYXNlZCB2ZXJzaW9uLCBvciBgdW5kZWZpbmVkYCBmb3IgYW4gaW4tcmVwbyBgMC4wLjBgIGJ1aWxkLiAqL1xuZnVuY3Rpb24gb3duVmVyc2lvbigpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICB0cnkge1xuICAgIC8vIFJlc29sdmUgdGhyb3VnaCB0aGUgcGFja2FnZSdzIGV4cG9ydGVkIGAuL3BhY2thZ2UuanNvbmAsIHdoaWNoIHdvcmtzIGZyb21cbiAgICAvLyBib3RoIHNvdXJjZSAoYHNyYy9ib290c3RyYXAudHNgKSBhbmQgcHVibGlzaGVkIG91dHB1dFxuICAgIC8vIChgbGliL3NyYy9ib290c3RyYXAuanNgKS4gQSByZWxhdGl2ZSBVUkwgaXMgb25lIGxldmVsIGZyb20gdGhlIG1hbmlmZXN0XG4gICAgLy8gaW4gc291cmNlIGJ1dCB0d28gbGV2ZWxzIGF3YXkgYWZ0ZXIgY29tcGlsYXRpb24gYW5kIHNpbGVudGx5IGZlbGwgYmFjayB0b1xuICAgIC8vIGBAbGF0ZXN0YCBpbiBldmVyeSBpbnN0YWxsZWQgQ0xJLlxuICAgIGNvbnN0IG1hbmlmZXN0UGF0aCA9IGNyZWF0ZVJlcXVpcmUoaW1wb3J0Lm1ldGEudXJsKS5yZXNvbHZlKGAke0NMSV9QQUNLQUdFfS9wYWNrYWdlLmpzb25gKTtcbiAgICBjb25zdCB2ZXJzaW9uID0ganNvbi5wYXJzZVJlY29yZChyZWFkRmlsZVN5bmMobWFuaWZlc3RQYXRoLCBcInV0ZjhcIikpPy52ZXJzaW9uO1xuICAgIHJldHVybiB0eXBlb2YgdmVyc2lvbiA9PT0gXCJzdHJpbmdcIiAmJiB2ZXJzaW9uICE9PSBcIjAuMC4wXCIgPyB2ZXJzaW9uIDogdW5kZWZpbmVkO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbi8qKiBDb21wYXJlIGB4LnkuemAgdHJpcGxlczsgcmV0dXJucyA8MCwgMCwgb3IgPjAuIE1pc3NpbmcgcGFydHMgY291bnQgYXMgMC4gKi9cbmZ1bmN0aW9uIGNvbXBhcmVWZXJzaW9ucyhhOiBzdHJpbmcsIGI6IHN0cmluZyk6IG51bWJlciB7XG4gIGNvbnN0IHBhcnRzID0gKHY6IHN0cmluZykgPT4gdi5zcGxpdChcIi5cIikubWFwKChwKSA9PiBOdW1iZXIucGFyc2VJbnQocCwgMTApIHx8IDApO1xuICBjb25zdCBbeCwgeV0gPSBbcGFydHMoYSksIHBhcnRzKGIpXTtcbiAgcmV0dXJuIHhbMF0gLSB5WzBdIHx8IHhbMV0gLSB5WzFdIHx8IHhbMl0gLSB5WzJdO1xufVxuXG4vKiogVmVyc2lvbiBvZiB0aGUgZW5naW5lIGN1cnJlbnRseSBpbnN0YWxsZWQgYXQgYHJvb3RgLCBpZiBhbnkuICovXG5mdW5jdGlvbiBpbnN0YWxsZWRFbmdpbmVWZXJzaW9uKHJvb3Q6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHRyeSB7XG4gICAgY29uc3QgbWFuaWZlc3QgPSBqb2luKHJvb3QsIFwibm9kZV9tb2R1bGVzXCIsIFwiQGRieC10b29sc1wiLCBcInByb2plblwiLCBcInBhY2thZ2UuanNvblwiKTtcbiAgICBjb25zdCB2ZXJzaW9uID0ganNvbi5wYXJzZVJlY29yZChyZWFkRmlsZVN5bmMobWFuaWZlc3QsIFwidXRmOFwiKSk/LnZlcnNpb247XG4gICAgcmV0dXJuIHR5cGVvZiB2ZXJzaW9uID09PSBcInN0cmluZ1wiID8gdmVyc2lvbiA6IHVuZGVmaW5lZDtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG4vKipcbiAqIFVwZ3JhZGUgYW4gZXN0YWJsaXNoZWQgd29ya3NwYWNlIHdob3NlIGluc3RhbGxlZCBlbmdpbmUgcHJlZGF0ZXMgdGhpcyBDTEkuXG4gKlxuICogQm9vdHN0cmFwcGluZyBwaW5zIHRoZSBlbmdpbmUgb25jZSwgYW5kIG5vdGhpbmcgYWZ0ZXJ3YXJkcyByZXZpc2l0cyBpdCAtIHNvIGFcbiAqIHdvcmtzcGFjZSBjcmVhdGVkIG1vbnRocyBhZ28ga2VwdCByZXNvbHZpbmcgaXRzIG9yaWdpbmFsIGVuZ2luZSBubyBtYXR0ZXIgaG93XG4gKiBjdXJyZW50IHRoZSBDTEkgaW52b2tpbmcgaXQgd2FzLCBhbmQgZmFpbGVkIGluc2lkZSB0aGUgT0xEIGVuZ2luZSdzIGNvZGVcbiAqIChgc3luYyAtLXdhdGNoYCBkeWluZyBvbiBhIGBjb25jdXJyZW50bHlgIHRoYXQgZW5naW5lIG5ldmVyIGRlY2xhcmVkKS4gVGhlIHR3b1xuICogYXJlIHJlbGVhc2VkIGluIGxvY2tzdGVwLCBzbyB0aGlzIENMSSdzIHZlcnNpb24gaXMgZXhhY3RseSB0aGUgZW5naW5lIGl0XG4gKiBleHBlY3RzLlxuICpcbiAqIE9ubHkgZXZlciBtb3ZlcyBGT1JXQVJEOiBhbiBlbmdpbmUgYXQgb3IgYWhlYWQgb2YgdGhpcyBDTEkgaXMgbGVmdCBhbG9uZSwgc29cbiAqIGFuIG9sZGVyIENMSSBjYW5ub3QgZG93bmdyYWRlIGEgd29ya3NwYWNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZW5zdXJlRW5naW5lQ3VycmVudChyb290OiBzdHJpbmcpOiB2b2lkIHtcbiAgY29uc3QgZXhwZWN0ZWQgPSBvd25WZXJzaW9uKCk7XG4gIGlmICghZXhwZWN0ZWQpIHJldHVybjtcbiAgY29uc3QgaW5zdGFsbGVkID0gaW5zdGFsbGVkRW5naW5lVmVyc2lvbihyb290KTtcbiAgaWYgKGluc3RhbGxlZCAmJiBjb21wYXJlVmVyc2lvbnMoaW5zdGFsbGVkLCBleHBlY3RlZCkgPj0gMCkgcmV0dXJuO1xuICBydW5CdW4oW1wiYWRkXCIsIFwiLURcIiwgZGVmYXVsdFByb2plblNwZWNpZmllcigpXSwgcm9vdCk7XG59XG5cbi8vIFJlYWNoIHRoZSBjbGFzcyB0aHJvdWdoIGl0cyBtb2R1bGUgTkFNRVNQQUNFLiBDdXJyZW50IGVuZ2luZXMgYWxzbyBob2lzdCBpdFxuLy8gZmxhdCwgYnV0IGV2ZXJ5IGVuZ2luZSBldmVyIHB1Ymxpc2hlZCBleHBvcnRzIHRoZSBuYW1lc3BhY2UsIGFuZCB0aGlzIHRlbXBsYXRlXG4vLyBpcyByZXNvbHZlZCBhZ2FpbnN0IGBAbGF0ZXN0YCAtIGEgZmxhdCBpbXBvcnQgZGllcyBvbiBhbiBvbGRlciBvbmUgd2l0aFxuLy8gXCJkb2VzIG5vdCBwcm92aWRlIGFuIGV4cG9ydCBuYW1lZCAnREJYVG9vbHNOb2RlUHJvamVjdCdcIi5cbmNvbnN0IFBST0pFTlJDX1RFTVBMQVRFID0gYGltcG9ydCB7IHByb2plY3QgYXMgcHJvamVjdEFwaSB9IGZyb20gXCJAZGJ4LXRvb2xzL3Byb2plblwiO1xuXG5jb25zdCBwcm9qZWN0ID0gbmV3IHByb2plY3RBcGkuREJYVG9vbHNOb2RlUHJvamVjdCgpO1xucHJvamVjdC5zeW50aCgpO1xuYDtcblxuLyoqXG4gKiBUdXJuIGEgZm9sZGVyIGludG8gYSBmdW5jdGlvbmluZyBkYngtdG9vbHMgd29ya3NwYWNlOiBgYnVuIGluaXRgLCBzZWVkIHRoZVxuICogYHBhY2thZ2UuanNvbmAgd29ya3NwYWNlIGZpZWxkcyAoYnVuIHJlYWRzIGB3b3Jrc3BhY2VzYC9gdHJ1c3RlZERlcGVuZGVuY2llc2BcbiAqIGZyb20gdGhlIG1hbmlmZXN0KSwgYWRkIGBwcm9qZW5gL2B0eXBlc2NyaXB0YCArIHRoZSBlbmdpbmUgcGFja2FnZSwgd3JpdGUgYVxuICogbWluaW1hbCBgLnByb2plbnJjLnRzYCwgc3ludGggb25jZSAod2l0aCBgUFJPSkVOX0RJU0FCTEVfUE9TVGApLCB0aGVuIGluc3RhbGwuXG4gKiBEb2VzIG5vdCBydW4gYmFycmVscyAtIHJ1biBgYnVuIHJ1biBiYXJyZWxzYCBvciBhIGZ1bGwgcHJvamVuIHN5bnRoIHBvc3QtaW5zdGFsbFxuICogdG8gZ2VuZXJhdGUgcGFja2FnZSBiYXJyZWxzLlxuICpcbiAqIEV2ZXJ5IHN0ZXAgaXMgaWRlbXBvdGVudCBhbmQgc2VsZi1ndWFyZGVkLCBzbyB0aGlzIGlzIHNhZmUgdG8gcnVuIGFnYWluc3QgYVxuICogZm9sZGVyIHRoYXQgQUxSRUFEWSBoYXMgYSBoYW5kLWF1dGhvcmVkIGAucHJvamVucmMudHNgIChhbmQgZXZlbiBhIGNvbW1pdHRlZFxuICogYHBhY2thZ2UuanNvbmApIGJ1dCBpcyBtaXNzaW5nIHRoZSBpbnN0YWxsZWQgdG9vbGNoYWluIC0gZS5nLiBhIGZyZXNobHkgY29waWVkXG4gKiBwcm9qZWN0IHdob3NlIGdlbmVyYXRlZCBmaWxlcyAoaW5jbHVkaW5nIG1hbmlmZXN0cykgYXJlIGdpdGlnbm9yZWQuIEluIHRoYXRcbiAqIGNhc2UgYGJ1biBpbml0YCBhbmQgdGhlIGAucHJvamVucmMudHNgIHNjYWZmb2xkIGFyZSBza2lwcGVkLCBidXQgdGhlIGVuZ2luZSArXG4gKiBwcm9qZW4gYXJlIChyZSlpbnN0YWxsZWQgc28gdGhlIHN1YnNlcXVlbnQgc3ludGggY2FuIHJlZ2VuZXJhdGUgZXZlcnl0aGluZy5cbiAqIFNlZSB7QGxpbmsgc2VlZFRvb2xjaGFpbn0uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBib290c3RyYXBXb3Jrc3BhY2UoXG4gIHJvb3Q6IHN0cmluZyxcbiAgcHJvamVuU3BlY2lmaWVyOiBzdHJpbmcgPSBkZWZhdWx0UHJvamVuU3BlY2lmaWVyKCksXG4pOiB2b2lkIHtcbiAgaW50cm8oYEJvb3RzdHJhcHBpbmcgZGJ4LXRvb2xzIHdvcmtzcGFjZSBpbiAke3Jvb3RMYWJlbChyb290KX1gKTtcblxuICBzZWVkVG9vbGNoYWluKHJvb3QsIHByb2plblNwZWNpZmllcik7XG5cbiAgY29uc3QgcHJvamVucmMgPSBqb2luKHJvb3QsIFwiLnByb2plbnJjLnRzXCIpO1xuICBpZiAoIWV4aXN0c1N5bmMocHJvamVucmMpKSB7XG4gICAgd3JpdGVGaWxlU3luYyhwcm9qZW5yYywgUFJPSkVOUkNfVEVNUExBVEUpO1xuICB9XG5cbiAgcnVuSW5pdGlhbFN5bnRoKHJvb3QpO1xuXG4gIHJ1bkJ1bihbXCJpbnN0YWxsXCJdLCByb290KTtcbiAgb3V0cm8oXCJXb3Jrc3BhY2UgcmVhZHkgLSByZS1ydW4gZGJ4LXRvb2xzIG9yIGFkZCBwYWNrYWdlcyB1bmRlciBwYWNrYWdlcy9cIik7XG59XG5cbi8qKlxuICogSW5zdGFsbCB0aGUgdG9vbGNoYWluIGEgc3ludGggbmVlZHMgKGBwcm9qZW5gLCBgdHlwZXNjcmlwdGAsIGFuZCB0aGUgZGJ4LXRvb2xzXG4gKiBlbmdpbmUpLCBzZWVkaW5nIGEgYHBhY2thZ2UuanNvbmAgZmlyc3Qgd2hlbiBhYnNlbnQuIGJ1biByZWFkcyBpdHMgd29ya3NwYWNlXG4gKiBjb25maWcgKGB3b3Jrc3BhY2VzYC9gdHJ1c3RlZERlcGVuZGVuY2llc2ApIGZyb20gdGhlIG1hbmlmZXN0LCBzbyB0aGVyZSBpcyBub1xuICogc2VwYXJhdGUgd29ya3NwYWNlIGZpbGUgdG8gc2VlZCAtIHRoZSBlbmdpbmUgd3JpdGVzIGBwbnBtLXdvcmtzcGFjZS55YW1sYCBhdFxuICogc3ludGggZm9yIHRoZSBEYXRhYnJpY2tzIEFwcHMgcGxhdGZvcm0uIElkZW1wb3RlbnQ6IHJ1biBpdCB3aGVuZXZlciB0aGUgZW5naW5lXG4gKiBpcyBtaXNzaW5nLCBzbyBhIGNvcGllZCBwcm9qZWN0IHdpdGggYSBgLnByb2plbnJjLnRzYCBidXQgbm9cbiAqIGBub2RlX21vZHVsZXNgL21hbmlmZXN0IGNhbiBiZSBicm91Z2h0IHVwIHRvIGEgc3ludGgtcmVhZHkgc3RhdGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWVkVG9vbGNoYWluKFxuICByb290OiBzdHJpbmcsXG4gIHByb2plblNwZWNpZmllcjogc3RyaW5nID0gZGVmYXVsdFByb2plblNwZWNpZmllcigpLFxuKTogdm9pZCB7XG4gIGNvbnN0IG1hbmlmZXN0UGF0aCA9IGpvaW4ocm9vdCwgXCJwYWNrYWdlLmpzb25cIik7XG4gIGlmICghZXhpc3RzU3luYyhtYW5pZmVzdFBhdGgpKSB7XG4gICAgcnVuQnVuKFtcImluaXRcIiwgXCIteVwiXSwgcm9vdCk7XG4gICAgbm9ybWFsaXplU2VlZE1hbmlmZXN0KG1hbmlmZXN0UGF0aCk7XG4gIH1cblxuICBzZWVkUmVnaXN0cnkocm9vdCk7XG5cbiAgY29uc3Qga2VybmVsQXJjaCA9IGV4ZWMuc3Bhd25TeW5jKFwidW5hbWVcIiwgW1wiLW1cIl0sIHtcbiAgICBzdGRpbjogXCJpZ25vcmVcIixcbiAgICBzdGRvdXQ6IFwiY2FwdHVyZVwiLFxuICAgIHN0ZGVycjogXCJpZ25vcmVcIixcbiAgfSkuc3Rkb3V0O1xuICBsb2dnZXIuaW5mbyhcInNlZWRpbmcgdG9vbGNoYWluXCIsIHtcbiAgICBub2RlOiBwcm9jZXNzLnZlcnNpb24sXG4gICAgYnVuOiBwcm9jZXNzLnZlcnNpb25zLmJ1bixcbiAgICBwbGF0Zm9ybTogcHJvY2Vzcy5wbGF0Zm9ybSxcbiAgICBhcmNoOiBwcm9jZXNzLmFyY2gsXG4gICAga2VybmVsQXJjaDoga2VybmVsQXJjaCB8fCBcInVua25vd25cIixcbiAgICBlbmdpbmU6IHByb2plblNwZWNpZmllcixcbiAgfSk7XG4gIHJ1bkJ1bihbXCJhZGRcIiwgXCItRFwiLCBcInByb2plblwiLCBcInR5cGVzY3JpcHRAXjUuOS4zXCIsIFwiQHR5cGVzL2J1blwiLCBwcm9qZW5TcGVjaWZpZXJdLCByb290KTtcbn1cblxuLyoqXG4gKiBQaW4gYSBub24tZGVmYXVsdCByZWdpc3RyeSBpbnRvIHRoZSBuZXcgcm9vdCdzIGAubnBtcmNgLlxuICpcbiAqIFRoZSBDTEkgYWxyZWFkeSBmb3JjZXMgYC0tcmVnaXN0cnlgIG9udG8gdGhlIGJ1biBpbnZvY2F0aW9ucyBpdCBtYWtlcyBpdHNlbGYsXG4gKiBidXQgYSBib290c3RyYXBwZWQgd29ya3NwYWNlIG91dGxpdmVzIHRoaXMgcHJvY2VzczogZXZlcnkgbGF0ZXIgYGJ1biBpbnN0YWxsYFxuICogdGhlIGRldmVsb3BlciAob3IgcHJvamVuJ3MgcG9zdC1zeW50aCBzdGVwKSBydW5zIGlzIG9uIGl0cyBvd24uIGJ1biBpZ25vcmVzXG4gKiBgbnBtX2NvbmZpZ19yZWdpc3RyeWAgZnJvbSB0aGUgZW52aXJvbm1lbnQsIHNvIHdpdGhvdXQgYSBmaWxlIG9uIGRpc2sgdGhvc2VcbiAqIHJ1bnMgcmV2ZXJ0IHRvIGBodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy9gIC0gd2hpY2ggaXMgYSBoYXJkIGZhaWx1cmUgd2hlcmVcbiAqIHRoZSBjdXN0b20gcmVnaXN0cnkgd2FzIHRoZSBvbmx5IHJlYWNoYWJsZSBvbmUuXG4gKlxuICogT25seSB3cml0ZXMgZm9yIGFuIGFjdHVhbCBvdmVycmlkZSwgbmV2ZXIgY3JlYXRlcyBhIGZpbGUganVzdCB0byBuYW1lIG5wbWpzLFxuICogYW5kIG5ldmVyIG92ZXJ3cml0ZXMgYW4gZXhpc3RpbmcgYC5ucG1yY2AgKHRoZSBkZXZlbG9wZXIncyBvd24gd2lucykuXG4gKi9cbmZ1bmN0aW9uIHNlZWRSZWdpc3RyeShyb290OiBzdHJpbmcpOiB2b2lkIHtcbiAgY29uc3QgcmVnaXN0cnkgPSBwcm9qZWN0Lm5wbVJlZ2lzdHJ5KG51bGwsIHsgb3ZlcnJpZGVPbmx5OiB0cnVlLCBlbnZWYXJzOiB0cnVlIH0pPy50b1N0cmluZygpO1xuICBpZiAoIXJlZ2lzdHJ5KSByZXR1cm47XG4gIGNvbnN0IG5wbXJjID0gam9pbihyb290LCBcIi5ucG1yY1wiKTtcbiAgaWYgKGV4aXN0c1N5bmMobnBtcmMpKSByZXR1cm47XG4gIHdyaXRlRmlsZVN5bmMobnBtcmMsIGByZWdpc3RyeT0ke3JlZ2lzdHJ5fVxcbmApO1xufVxuXG4vKipcbiAqIE1ha2Ugd2hhdCBgYnVuIGluaXRgIHByb2R1Y2VkIHNhZmUgdG8gc3ludGggYWdhaW5zdDogZm9yY2UgYHR5cGU6IFwibW9kdWxlXCJgXG4gKiAoYnVuIHJ1bnMgYC5wcm9qZW5yYy50c2AgZmluZSBlaXRoZXIgd2F5LCBidXQgcHJvamVuJ3MgRVNNIHNvdXJjZXMgYW5kIHRoZVxuICogZW1pdHRlZCBjb25maWcgYXNzdW1lIG1vZHVsZSB0eXBlKSBhbmQgZHJvcCBhbnkgYHBhY2thZ2VNYW5hZ2VyYC9gZGV2RW5naW5lc2BcbiAqIGZpZWxkIHRoYXQgd291bGQgcGluIGEgZGlmZmVyZW50IG1hbmFnZXIuIHByb2plbiByZWdlbmVyYXRlcyB0aGUgd2hvbGUgbWFuaWZlc3RcbiAqIGF0IHN5bnRoLCBzbyB0aGlzIG9ubHkgaGFzIHRvIGhvbGQgdGhlIHNlZWQgdG9nZXRoZXIgbG9uZyBlbm91Z2ggdG8gZ2V0IHRoZXJlLlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVTZWVkTWFuaWZlc3QobWFuaWZlc3RQYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IGpzb24ucGFyc2VSZWNvcmQocmVhZEZpbGVTeW5jKG1hbmlmZXN0UGF0aCwgXCJ1dGY4XCIpKTtcbiAgICBpZiAoIW1hbmlmZXN0KSByZXR1cm47XG4gICAgZGVsZXRlIG1hbmlmZXN0LmRldkVuZ2luZXM7XG4gICAgZGVsZXRlIG1hbmlmZXN0LnBhY2thZ2VNYW5hZ2VyO1xuICAgIG1hbmlmZXN0LnR5cGUgPSBcIm1vZHVsZVwiO1xuICAgIHdyaXRlRmlsZVN5bmMobWFuaWZlc3RQYXRoLCBgJHtKU09OLnN0cmluZ2lmeShtYW5pZmVzdCwgbnVsbCwgMil9XFxuYCk7XG4gIH0gY2F0Y2gge1xuICAgIC8vIEEgbWFsZm9ybWVkL2Fic2VudCBtYW5pZmVzdCBoZXJlIGp1c3QgbWVhbnMgdGhlIGxhdGVyIGBidW4gYWRkYCByZWNyZWF0ZXMgaXQuXG4gIH1cbn1cblxuLyoqXG4gKiBSdW4gdGhlIGluaXRpYWwgc3ludGggYnkgZXhlY3V0aW5nIGAucHJvamVucmMudHNgIGRpcmVjdGx5IHdpdGggYnVuICh3aXRoXG4gKiBgUFJPSkVOX0RJU0FCTEVfUE9TVGAgc2V0KSwgTk9UIGBwcm9qZW4gPHRhc2s+YC4gVXNlIHJpZ2h0IGFmdGVyIHNlZWRpbmcgYVxuICogZnJlc2ggd29ya3NwYWNlOiB0aGUgcHJvamVuIFRBU0tTIChgc3luY2AsIGBiYXJyZWxzYCwgLi4uKSBvbmx5IGV4aXN0IG9uY2VcbiAqIGAucHJvamVucmMudHNgIGhhcyBydW4gb25jZSwgc28gYHByb2plbiBzeW5jYCBjYW4ndCBiZSB0aGUgYm9vdHN0cmFwcGluZyBzdGVwLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcnVuSW5pdGlhbFN5bnRoKHJvb3Q6IHN0cmluZyk6IHZvaWQge1xuICBjb25zdCBbY29tbWFuZCwgLi4ucHJlZml4XSA9IHJlc29sdmVCdW5Bcmd2KCk7XG4gIC8vIGJ1biBydW5zIHRoZSBgLnRzYCBkaXJlY3RseS4gVGhlIHJlZ2lzdHJ5IHJlYWNoZXMgYW55dGhpbmcgbmVzdGVkIHRocm91Z2hcbiAgLy8gYGNoaWxkRW52YCBhbmQgdGhlIHNlZWRlZCBgLm5wbXJjYC5cbiAgZXhlYy5zcGF3blN5bmMoY29tbWFuZCwgWy4uLnByZWZpeCwgXCIucHJvamVucmMudHNcIl0sIHtcbiAgICBjd2Q6IHJvb3QsXG4gICAgZW52OiBjaGlsZEVudih7IFBST0pFTl9ESVNBQkxFX1BPU1Q6IFwidHJ1ZVwiIH0pLFxuICAgIGNoZWNrOiB0cnVlLFxuICB9KTtcbn1cbiJdfQ==
213
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9vdHN0cmFwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Jvb3RzdHJhcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDNUMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNqQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDaEQsT0FBTyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNuRCxPQUFPLEVBQUUsUUFBUSxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDNUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUV0QyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLHFCQUFxQixDQUFDLENBQUM7QUFFakQsaUZBQWlGO0FBQ2pGLE1BQU0sV0FBVyxHQUFHLGdCQUFnQixDQUFDO0FBRXJDLHNGQUFzRjtBQUN0RixNQUFNLHlCQUF5QixHQUFHLDBCQUEwQixDQUFDO0FBRTdEOzs7Ozs7Ozs7R0FTRztBQUNILFNBQVMsc0JBQXNCO0lBQzdCLE1BQU0sT0FBTyxHQUFHLFVBQVUsRUFBRSxDQUFDO0lBQzdCLE9BQU8sT0FBTyxDQUFDLENBQUMsQ0FBQyxzQkFBc0IsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLHlCQUF5QixDQUFDO0FBQy9FLENBQUM7QUFFRCxvRkFBb0Y7QUFDcEYsU0FBUyxVQUFVO0lBQ2pCLElBQUksQ0FBQztRQUNILDRFQUE0RTtRQUM1RSx3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QUFhLENBQUMsWUFBWSxFQUFFLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN4RSxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsZ0ZBQWdGO0lBQ2xGLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsZUFBZSxDQUFDLElBQVk7SUFDMUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxHQUFHLE1BQU0sQ0FBQyxHQUFHLGNBQWMsRUFBRSxDQUFDO0lBQzlDLDRFQUE0RTtJQUM1RSxzQ0FBc0M7SUFDdEMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLE1BQU0sRUFBRSxjQUFjLENBQUMsRUFBRTtRQUNuRCxHQUFHLEVBQUUsSUFBSTtRQUNULEdBQUcsRUFBRSxRQUFRLENBQUMsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLEVBQUUsQ0FBQztRQUM5QyxLQUFLLEVBQUUsSUFBSTtLQUNaLENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEJvb3RzdHJhcCBhIGJyYW5kLW5ldyBmb2xkZXIgaW50byBhIHdvcmtpbmcgZGJ4LXRvb2xzIHdvcmtzcGFjZSBiZWZvcmUgcHJvamVuIHJ1bnMuXG4gKlxuICogQG1vZHVsZVxuICovXG5pbXBvcnQgeyBleGlzdHNTeW5jLCByZWFkRmlsZVN5bmMsIHdyaXRlRmlsZVN5bmMgfSBmcm9tIFwibm9kZTpmc1wiO1xuaW1wb3J0IHsgY3JlYXRlUmVxdWlyZSB9IGZyb20gXCJub2RlOm1vZHVsZVwiO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB7IGludHJvLCBvdXRybyB9IGZyb20gXCJAY2xhY2svcHJvbXB0c1wiO1xuaW1wb3J0IHsgZXhlYywgcHJvamVjdCB9IGZyb20gXCJAZGJ4LXRvb2xzL2NvcmVcIjtcbmltcG9ydCB7IGpzb24sIGxvZyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgeyBjaGlsZEVudiwgcmVzb2x2ZUJ1bkFyZ3YsIHJ1bkJ1biB9IGZyb20gXCIuL2J1bi50c1wiO1xuaW1wb3J0IHsgcm9vdExhYmVsIH0gZnJvbSBcIi4vcm9vdC50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwiZGJ4LXRvb2xzOmJvb3RzdHJhcFwiKTtcblxuLyoqIFB1Ymxpc2hlZCBwYWNrYWdlIG5hbWUgdXNlZCBmb3IgTm9kZSdzIHNlbGYtcmVmZXJlbmNlIG1hbmlmZXN0IHJlc29sdXRpb24uICovXG5jb25zdCBDTElfUEFDS0FHRSA9IFwiQGRieC10b29scy9jbGlcIjtcblxuLyoqIEZhbGxiYWNrIHdoZW4gdGhpcyBDTEkncyBvd24gdmVyc2lvbiBpc24ndCBhIHJlYWwgcmVsZWFzZSAoYW4gaW4tcmVwbyBgMC4wLjBgKS4gKi9cbmNvbnN0IEZBTExCQUNLX1BST0pFTl9TUEVDSUZJRVIgPSBcIkBkYngtdG9vbHMvcHJvamVuQGxhdGVzdFwiO1xuXG4vKipcbiAqIEluc3RhbGwgdGhlIGVuZ2luZSBhdCBUSElTIENMSSdzIG93biB2ZXJzaW9uLiBUaGUgdHdvIGFyZSByZWxlYXNlZCB0b2dldGhlciBieVxuICogdGhlIHJvb3QgYGJ1bXBgLCBzbyB0aGUgbWF0Y2hpbmcgZW5naW5lIGFsd2F5cyBleGlzdHMgb24gdGhlIHJlZ2lzdHJ5LlxuICpcbiAqIE5vdCBgQGxhdGVzdGAsIGFuZCBub3QgYSBiYXJlIGBAZGJ4LXRvb2xzL3Byb2plbmAuIEEgYmFyZSBzcGVjaWZpZXIgY2FuIGxhbmQgb25cbiAqIGEgc3RyYXkgYDAuMC4wYCwgd2hvc2UgYF4wLjAuMGAgY2FyZXQgdGhlbiByZWFjaGVzIG5vIHJlYWwgcmVsZWFzZS4gQW4gZXhwbGljaXRcbiAqIHJhbmdlIHBpbm5lZCB0byB0aGlzIENMSSdzIG93biB2ZXJzaW9uIGFkbWl0cyBvbmx5IHRoZSBtYXRjaGluZyBlbmdpbmUsIHNvIHRoZVxuICogQ0xJIGFuZCB0aGUgZW5naW5lIGl0IGRyaXZlcyBuZXZlciBkcmlmdCBhY3Jvc3MgYSByZWxlYXNlICh0aGV5IGFyZSBjdXRcbiAqIHRvZ2V0aGVyIGJ5IHRoZSByb290IGBidW1wYCkuXG4gKi9cbmZ1bmN0aW9uIGRlZmF1bHRQcm9qZW5TcGVjaWZpZXIoKTogc3RyaW5nIHtcbiAgY29uc3QgdmVyc2lvbiA9IG93blZlcnNpb24oKTtcbiAgcmV0dXJuIHZlcnNpb24gPyBgQGRieC10b29scy9wcm9qZW5AXiR7dmVyc2lvbn1gIDogRkFMTEJBQ0tfUFJPSkVOX1NQRUNJRklFUjtcbn1cblxuLyoqIFRoaXMgQ0xJJ3Mgb3duIHJlbGVhc2VkIHZlcnNpb24sIG9yIGB1bmRlZmluZWRgIGZvciBhbiBpbi1yZXBvIGAwLjAuMGAgYnVpbGQuICovXG5mdW5jdGlvbiBvd25WZXJzaW9uKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHRyeSB7XG4gICAgLy8gUmVzb2x2ZSB0aHJvdWdoIHRoZSBwYWNrYWdlJ3MgZXhwb3J0ZWQgYC4vcGFja2FnZS5qc29uYCwgd2hpY2ggd29ya3MgZnJvbVxuICAgIC8vIGJvdGggc291cmNlIChgc3JjL2Jvb3RzdHJhcC50c2ApIGFuZCBwdWJsaXNoZWQgb3V0cHV0XG4gICAgLy8gKGBsaWIvc3JjL2Jvb3RzdHJhcC5qc2ApLiBBIHJlbGF0aXZlIFVSTCBpcyBvbmUgbGV2ZWwgZnJvbSB0aGUgbWFuaWZlc3RcbiAgICAvLyBpbiBzb3VyY2UgYnV0IHR3byBsZXZlbHMgYXdheSBhZnRlciBjb21waWxhdGlvbiBhbmQgc2lsZW50bHkgZmVsbCBiYWNrIHRvXG4gICAgLy8gYEBsYXRlc3RgIGluIGV2ZXJ5IGluc3RhbGxlZCBDTEkuXG4gICAgY29uc3QgbWFuaWZlc3RQYXRoID0gY3JlYXRlUmVxdWlyZShpbXBvcnQubWV0YS51cmwpLnJlc29sdmUoYCR7Q0xJX1BBQ0tBR0V9L3BhY2thZ2UuanNvbmApO1xuICAgIGNvbnN0IHZlcnNpb24gPSBqc29uLnBhcnNlUmVjb3JkKHJlYWRGaWxlU3luYyhtYW5pZmVzdFBhdGgsIFwidXRmOFwiKSk/LnZlcnNpb247XG4gICAgcmV0dXJuIHR5cGVvZiB2ZXJzaW9uID09PSBcInN0cmluZ1wiICYmIHZlcnNpb24gIT09IFwiMC4wLjBcIiA/IHZlcnNpb24gOiB1bmRlZmluZWQ7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuLyoqIENvbXBhcmUgYHgueS56YCB0cmlwbGVzOyByZXR1cm5zIDwwLCAwLCBvciA+MC4gTWlzc2luZyBwYXJ0cyBjb3VudCBhcyAwLiAqL1xuZnVuY3Rpb24gY29tcGFyZVZlcnNpb25zKGE6IHN0cmluZywgYjogc3RyaW5nKTogbnVtYmVyIHtcbiAgY29uc3QgcGFydHMgPSAodjogc3RyaW5nKSA9PiB2LnNwbGl0KFwiLlwiKS5tYXAoKHApID0+IE51bWJlci5wYXJzZUludChwLCAxMCkgfHwgMCk7XG4gIGNvbnN0IFt4LCB5XSA9IFtwYXJ0cyhhKSwgcGFydHMoYildO1xuICByZXR1cm4geFswXSAtIHlbMF0gfHwgeFsxXSAtIHlbMV0gfHwgeFsyXSAtIHlbMl07XG59XG5cbi8qKiBWZXJzaW9uIG9mIHRoZSBlbmdpbmUgY3VycmVudGx5IGluc3RhbGxlZCBhdCBgcm9vdGAsIGlmIGFueS4gKi9cbmZ1bmN0aW9uIGluc3RhbGxlZEVuZ2luZVZlcnNpb24ocm9vdDogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IGpvaW4ocm9vdCwgXCJub2RlX21vZHVsZXNcIiwgXCJAZGJ4LXRvb2xzXCIsIFwicHJvamVuXCIsIFwicGFja2FnZS5qc29uXCIpO1xuICAgIGNvbnN0IHZlcnNpb24gPSBqc29uLnBhcnNlUmVjb3JkKHJlYWRGaWxlU3luYyhtYW5pZmVzdCwgXCJ1dGY4XCIpKT8udmVyc2lvbjtcbiAgICByZXR1cm4gdHlwZW9mIHZlcnNpb24gPT09IFwic3RyaW5nXCIgPyB2ZXJzaW9uIDogdW5kZWZpbmVkO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbi8qKlxuICogVXBncmFkZSBhbiBlc3RhYmxpc2hlZCB3b3Jrc3BhY2Ugd2hvc2UgaW5zdGFsbGVkIGVuZ2luZSBwcmVkYXRlcyB0aGlzIENMSS5cbiAqXG4gKiBCb290c3RyYXBwaW5nIHBpbnMgdGhlIGVuZ2luZSBvbmNlLCBzbyB3aXRob3V0IHRoaXMgYSB3b3Jrc3BhY2UgY3JlYXRlZCBtb250aHMgYWdvXG4gKiB3b3VsZCBrZWVwIHJlc29sdmluZyBpdHMgb3JpZ2luYWwgZW5naW5lIG5vIG1hdHRlciBob3cgY3VycmVudCB0aGUgQ0xJIGludm9raW5nIGl0XG4gKiBpcywgYW5kIHdvdWxkIGZhaWwgaW5zaWRlIFRIQVQgZW5naW5lJ3MgY29kZSAoYHN5bmMgLS13YXRjaGAgZHlpbmcgb24gYVxuICogYGNvbmN1cnJlbnRseWAgaXQgbmV2ZXIgZGVjbGFyZWQpLiBUaGUgdHdvIGFyZSByZWxlYXNlZCBpbiBsb2Nrc3RlcCwgc28gdGhpcyBDTEknc1xuICogdmVyc2lvbiBpcyBleGFjdGx5IHRoZSBlbmdpbmUgaXQgZXhwZWN0cy5cbiAqXG4gKiBPbmx5IGV2ZXIgbW92ZXMgRk9SV0FSRDogYW4gZW5naW5lIGF0IG9yIGFoZWFkIG9mIHRoaXMgQ0xJIGlzIGxlZnQgYWxvbmUsIHNvXG4gKiBhbiBvbGRlciBDTEkgY2Fubm90IGRvd25ncmFkZSBhIHdvcmtzcGFjZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuc3VyZUVuZ2luZUN1cnJlbnQocm9vdDogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IGV4cGVjdGVkID0gb3duVmVyc2lvbigpO1xuICBpZiAoIWV4cGVjdGVkKSByZXR1cm47XG4gIGNvbnN0IGluc3RhbGxlZCA9IGluc3RhbGxlZEVuZ2luZVZlcnNpb24ocm9vdCk7XG4gIGlmIChpbnN0YWxsZWQgJiYgY29tcGFyZVZlcnNpb25zKGluc3RhbGxlZCwgZXhwZWN0ZWQpID49IDApIHJldHVybjtcbiAgcnVuQnVuKFtcImFkZFwiLCBcIi1EXCIsIGRlZmF1bHRQcm9qZW5TcGVjaWZpZXIoKV0sIHJvb3QpO1xufVxuXG4vLyBSZWFjaCB0aGUgY2xhc3MgdGhyb3VnaCBpdHMgbW9kdWxlIE5BTUVTUEFDRS4gQ3VycmVudCBlbmdpbmVzIGFsc28gaG9pc3QgaXRcbi8vIGZsYXQsIGJ1dCBldmVyeSBlbmdpbmUgZXZlciBwdWJsaXNoZWQgZXhwb3J0cyB0aGUgbmFtZXNwYWNlLCBhbmQgdGhpcyB0ZW1wbGF0ZVxuLy8gaXMgcmVzb2x2ZWQgYWdhaW5zdCBgQGxhdGVzdGAgLSBhIGZsYXQgaW1wb3J0IGRpZXMgb24gYW4gb2xkZXIgb25lIHdpdGhcbi8vIFwiZG9lcyBub3QgcHJvdmlkZSBhbiBleHBvcnQgbmFtZWQgJ0RCWFRvb2xzTm9kZVByb2plY3QnXCIuXG5jb25zdCBQUk9KRU5SQ19URU1QTEFURSA9IGBpbXBvcnQgeyBwcm9qZWN0IGFzIHByb2plY3RBcGkgfSBmcm9tIFwiQGRieC10b29scy9wcm9qZW5cIjtcblxuY29uc3QgcHJvamVjdCA9IG5ldyBwcm9qZWN0QXBpLkRCWFRvb2xzTm9kZVByb2plY3QoKTtcbnByb2plY3Quc3ludGgoKTtcbmA7XG5cbi8qKlxuICogVHVybiBhIGZvbGRlciBpbnRvIGEgZnVuY3Rpb25pbmcgZGJ4LXRvb2xzIHdvcmtzcGFjZTogYGJ1biBpbml0YCwgc2VlZCB0aGVcbiAqIGBwYWNrYWdlLmpzb25gIHdvcmtzcGFjZSBmaWVsZHMgKGJ1biByZWFkcyBgd29ya3NwYWNlc2AvYHRydXN0ZWREZXBlbmRlbmNpZXNgXG4gKiBmcm9tIHRoZSBtYW5pZmVzdCksIGFkZCBgcHJvamVuYC9gdHlwZXNjcmlwdGAgKyB0aGUgZW5naW5lIHBhY2thZ2UsIHdyaXRlIGFcbiAqIG1pbmltYWwgYC5wcm9qZW5yYy50c2AsIHN5bnRoIG9uY2UgKHdpdGggYFBST0pFTl9ESVNBQkxFX1BPU1RgKSwgdGhlbiBpbnN0YWxsLlxuICogRG9lcyBub3QgcnVuIGJhcnJlbHMgLSBydW4gYGJ1biBydW4gYmFycmVsc2Agb3IgYSBmdWxsIHByb2plbiBzeW50aCBwb3N0LWluc3RhbGxcbiAqIHRvIGdlbmVyYXRlIHBhY2thZ2UgYmFycmVscy5cbiAqXG4gKiBFdmVyeSBzdGVwIGlzIGlkZW1wb3RlbnQgYW5kIHNlbGYtZ3VhcmRlZCwgc28gdGhpcyBpcyBzYWZlIHRvIHJ1biBhZ2FpbnN0IGFcbiAqIGZvbGRlciB0aGF0IEFMUkVBRFkgaGFzIGEgaGFuZC1hdXRob3JlZCBgLnByb2plbnJjLnRzYCAoYW5kIGV2ZW4gYSBjb21taXR0ZWRcbiAqIGBwYWNrYWdlLmpzb25gKSBidXQgaXMgbWlzc2luZyB0aGUgaW5zdGFsbGVkIHRvb2xjaGFpbiAtIGUuZy4gYSBmcmVzaGx5IGNvcGllZFxuICogcHJvamVjdCB3aG9zZSBnZW5lcmF0ZWQgZmlsZXMgKGluY2x1ZGluZyBtYW5pZmVzdHMpIGFyZSBnaXRpZ25vcmVkLiBJbiB0aGF0XG4gKiBjYXNlIGBidW4gaW5pdGAgYW5kIHRoZSBgLnByb2plbnJjLnRzYCBzY2FmZm9sZCBhcmUgc2tpcHBlZCwgYnV0IHRoZSBlbmdpbmUgK1xuICogcHJvamVuIGFyZSAocmUpaW5zdGFsbGVkIHNvIHRoZSBzdWJzZXF1ZW50IHN5bnRoIGNhbiByZWdlbmVyYXRlIGV2ZXJ5dGhpbmcuXG4gKiBTZWUge0BsaW5rIHNlZWRUb29sY2hhaW59LlxuICovXG5leHBvcnQgZnVuY3Rpb24gYm9vdHN0cmFwV29ya3NwYWNlKFxuICByb290OiBzdHJpbmcsXG4gIHByb2plblNwZWNpZmllcjogc3RyaW5nID0gZGVmYXVsdFByb2plblNwZWNpZmllcigpLFxuKTogdm9pZCB7XG4gIGludHJvKGBCb290c3RyYXBwaW5nIGRieC10b29scyB3b3Jrc3BhY2UgaW4gJHtyb290TGFiZWwocm9vdCl9YCk7XG5cbiAgc2VlZFRvb2xjaGFpbihyb290LCBwcm9qZW5TcGVjaWZpZXIpO1xuXG4gIGNvbnN0IHByb2plbnJjID0gam9pbihyb290LCBcIi5wcm9qZW5yYy50c1wiKTtcbiAgaWYgKCFleGlzdHNTeW5jKHByb2plbnJjKSkge1xuICAgIHdyaXRlRmlsZVN5bmMocHJvamVucmMsIFBST0pFTlJDX1RFTVBMQVRFKTtcbiAgfVxuXG4gIHJ1bkluaXRpYWxTeW50aChyb290KTtcblxuICBydW5CdW4oW1wiaW5zdGFsbFwiXSwgcm9vdCk7XG4gIG91dHJvKFwiV29ya3NwYWNlIHJlYWR5IC0gcmUtcnVuIGRieC10b29scyBvciBhZGQgcGFja2FnZXMgdW5kZXIgcGFja2FnZXMvXCIpO1xufVxuXG4vKipcbiAqIEluc3RhbGwgdGhlIHRvb2xjaGFpbiBhIHN5bnRoIG5lZWRzIChgcHJvamVuYCwgYHR5cGVzY3JpcHRgLCBhbmQgdGhlIGRieC10b29sc1xuICogZW5naW5lKSwgc2VlZGluZyBhIGBwYWNrYWdlLmpzb25gIGZpcnN0IHdoZW4gYWJzZW50LiBidW4gcmVhZHMgaXRzIHdvcmtzcGFjZVxuICogY29uZmlnIChgd29ya3NwYWNlc2AvYHRydXN0ZWREZXBlbmRlbmNpZXNgKSBmcm9tIHRoZSBtYW5pZmVzdCwgc28gdGhlcmUgaXMgbm9cbiAqIHNlcGFyYXRlIHdvcmtzcGFjZSBmaWxlIHRvIHNlZWQgLSB0aGUgZW5naW5lIHdyaXRlcyBgcG5wbS13b3Jrc3BhY2UueWFtbGAgYXRcbiAqIHN5bnRoIGZvciB0aGUgRGF0YWJyaWNrcyBBcHBzIHBsYXRmb3JtLiBJZGVtcG90ZW50OiBydW4gaXQgd2hlbmV2ZXIgdGhlIGVuZ2luZVxuICogaXMgbWlzc2luZywgc28gYSBjb3BpZWQgcHJvamVjdCB3aXRoIGEgYC5wcm9qZW5yYy50c2AgYnV0IG5vXG4gKiBgbm9kZV9tb2R1bGVzYC9tYW5pZmVzdCBjYW4gYmUgYnJvdWdodCB1cCB0byBhIHN5bnRoLXJlYWR5IHN0YXRlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VlZFRvb2xjaGFpbihcbiAgcm9vdDogc3RyaW5nLFxuICBwcm9qZW5TcGVjaWZpZXI6IHN0cmluZyA9IGRlZmF1bHRQcm9qZW5TcGVjaWZpZXIoKSxcbik6IHZvaWQge1xuICBjb25zdCBtYW5pZmVzdFBhdGggPSBqb2luKHJvb3QsIFwicGFja2FnZS5qc29uXCIpO1xuICBpZiAoIWV4aXN0c1N5bmMobWFuaWZlc3RQYXRoKSkge1xuICAgIHJ1bkJ1bihbXCJpbml0XCIsIFwiLXlcIl0sIHJvb3QpO1xuICAgIG5vcm1hbGl6ZVNlZWRNYW5pZmVzdChtYW5pZmVzdFBhdGgpO1xuICB9XG5cbiAgc2VlZFJlZ2lzdHJ5KHJvb3QpO1xuXG4gIGNvbnN0IGtlcm5lbEFyY2ggPSBleGVjLnNwYXduU3luYyhcInVuYW1lXCIsIFtcIi1tXCJdLCB7XG4gICAgc3RkaW46IFwiaWdub3JlXCIsXG4gICAgc3Rkb3V0OiBcImNhcHR1cmVcIixcbiAgICBzdGRlcnI6IFwiaWdub3JlXCIsXG4gIH0pLnN0ZG91dDtcbiAgbG9nZ2VyLmluZm8oXCJzZWVkaW5nIHRvb2xjaGFpblwiLCB7XG4gICAgbm9kZTogcHJvY2Vzcy52ZXJzaW9uLFxuICAgIGJ1bjogcHJvY2Vzcy52ZXJzaW9ucy5idW4sXG4gICAgcGxhdGZvcm06IHByb2Nlc3MucGxhdGZvcm0sXG4gICAgYXJjaDogcHJvY2Vzcy5hcmNoLFxuICAgIGtlcm5lbEFyY2g6IGtlcm5lbEFyY2ggfHwgXCJ1bmtub3duXCIsXG4gICAgZW5naW5lOiBwcm9qZW5TcGVjaWZpZXIsXG4gIH0pO1xuICBydW5CdW4oW1wiYWRkXCIsIFwiLURcIiwgXCJwcm9qZW5cIiwgXCJ0eXBlc2NyaXB0QF41LjkuM1wiLCBcIkB0eXBlcy9idW5cIiwgcHJvamVuU3BlY2lmaWVyXSwgcm9vdCk7XG59XG5cbi8qKlxuICogUGluIGEgbm9uLWRlZmF1bHQgcmVnaXN0cnkgaW50byB0aGUgbmV3IHJvb3QncyBgLm5wbXJjYC5cbiAqXG4gKiBUaGUgQ0xJIGFscmVhZHkgZm9yY2VzIGAtLXJlZ2lzdHJ5YCBvbnRvIHRoZSBidW4gaW52b2NhdGlvbnMgaXQgbWFrZXMgaXRzZWxmLFxuICogYnV0IGEgYm9vdHN0cmFwcGVkIHdvcmtzcGFjZSBvdXRsaXZlcyB0aGlzIHByb2Nlc3M6IGV2ZXJ5IGxhdGVyIGBidW4gaW5zdGFsbGBcbiAqIHRoZSBkZXZlbG9wZXIgKG9yIHByb2plbidzIHBvc3Qtc3ludGggc3RlcCkgcnVucyBpcyBvbiBpdHMgb3duLiBidW4gaWdub3Jlc1xuICogYG5wbV9jb25maWdfcmVnaXN0cnlgIGZyb20gdGhlIGVudmlyb25tZW50LCBzbyB3aXRob3V0IGEgZmlsZSBvbiBkaXNrIHRob3NlXG4gKiBydW5zIHJldmVydCB0byBgaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvYCAtIHdoaWNoIGlzIGEgaGFyZCBmYWlsdXJlIHdoZXJlXG4gKiB0aGUgY3VzdG9tIHJlZ2lzdHJ5IHdhcyB0aGUgb25seSByZWFjaGFibGUgb25lLlxuICpcbiAqIE9ubHkgd3JpdGVzIGZvciBhbiBhY3R1YWwgb3ZlcnJpZGUsIG5ldmVyIGNyZWF0ZXMgYSBmaWxlIGp1c3QgdG8gbmFtZSBucG1qcyxcbiAqIGFuZCBuZXZlciBvdmVyd3JpdGVzIGFuIGV4aXN0aW5nIGAubnBtcmNgICh0aGUgZGV2ZWxvcGVyJ3Mgb3duIHdpbnMpLlxuICovXG5mdW5jdGlvbiBzZWVkUmVnaXN0cnkocm9vdDogc3RyaW5nKTogdm9pZCB7XG4gIGNvbnN0IHJlZ2lzdHJ5ID0gcHJvamVjdC5ucG1SZWdpc3RyeShudWxsLCB7IG92ZXJyaWRlT25seTogdHJ1ZSwgZW52VmFyczogdHJ1ZSB9KT8udG9TdHJpbmcoKTtcbiAgaWYgKCFyZWdpc3RyeSkgcmV0dXJuO1xuICBjb25zdCBucG1yYyA9IGpvaW4ocm9vdCwgXCIubnBtcmNcIik7XG4gIGlmIChleGlzdHNTeW5jKG5wbXJjKSkgcmV0dXJuO1xuICB3cml0ZUZpbGVTeW5jKG5wbXJjLCBgcmVnaXN0cnk9JHtyZWdpc3RyeX1cXG5gKTtcbn1cblxuLyoqXG4gKiBNYWtlIHdoYXQgYGJ1biBpbml0YCBwcm9kdWNlZCBzYWZlIHRvIHN5bnRoIGFnYWluc3Q6IGZvcmNlIGB0eXBlOiBcIm1vZHVsZVwiYFxuICogKGJ1biBydW5zIGAucHJvamVucmMudHNgIGZpbmUgZWl0aGVyIHdheSwgYnV0IHByb2plbidzIEVTTSBzb3VyY2VzIGFuZCB0aGVcbiAqIGVtaXR0ZWQgY29uZmlnIGFzc3VtZSBtb2R1bGUgdHlwZSkgYW5kIGRyb3AgYW55IGBwYWNrYWdlTWFuYWdlcmAvYGRldkVuZ2luZXNgXG4gKiBmaWVsZCB0aGF0IHdvdWxkIHBpbiBhIGRpZmZlcmVudCBtYW5hZ2VyLiBwcm9qZW4gcmVnZW5lcmF0ZXMgdGhlIHdob2xlIG1hbmlmZXN0XG4gKiBhdCBzeW50aCwgc28gdGhpcyBvbmx5IGhhcyB0byBob2xkIHRoZSBzZWVkIHRvZ2V0aGVyIGxvbmcgZW5vdWdoIHRvIGdldCB0aGVyZS5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplU2VlZE1hbmlmZXN0KG1hbmlmZXN0UGF0aDogc3RyaW5nKTogdm9pZCB7XG4gIHRyeSB7XG4gICAgY29uc3QgbWFuaWZlc3QgPSBqc29uLnBhcnNlUmVjb3JkKHJlYWRGaWxlU3luYyhtYW5pZmVzdFBhdGgsIFwidXRmOFwiKSk7XG4gICAgaWYgKCFtYW5pZmVzdCkgcmV0dXJuO1xuICAgIGRlbGV0ZSBtYW5pZmVzdC5kZXZFbmdpbmVzO1xuICAgIGRlbGV0ZSBtYW5pZmVzdC5wYWNrYWdlTWFuYWdlcjtcbiAgICBtYW5pZmVzdC50eXBlID0gXCJtb2R1bGVcIjtcbiAgICB3cml0ZUZpbGVTeW5jKG1hbmlmZXN0UGF0aCwgYCR7SlNPTi5zdHJpbmdpZnkobWFuaWZlc3QsIG51bGwsIDIpfVxcbmApO1xuICB9IGNhdGNoIHtcbiAgICAvLyBBIG1hbGZvcm1lZC9hYnNlbnQgbWFuaWZlc3QgaGVyZSBqdXN0IG1lYW5zIHRoZSBsYXRlciBgYnVuIGFkZGAgcmVjcmVhdGVzIGl0LlxuICB9XG59XG5cbi8qKlxuICogUnVuIHRoZSBpbml0aWFsIHN5bnRoIGJ5IGV4ZWN1dGluZyBgLnByb2plbnJjLnRzYCBkaXJlY3RseSB3aXRoIGJ1biAod2l0aFxuICogYFBST0pFTl9ESVNBQkxFX1BPU1RgIHNldCksIE5PVCBgcHJvamVuIDx0YXNrPmAuIFVzZSByaWdodCBhZnRlciBzZWVkaW5nIGFcbiAqIGZyZXNoIHdvcmtzcGFjZTogdGhlIHByb2plbiBUQVNLUyAoYHN5bmNgLCBgYmFycmVsc2AsIC4uLikgb25seSBleGlzdCBvbmNlXG4gKiBgLnByb2plbnJjLnRzYCBoYXMgcnVuIG9uY2UsIHNvIGBwcm9qZW4gc3luY2AgY2FuJ3QgYmUgdGhlIGJvb3RzdHJhcHBpbmcgc3RlcC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJ1bkluaXRpYWxTeW50aChyb290OiBzdHJpbmcpOiB2b2lkIHtcbiAgY29uc3QgW2NvbW1hbmQsIC4uLnByZWZpeF0gPSByZXNvbHZlQnVuQXJndigpO1xuICAvLyBidW4gcnVucyB0aGUgYC50c2AgZGlyZWN0bHkuIFRoZSByZWdpc3RyeSByZWFjaGVzIGFueXRoaW5nIG5lc3RlZCB0aHJvdWdoXG4gIC8vIGBjaGlsZEVudmAgYW5kIHRoZSBzZWVkZWQgYC5ucG1yY2AuXG4gIGV4ZWMuc3Bhd25TeW5jKGNvbW1hbmQsIFsuLi5wcmVmaXgsIFwiLnByb2plbnJjLnRzXCJdLCB7XG4gICAgY3dkOiByb290LFxuICAgIGVudjogY2hpbGRFbnYoeyBQUk9KRU5fRElTQUJMRV9QT1NUOiBcInRydWVcIiB9KSxcbiAgICBjaGVjazogdHJ1ZSxcbiAgfSk7XG59XG4iXX0=
package/lib/src/cli.d.ts CHANGED
@@ -1,2 +1,20 @@
1
- /** Parse `argv` with commander and forward remaining args to projen. */
1
+ import { Command } from "commander";
2
+ /**
3
+ * Prepare the workspace at `root`, then run projen (via bun) with `projenArgs`.
4
+ *
5
+ * Three cases, in order:
6
+ * - no `.projenrc.ts` at all -> full bootstrap (scaffold + install + synth),
7
+ * which already runs the initial synth; nothing more to forward.
8
+ * - a `.projenrc.ts` but the engine/toolchain isn't installed (e.g. a freshly
9
+ * copied project whose generated files + manifests are gitignored) -> seed
10
+ * the toolchain, then run the INITIAL synth directly (the projen tasks the
11
+ * args would name, like `sync`, don't exist until `.projenrc.ts` has run
12
+ * once), and install. Don't forward `projenArgs` - the synth is the work.
13
+ * - otherwise (established workspace) -> ensure deps, bring the engine up to
14
+ * this CLI's version, then forward to projen.
15
+ */
16
+ export declare function prepareAndRunProjen(projenArgs: string[], startDir?: string): Promise<void>;
17
+ /** Build the `dbx` commander program (no side effects until parsed). */
18
+ export declare function buildProgram(name?: string): Command;
19
+ /** Parse `argv` (a `process.argv`) and run the matching command. */
2
20
  export declare function runCli(argv: string[]): Promise<void>;
package/lib/src/cli.js CHANGED
@@ -1,12 +1,30 @@
1
1
  /**
2
- * `dbx-tools` commander entry: detect root, bootstrap or install, forward to projen.
2
+ * The single `dbx` (alias `dbx-tools`) commander entry.
3
+ *
4
+ * One bin, three command groups:
5
+ * - `dev` - workspace lifecycle: detect the root, bootstrap or repair, then
6
+ * forward whatever follows to projen. This is the passthrough, and it is an
7
+ * EXPLICIT subcommand rather than the bare root action so a projen task
8
+ * name can never shadow (or be shadowed by) a sibling command.
9
+ * - `model-proxy` - the local OpenAI-compatible Model Serving proxy.
10
+ * - `appkit` - AppKit environment helpers (`appkit env`).
11
+ *
12
+ * The two feature groups stay in their own packages (`@dbx-tools/cli-model-proxy`,
13
+ * `@dbx-tools/cli-appkit-env`) and are `await import()`ed only once their name is
14
+ * matched, so `dbx dev` never loads the Databricks SDK or AppKit. That lazy hop
15
+ * is also why they are mounted as ARG-FORWARDING commands instead of
16
+ * `addCommand()`: building a child program eagerly to register it would defeat
17
+ * the point. Each forwards its own `--help`, so the child prints its real help.
3
18
  *
4
19
  * @module
5
20
  */
21
+ import { basename } from "node:path";
6
22
  import { Command } from "commander";
7
23
  import { bootstrapWorkspace, ensureEngineCurrent, runInitialSynth, seedToolchain, } from "./bootstrap.js";
8
24
  import { ensureWorkspaceReady, runBun, runProjen } from "./bun.js";
9
25
  import { findWorkspaceRoot, needsBootstrap, needsToolchain } from "./root.js";
26
+ /** Commands the bin exposes, and the names help is rendered under. */
27
+ const PROGRAM_NAMES = ["dbx", "dbx-tools"];
10
28
  /**
11
29
  * Prepare the workspace at `root`, then run projen (via bun) with `projenArgs`.
12
30
  *
@@ -21,7 +39,7 @@ import { findWorkspaceRoot, needsBootstrap, needsToolchain } from "./root.js";
21
39
  * - otherwise (established workspace) -> ensure deps, bring the engine up to
22
40
  * this CLI's version, then forward to projen.
23
41
  */
24
- async function prepareAndRunProjen(projenArgs, startDir) {
42
+ export async function prepareAndRunProjen(projenArgs, startDir) {
25
43
  const root = await findWorkspaceRoot(startDir);
26
44
  if (needsBootstrap(root)) {
27
45
  bootstrapWorkspace(root);
@@ -37,16 +55,56 @@ async function prepareAndRunProjen(projenArgs, startDir) {
37
55
  ensureEngineCurrent(root);
38
56
  runProjen(projenArgs, root);
39
57
  }
40
- /** Parse `argv` with commander and forward remaining args to projen. */
41
- export async function runCli(argv) {
42
- const program = new Command()
43
- .name("dbx-tools")
44
- .description("Bootstrap dbx-tools workspaces and forward to projen")
58
+ /**
59
+ * Mount `name` as a command that captures every following token verbatim and
60
+ * hands it to the program `load()` resolves. `helpOption(false)` is what lets
61
+ * `--help` through to the child instead of being answered here, and the child
62
+ * program owns its own flags, so this wrapper never has to restate them.
63
+ */
64
+ function addForwardedCommand(program, name, description, load) {
65
+ program
66
+ .command(name)
67
+ .description(description)
68
+ .argument("[args...]", `arguments forwarded to ${name}`)
45
69
  .allowUnknownOption()
46
70
  .allowExcessArguments()
71
+ .helpOption(false)
72
+ .action(async (args) => {
73
+ const buildProgram = await load();
74
+ await buildProgram(`${program.name()} ${name}`).parseAsync(args, { from: "user" });
75
+ });
76
+ }
77
+ /** Build the `dbx` commander program (no side effects until parsed). */
78
+ export function buildProgram(name = PROGRAM_NAMES[0]) {
79
+ const program = new Command()
80
+ .name(name)
81
+ .description("Databricks developer tools: workspace lifecycle, model proxy, AppKit env")
47
82
  .showHelpAfterError()
48
- .helpOption("-h, --help", "Show dbx-tools help");
49
- program.parse(argv);
50
- await prepareAndRunProjen(program.args);
83
+ .helpOption("-h, --help", `Show ${name} help`);
84
+ program
85
+ .command("dev")
86
+ .description("Bootstrap or repair a dbx-tools workspace, then forward to projen")
87
+ .argument("[projenArgs...]", "projen task and arguments (e.g. sync --watch)")
88
+ .allowUnknownOption()
89
+ .allowExcessArguments()
90
+ .helpOption(false)
91
+ .action(async (projenArgs) => {
92
+ await prepareAndRunProjen(projenArgs);
93
+ });
94
+ addForwardedCommand(program, "model-proxy", "Serve a local OpenAI-compatible proxy in front of Databricks Model Serving", async () => (await import("@dbx-tools/cli-model-proxy/cli")).buildProgram);
95
+ addForwardedCommand(program, "appkit", "AppKit helpers (env: print the environment an AppKit app resolves)", async () => (await import("@dbx-tools/cli-appkit-env/cli")).buildProgram);
96
+ return program;
97
+ }
98
+ /**
99
+ * Program name for help output: whichever bin the user actually typed, so
100
+ * `dbx-tools --help` doesn't document itself as `dbx`. Falls back to `dbx`.
101
+ */
102
+ function programName(argv) {
103
+ const invoked = argv[1] ? basename(argv[1]).replace(/\.(?:[cm]?[jt]s)$/, "") : undefined;
104
+ return PROGRAM_NAMES.find((candidate) => candidate === invoked) ?? PROGRAM_NAMES[0];
105
+ }
106
+ /** Parse `argv` (a `process.argv`) and run the matching command. */
107
+ export async function runCli(argv) {
108
+ await buildProgram(programName(argv)).parseAsync(argv);
51
109
  }
52
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLEVBQ0wsa0JBQWtCLEVBQ2xCLG1CQUFtQixFQUNuQixlQUFlLEVBQ2YsYUFBYSxHQUNkLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDbkUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGNBQWMsRUFBRSxjQUFjLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFOUU7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILEtBQUssVUFBVSxtQkFBbUIsQ0FBQyxVQUFvQixFQUFFLFFBQWlCO0lBQ3hFLE1BQU0sSUFBSSxHQUFHLE1BQU0saUJBQWlCLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDL0MsSUFBSSxjQUFjLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUN6QixrQkFBa0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN6QixPQUFPO0lBQ1QsQ0FBQztJQUNELElBQUksY0FBYyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDekIsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3BCLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN0QixNQUFNLENBQUMsQ0FBQyxTQUFTLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMxQixPQUFPO0lBQ1QsQ0FBQztJQUNELG9CQUFvQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzNCLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFCLFNBQVMsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDOUIsQ0FBQztBQUVELHdFQUF3RTtBQUN4RSxNQUFNLENBQUMsS0FBSyxVQUFVLE1BQU0sQ0FBQyxJQUFjO0lBQ3pDLE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxFQUFFO1NBQzFCLElBQUksQ0FBQyxXQUFXLENBQUM7U0FDakIsV0FBVyxDQUFDLHNEQUFzRCxDQUFDO1NBQ25FLGtCQUFrQixFQUFFO1NBQ3BCLG9CQUFvQixFQUFFO1NBQ3RCLGtCQUFrQixFQUFFO1NBQ3BCLFVBQVUsQ0FBQyxZQUFZLEVBQUUscUJBQXFCLENBQUMsQ0FBQztJQUVuRCxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BCLE1BQU0sbUJBQW1CLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIGBkYngtdG9vbHNgIGNvbW1hbmRlciBlbnRyeTogZGV0ZWN0IHJvb3QsIGJvb3RzdHJhcCBvciBpbnN0YWxsLCBmb3J3YXJkIHRvIHByb2plbi5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cbmltcG9ydCB7IENvbW1hbmQgfSBmcm9tIFwiY29tbWFuZGVyXCI7XG5pbXBvcnQge1xuICBib290c3RyYXBXb3Jrc3BhY2UsXG4gIGVuc3VyZUVuZ2luZUN1cnJlbnQsXG4gIHJ1bkluaXRpYWxTeW50aCxcbiAgc2VlZFRvb2xjaGFpbixcbn0gZnJvbSBcIi4vYm9vdHN0cmFwLnRzXCI7XG5pbXBvcnQgeyBlbnN1cmVXb3Jrc3BhY2VSZWFkeSwgcnVuQnVuLCBydW5Qcm9qZW4gfSBmcm9tIFwiLi9idW4udHNcIjtcbmltcG9ydCB7IGZpbmRXb3Jrc3BhY2VSb290LCBuZWVkc0Jvb3RzdHJhcCwgbmVlZHNUb29sY2hhaW4gfSBmcm9tIFwiLi9yb290LnRzXCI7XG5cbi8qKlxuICogUHJlcGFyZSB0aGUgd29ya3NwYWNlIGF0IGByb290YCwgdGhlbiBydW4gcHJvamVuICh2aWEgYnVuKSB3aXRoIGBwcm9qZW5BcmdzYC5cbiAqXG4gKiBUaHJlZSBjYXNlcywgaW4gb3JkZXI6XG4gKiAgIC0gbm8gYC5wcm9qZW5yYy50c2AgYXQgYWxsIC0+IGZ1bGwgYm9vdHN0cmFwIChzY2FmZm9sZCArIGluc3RhbGwgKyBzeW50aCksXG4gKiAgICAgd2hpY2ggYWxyZWFkeSBydW5zIHRoZSBpbml0aWFsIHN5bnRoOyBub3RoaW5nIG1vcmUgdG8gZm9yd2FyZC5cbiAqICAgLSBhIGAucHJvamVucmMudHNgIGJ1dCB0aGUgZW5naW5lL3Rvb2xjaGFpbiBpc24ndCBpbnN0YWxsZWQgKGUuZy4gYSBmcmVzaGx5XG4gKiAgICAgY29waWVkIHByb2plY3Qgd2hvc2UgZ2VuZXJhdGVkIGZpbGVzICsgbWFuaWZlc3RzIGFyZSBnaXRpZ25vcmVkKSAtPiBzZWVkXG4gKiAgICAgdGhlIHRvb2xjaGFpbiwgdGhlbiBydW4gdGhlIElOSVRJQUwgc3ludGggZGlyZWN0bHkgKHRoZSBwcm9qZW4gdGFza3MgdGhlXG4gKiAgICAgYXJncyB3b3VsZCBuYW1lLCBsaWtlIGBzeW5jYCwgZG9uJ3QgZXhpc3QgdW50aWwgYC5wcm9qZW5yYy50c2AgaGFzIHJ1blxuICogICAgIG9uY2UpLCBhbmQgaW5zdGFsbC4gRG9uJ3QgZm9yd2FyZCBgcHJvamVuQXJnc2AgLSB0aGUgc3ludGggaXMgdGhlIHdvcmsuXG4gKiAgIC0gb3RoZXJ3aXNlIChlc3RhYmxpc2hlZCB3b3Jrc3BhY2UpIC0+IGVuc3VyZSBkZXBzLCBicmluZyB0aGUgZW5naW5lIHVwIHRvXG4gKiAgICAgdGhpcyBDTEkncyB2ZXJzaW9uLCB0aGVuIGZvcndhcmQgdG8gcHJvamVuLlxuICovXG5hc3luYyBmdW5jdGlvbiBwcmVwYXJlQW5kUnVuUHJvamVuKHByb2plbkFyZ3M6IHN0cmluZ1tdLCBzdGFydERpcj86IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCByb290ID0gYXdhaXQgZmluZFdvcmtzcGFjZVJvb3Qoc3RhcnREaXIpO1xuICBpZiAobmVlZHNCb290c3RyYXAocm9vdCkpIHtcbiAgICBib290c3RyYXBXb3Jrc3BhY2Uocm9vdCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChuZWVkc1Rvb2xjaGFpbihyb290KSkge1xuICAgIHNlZWRUb29sY2hhaW4ocm9vdCk7XG4gICAgcnVuSW5pdGlhbFN5bnRoKHJvb3QpO1xuICAgIHJ1bkJ1bihbXCJpbnN0YWxsXCJdLCByb290KTtcbiAgICByZXR1cm47XG4gIH1cbiAgZW5zdXJlV29ya3NwYWNlUmVhZHkocm9vdCk7XG4gIGVuc3VyZUVuZ2luZUN1cnJlbnQocm9vdCk7XG4gIHJ1blByb2plbihwcm9qZW5BcmdzLCByb290KTtcbn1cblxuLyoqIFBhcnNlIGBhcmd2YCB3aXRoIGNvbW1hbmRlciBhbmQgZm9yd2FyZCByZW1haW5pbmcgYXJncyB0byBwcm9qZW4uICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcnVuQ2xpKGFyZ3Y6IHN0cmluZ1tdKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHByb2dyYW0gPSBuZXcgQ29tbWFuZCgpXG4gICAgLm5hbWUoXCJkYngtdG9vbHNcIilcbiAgICAuZGVzY3JpcHRpb24oXCJCb290c3RyYXAgZGJ4LXRvb2xzIHdvcmtzcGFjZXMgYW5kIGZvcndhcmQgdG8gcHJvamVuXCIpXG4gICAgLmFsbG93VW5rbm93bk9wdGlvbigpXG4gICAgLmFsbG93RXhjZXNzQXJndW1lbnRzKClcbiAgICAuc2hvd0hlbHBBZnRlckVycm9yKClcbiAgICAuaGVscE9wdGlvbihcIi1oLCAtLWhlbHBcIiwgXCJTaG93IGRieC10b29scyBoZWxwXCIpO1xuXG4gIHByb2dyYW0ucGFyc2UoYXJndik7XG4gIGF3YWl0IHByZXBhcmVBbmRSdW5Qcm9qZW4ocHJvZ3JhbS5hcmdzKTtcbn1cbiJdfQ==
110
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1CRztBQUNILE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDckMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLEVBQ0wsa0JBQWtCLEVBQ2xCLG1CQUFtQixFQUNuQixlQUFlLEVBQ2YsYUFBYSxHQUNkLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDbkUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGNBQWMsRUFBRSxjQUFjLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFOUUsc0VBQXNFO0FBQ3RFLE1BQU0sYUFBYSxHQUFHLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBVSxDQUFDO0FBRXBEOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLG1CQUFtQixDQUFDLFVBQW9CLEVBQUUsUUFBaUI7SUFDL0UsTUFBTSxJQUFJLEdBQUcsTUFBTSxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUMvQyxJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ3pCLGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pCLE9BQU87SUFDVCxDQUFDO0lBQ0QsSUFBSSxjQUFjLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUN6QixhQUFhLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDcEIsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3RCLE1BQU0sQ0FBQyxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzFCLE9BQU87SUFDVCxDQUFDO0lBQ0Qsb0JBQW9CLENBQUMsSUFBSSxD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QUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGUgc2luZ2xlIGBkYnhgIChhbGlhcyBgZGJ4LXRvb2xzYCkgY29tbWFuZGVyIGVudHJ5LlxuICpcbiAqIE9uZSBiaW4sIHRocmVlIGNvbW1hbmQgZ3JvdXBzOlxuICogICAtIGBkZXZgIC0gd29ya3NwYWNlIGxpZmVjeWNsZTogZGV0ZWN0IHRoZSByb290LCBib290c3RyYXAgb3IgcmVwYWlyLCB0aGVuXG4gKiAgICAgZm9yd2FyZCB3aGF0ZXZlciBmb2xsb3dzIHRvIHByb2plbi4gVGhpcyBpcyB0aGUgcGFzc3Rocm91Z2gsIGFuZCBpdCBpcyBhblxuICogICAgIEVYUExJQ0lUIHN1YmNvbW1hbmQgcmF0aGVyIHRoYW4gdGhlIGJhcmUgcm9vdCBhY3Rpb24gc28gYSBwcm9qZW4gdGFza1xuICogICAgIG5hbWUgY2FuIG5ldmVyIHNoYWRvdyAob3IgYmUgc2hhZG93ZWQgYnkpIGEgc2libGluZyBjb21tYW5kLlxuICogICAtIGBtb2RlbC1wcm94eWAgLSB0aGUgbG9jYWwgT3BlbkFJLWNvbXBhdGlibGUgTW9kZWwgU2VydmluZyBwcm94eS5cbiAqICAgLSBgYXBwa2l0YCAtIEFwcEtpdCBlbnZpcm9ubWVudCBoZWxwZXJzIChgYXBwa2l0IGVudmApLlxuICpcbiAqIFRoZSB0d28gZmVhdHVyZSBncm91cHMgc3RheSBpbiB0aGVpciBvd24gcGFja2FnZXMgKGBAZGJ4LXRvb2xzL2NsaS1tb2RlbC1wcm94eWAsXG4gKiBgQGRieC10b29scy9jbGktYXBwa2l0LWVudmApIGFuZCBhcmUgYGF3YWl0IGltcG9ydCgpYGVkIG9ubHkgb25jZSB0aGVpciBuYW1lIGlzXG4gKiBtYXRjaGVkLCBzbyBgZGJ4IGRldmAgbmV2ZXIgbG9hZHMgdGhlIERhdGFicmlja3MgU0RLIG9yIEFwcEtpdC4gVGhhdCBsYXp5IGhvcFxuICogaXMgYWxzbyB3aHkgdGhleSBhcmUgbW91bnRlZCBhcyBBUkctRk9SV0FSRElORyBjb21tYW5kcyBpbnN0ZWFkIG9mXG4gKiBgYWRkQ29tbWFuZCgpYDogYnVpbGRpbmcgYSBjaGlsZCBwcm9ncmFtIGVhZ2VybHkgdG8gcmVnaXN0ZXIgaXQgd291bGQgZGVmZWF0XG4gKiB0aGUgcG9pbnQuIEVhY2ggZm9yd2FyZHMgaXRzIG93biBgLS1oZWxwYCwgc28gdGhlIGNoaWxkIHByaW50cyBpdHMgcmVhbCBoZWxwLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuaW1wb3J0IHsgYmFzZW5hbWUgfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSBcImNvbW1hbmRlclwiO1xuaW1wb3J0IHtcbiAgYm9vdHN0cmFwV29ya3NwYWNlLFxuICBlbnN1cmVFbmdpbmVDdXJyZW50LFxuICBydW5Jbml0aWFsU3ludGgsXG4gIHNlZWRUb29sY2hhaW4sXG59IGZyb20gXCIuL2Jvb3RzdHJhcC50c1wiO1xuaW1wb3J0IHsgZW5zdXJlV29ya3NwYWNlUmVhZHksIHJ1bkJ1biwgcnVuUHJvamVuIH0gZnJvbSBcIi4vYnVuLnRzXCI7XG5pbXBvcnQgeyBmaW5kV29ya3NwYWNlUm9vdCwgbmVlZHNCb290c3RyYXAsIG5lZWRzVG9vbGNoYWluIH0gZnJvbSBcIi4vcm9vdC50c1wiO1xuXG4vKiogQ29tbWFuZHMgdGhlIGJpbiBleHBvc2VzLCBhbmQgdGhlIG5hbWVzIGhlbHAgaXMgcmVuZGVyZWQgdW5kZXIuICovXG5jb25zdCBQUk9HUkFNX05BTUVTID0gW1wiZGJ4XCIsIFwiZGJ4LXRvb2xzXCJdIGFzIGNvbnN0O1xuXG4vKipcbiAqIFByZXBhcmUgdGhlIHdvcmtzcGFjZSBhdCBgcm9vdGAsIHRoZW4gcnVuIHByb2plbiAodmlhIGJ1bikgd2l0aCBgcHJvamVuQXJnc2AuXG4gKlxuICogVGhyZWUgY2FzZXMsIGluIG9yZGVyOlxuICogICAtIG5vIGAucHJvamVucmMudHNgIGF0IGFsbCAtPiBmdWxsIGJvb3RzdHJhcCAoc2NhZmZvbGQgKyBpbnN0YWxsICsgc3ludGgpLFxuICogICAgIHdoaWNoIGFscmVhZHkgcnVucyB0aGUgaW5pdGlhbCBzeW50aDsgbm90aGluZyBtb3JlIHRvIGZvcndhcmQuXG4gKiAgIC0gYSBgLnByb2plbnJjLnRzYCBidXQgdGhlIGVuZ2luZS90b29sY2hhaW4gaXNuJ3QgaW5zdGFsbGVkIChlLmcuIGEgZnJlc2hseVxuICogICAgIGNvcGllZCBwcm9qZWN0IHdob3NlIGdlbmVyYXRlZCBmaWxlcyArIG1hbmlmZXN0cyBhcmUgZ2l0aWdub3JlZCkgLT4gc2VlZFxuICogICAgIHRoZSB0b29sY2hhaW4sIHRoZW4gcnVuIHRoZSBJTklUSUFMIHN5bnRoIGRpcmVjdGx5ICh0aGUgcHJvamVuIHRhc2tzIHRoZVxuICogICAgIGFyZ3Mgd291bGQgbmFtZSwgbGlrZSBgc3luY2AsIGRvbid0IGV4aXN0IHVudGlsIGAucHJvamVucmMudHNgIGhhcyBydW5cbiAqICAgICBvbmNlKSwgYW5kIGluc3RhbGwuIERvbid0IGZvcndhcmQgYHByb2plbkFyZ3NgIC0gdGhlIHN5bnRoIGlzIHRoZSB3b3JrLlxuICogICAtIG90aGVyd2lzZSAoZXN0YWJsaXNoZWQgd29ya3NwYWNlKSAtPiBlbnN1cmUgZGVwcywgYnJpbmcgdGhlIGVuZ2luZSB1cCB0b1xuICogICAgIHRoaXMgQ0xJJ3MgdmVyc2lvbiwgdGhlbiBmb3J3YXJkIHRvIHByb2plbi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHByZXBhcmVBbmRSdW5Qcm9qZW4ocHJvamVuQXJnczogc3RyaW5nW10sIHN0YXJ0RGlyPzogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHJvb3QgPSBhd2FpdCBmaW5kV29ya3NwYWNlUm9vdChzdGFydERpcik7XG4gIGlmIChuZWVkc0Jvb3RzdHJhcChyb290KSkge1xuICAgIGJvb3RzdHJhcFdvcmtzcGFjZShyb290KTtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKG5lZWRzVG9vbGNoYWluKHJvb3QpKSB7XG4gICAgc2VlZFRvb2xjaGFpbihyb290KTtcbiAgICBydW5Jbml0aWFsU3ludGgocm9vdCk7XG4gICAgcnVuQnVuKFtcImluc3RhbGxcIl0sIHJvb3QpO1xuICAgIHJldHVybjtcbiAgfVxuICBlbnN1cmVXb3Jrc3BhY2VSZWFkeShyb290KTtcbiAgZW5zdXJlRW5naW5lQ3VycmVudChyb290KTtcbiAgcnVuUHJvamVuKHByb2plbkFyZ3MsIHJvb3QpO1xufVxuXG4vKipcbiAqIE1vdW50IGBuYW1lYCBhcyBhIGNvbW1hbmQgdGhhdCBjYXB0dXJlcyBldmVyeSBmb2xsb3dpbmcgdG9rZW4gdmVyYmF0aW0gYW5kXG4gKiBoYW5kcyBpdCB0byB0aGUgcHJvZ3JhbSBgbG9hZCgpYCByZXNvbHZlcy4gYGhlbHBPcHRpb24oZmFsc2UpYCBpcyB3aGF0IGxldHNcbiAqIGAtLWhlbHBgIHRocm91Z2ggdG8gdGhlIGNoaWxkIGluc3RlYWQgb2YgYmVpbmcgYW5zd2VyZWQgaGVyZSwgYW5kIHRoZSBjaGlsZFxuICogcHJvZ3JhbSBvd25zIGl0cyBvd24gZmxhZ3MsIHNvIHRoaXMgd3JhcHBlciBuZXZlciBoYXMgdG8gcmVzdGF0ZSB0aGVtLlxuICovXG5mdW5jdGlvbiBhZGRGb3J3YXJkZWRDb21tYW5kKFxuICBwcm9ncmFtOiBDb21tYW5kLFxuICBuYW1lOiBzdHJpbmcsXG4gIGRlc2NyaXB0aW9uOiBzdHJpbmcsXG4gIGxvYWQ6ICgpID0+IFByb21pc2U8KG5hbWU6IHN0cmluZykgPT4gQ29tbWFuZD4sXG4pOiB2b2lkIHtcbiAgcHJvZ3JhbVxuICAgIC5jb21tYW5kKG5hbWUpXG4gICAgLmRlc2NyaXB0aW9uKGRlc2NyaXB0aW9uKVxuICAgIC5hcmd1bWVudChcIlthcmdzLi4uXVwiLCBgYXJndW1lbnRzIGZvcndhcmRlZCB0byAke25hbWV9YClcbiAgICAuYWxsb3dVbmtub3duT3B0aW9uKClcbiAgICAuYWxsb3dFeGNlc3NBcmd1bWVudHMoKVxuICAgIC5oZWxwT3B0aW9uKGZhbHNlKVxuICAgIC5hY3Rpb24oYXN5bmMgKGFyZ3M6IHN0cmluZ1tdKSA9PiB7XG4gICAgICBjb25zdCBidWlsZFByb2dyYW0gPSBhd2FpdCBsb2FkKCk7XG4gICAgICBhd2FpdCBidWlsZFByb2dyYW0oYCR7cHJvZ3JhbS5uYW1lKCl9ICR7bmFtZX1gKS5wYXJzZUFzeW5jKGFyZ3MsIHsgZnJvbTogXCJ1c2VyXCIgfSk7XG4gICAgfSk7XG59XG5cbi8qKiBCdWlsZCB0aGUgYGRieGAgY29tbWFuZGVyIHByb2dyYW0gKG5vIHNpZGUgZWZmZWN0cyB1bnRpbCBwYXJzZWQpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkUHJvZ3JhbShuYW1lOiBzdHJpbmcgPSBQUk9HUkFNX05BTUVTWzBdKTogQ29tbWFuZCB7XG4gIGNvbnN0IHByb2dyYW0gPSBuZXcgQ29tbWFuZCgpXG4gICAgLm5hbWUobmFtZSlcbiAgICAuZGVzY3JpcHRpb24oXCJEYXRhYnJpY2tzIGRldmVsb3BlciB0b29sczogd29ya3NwYWNlIGxpZmVjeWNsZSwgbW9kZWwgcHJveHksIEFwcEtpdCBlbnZcIilcbiAgICAuc2hvd0hlbHBBZnRlckVycm9yKClcbiAgICAuaGVscE9wdGlvbihcIi1oLCAtLWhlbHBcIiwgYFNob3cgJHtuYW1lfSBoZWxwYCk7XG5cbiAgcHJvZ3JhbVxuICAgIC5jb21tYW5kKFwiZGV2XCIpXG4gICAgLmRlc2NyaXB0aW9uKFwiQm9vdHN0cmFwIG9yIHJlcGFpciBhIGRieC10b29scyB3b3Jrc3BhY2UsIHRoZW4gZm9yd2FyZCB0byBwcm9qZW5cIilcbiAgICAuYXJndW1lbnQoXCJbcHJvamVuQXJncy4uLl1cIiwgXCJwcm9qZW4gdGFzayBhbmQgYXJndW1lbnRzIChlLmcuIHN5bmMgLS13YXRjaClcIilcbiAgICAuYWxsb3dVbmtub3duT3B0aW9uKClcbiAgICAuYWxsb3dFeGNlc3NBcmd1bWVudHMoKVxuICAgIC5oZWxwT3B0aW9uKGZhbHNlKVxuICAgIC5hY3Rpb24oYXN5bmMgKHByb2plbkFyZ3M6IHN0cmluZ1tdKSA9PiB7XG4gICAgICBhd2FpdCBwcmVwYXJlQW5kUnVuUHJvamVuKHByb2plbkFyZ3MpO1xuICAgIH0pO1xuXG4gIGFkZEZvcndhcmRlZENvbW1hbmQoXG4gICAgcHJvZ3JhbSxcbiAgICBcIm1vZGVsLXByb3h5XCIsXG4gICAgXCJTZXJ2ZSBhIGxvY2FsIE9wZW5BSS1jb21wYXRpYmxlIHByb3h5IGluIGZyb250IG9mIERhdGFicmlja3MgTW9kZWwgU2VydmluZ1wiLFxuICAgIGFzeW5jICgpID0+IChhd2FpdCBpbXBvcnQoXCJAZGJ4LXRvb2xzL2NsaS1tb2RlbC1wcm94eS9jbGlcIikpLmJ1aWxkUHJvZ3JhbSxcbiAgKTtcblxuICBhZGRGb3J3YXJkZWRDb21tYW5kKFxuICAgIHByb2dyYW0sXG4gICAgXCJhcHBraXRcIixcbiAgICBcIkFwcEtpdCBoZWxwZXJzIChlbnY6IHByaW50IHRoZSBlbnZpcm9ubWVudCBhbiBBcHBLaXQgYXBwIHJlc29sdmVzKVwiLFxuICAgIGFzeW5jICgpID0+IChhd2FpdCBpbXBvcnQoXCJAZGJ4LXRvb2xzL2NsaS1hcHBraXQtZW52L2NsaVwiKSkuYnVpbGRQcm9ncmFtLFxuICApO1xuXG4gIHJldHVybiBwcm9ncmFtO1xufVxuXG4vKipcbiAqIFByb2dyYW0gbmFtZSBmb3IgaGVscCBvdXRwdXQ6IHdoaWNoZXZlciBiaW4gdGhlIHVzZXIgYWN0dWFsbHkgdHlwZWQsIHNvXG4gKiBgZGJ4LXRvb2xzIC0taGVscGAgZG9lc24ndCBkb2N1bWVudCBpdHNlbGYgYXMgYGRieGAuIEZhbGxzIGJhY2sgdG8gYGRieGAuXG4gKi9cbmZ1bmN0aW9uIHByb2dyYW1OYW1lKGFyZ3Y6IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgY29uc3QgaW52b2tlZCA9IGFyZ3ZbMV0gPyBiYXNlbmFtZShhcmd2WzFdKS5yZXBsYWNlKC9cXC4oPzpbY21dP1tqdF1zKSQvLCBcIlwiKSA6IHVuZGVmaW5lZDtcbiAgcmV0dXJuIFBST0dSQU1fTkFNRVMuZmluZCgoY2FuZGlkYXRlKSA9PiBjYW5kaWRhdGUgPT09IGludm9rZWQpID8/IFBST0dSQU1fTkFNRVNbMF07XG59XG5cbi8qKiBQYXJzZSBgYXJndmAgKGEgYHByb2Nlc3MuYXJndmApIGFuZCBydW4gdGhlIG1hdGNoaW5nIGNvbW1hbmQuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcnVuQ2xpKGFyZ3Y6IHN0cmluZ1tdKTogUHJvbWlzZTx2b2lkPiB7XG4gIGF3YWl0IGJ1aWxkUHJvZ3JhbShwcm9ncmFtTmFtZShhcmd2KSkucGFyc2VBc3luYyhhcmd2KTtcbn1cbiJdfQ==
package/package.json CHANGED
@@ -6,8 +6,8 @@
6
6
  "directory": "packages/js/cli/dbx-tools"
7
7
  },
8
8
  "bin": {
9
- "dbx-tools": "./lib/bin/dbx-tools.js",
10
- "dbxt": "./lib/bin/dbx-tools.js"
9
+ "dbx": "./lib/bin/dbx-tools.js",
10
+ "dbx-tools": "./lib/bin/dbx-tools.js"
11
11
  },
12
12
  "scripts": {
13
13
  "build": "projen build",
@@ -28,8 +28,10 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@clack/prompts": "^1.7.0",
31
- "@dbx-tools/core": "0.6.75",
32
- "@dbx-tools/shared-core": "0.6.75",
31
+ "@dbx-tools/cli-appkit-env": "0.6.77",
32
+ "@dbx-tools/cli-model-proxy": "0.6.77",
33
+ "@dbx-tools/core": "0.6.77",
34
+ "@dbx-tools/shared-core": "0.6.77",
33
35
  "commander": "^15.0.0"
34
36
  },
35
37
  "main": "./lib/index.js",
@@ -39,8 +41,8 @@
39
41
  "main": "./lib/index.js",
40
42
  "types": "./lib/index.d.ts",
41
43
  "bin": {
42
- "dbx-tools": "./lib/bin/dbx-tools.js",
43
- "dbxt": "./lib/bin/dbx-tools.js"
44
+ "dbx": "./lib/bin/dbx-tools.js",
45
+ "dbx-tools": "./lib/bin/dbx-tools.js"
44
46
  },
45
47
  "exports": {
46
48
  ".": {
@@ -66,7 +68,7 @@
66
68
  "./package.json": "./package.json"
67
69
  }
68
70
  },
69
- "version": "0.6.75",
71
+ "version": "0.6.77",
70
72
  "types": "./lib/index.d.ts",
71
73
  "type": "module",
72
74
  "exports": {
package/src/bootstrap.ts CHANGED
@@ -72,12 +72,11 @@ function installedEngineVersion(root: string): string | undefined {
72
72
  /**
73
73
  * Upgrade an established workspace whose installed engine predates this CLI.
74
74
  *
75
- * Bootstrapping pins the engine once, and nothing afterwards revisits it - so a
76
- * workspace created months ago kept resolving its original engine no matter how
77
- * current the CLI invoking it was, and failed inside the OLD engine's code
78
- * (`sync --watch` dying on a `concurrently` that engine never declared). The two
79
- * are released in lockstep, so this CLI's version is exactly the engine it
80
- * expects.
75
+ * Bootstrapping pins the engine once, so without this a workspace created months ago
76
+ * would keep resolving its original engine no matter how current the CLI invoking it
77
+ * is, and would fail inside THAT engine's code (`sync --watch` dying on a
78
+ * `concurrently` it never declared). The two are released in lockstep, so this CLI's
79
+ * version is exactly the engine it expects.
81
80
  *
82
81
  * Only ever moves FORWARD: an engine at or ahead of this CLI is left alone, so
83
82
  * an older CLI cannot downgrade a workspace.
package/src/cli.ts CHANGED
@@ -1,8 +1,24 @@
1
1
  /**
2
- * `dbx-tools` commander entry: detect root, bootstrap or install, forward to projen.
2
+ * The single `dbx` (alias `dbx-tools`) commander entry.
3
+ *
4
+ * One bin, three command groups:
5
+ * - `dev` - workspace lifecycle: detect the root, bootstrap or repair, then
6
+ * forward whatever follows to projen. This is the passthrough, and it is an
7
+ * EXPLICIT subcommand rather than the bare root action so a projen task
8
+ * name can never shadow (or be shadowed by) a sibling command.
9
+ * - `model-proxy` - the local OpenAI-compatible Model Serving proxy.
10
+ * - `appkit` - AppKit environment helpers (`appkit env`).
11
+ *
12
+ * The two feature groups stay in their own packages (`@dbx-tools/cli-model-proxy`,
13
+ * `@dbx-tools/cli-appkit-env`) and are `await import()`ed only once their name is
14
+ * matched, so `dbx dev` never loads the Databricks SDK or AppKit. That lazy hop
15
+ * is also why they are mounted as ARG-FORWARDING commands instead of
16
+ * `addCommand()`: building a child program eagerly to register it would defeat
17
+ * the point. Each forwards its own `--help`, so the child prints its real help.
3
18
  *
4
19
  * @module
5
20
  */
21
+ import { basename } from "node:path";
6
22
  import { Command } from "commander";
7
23
  import {
8
24
  bootstrapWorkspace,
@@ -13,6 +29,9 @@ import {
13
29
  import { ensureWorkspaceReady, runBun, runProjen } from "./bun.ts";
14
30
  import { findWorkspaceRoot, needsBootstrap, needsToolchain } from "./root.ts";
15
31
 
32
+ /** Commands the bin exposes, and the names help is rendered under. */
33
+ const PROGRAM_NAMES = ["dbx", "dbx-tools"] as const;
34
+
16
35
  /**
17
36
  * Prepare the workspace at `root`, then run projen (via bun) with `projenArgs`.
18
37
  *
@@ -27,7 +46,7 @@ import { findWorkspaceRoot, needsBootstrap, needsToolchain } from "./root.ts";
27
46
  * - otherwise (established workspace) -> ensure deps, bring the engine up to
28
47
  * this CLI's version, then forward to projen.
29
48
  */
30
- async function prepareAndRunProjen(projenArgs: string[], startDir?: string): Promise<void> {
49
+ export async function prepareAndRunProjen(projenArgs: string[], startDir?: string): Promise<void> {
31
50
  const root = await findWorkspaceRoot(startDir);
32
51
  if (needsBootstrap(root)) {
33
52
  bootstrapWorkspace(root);
@@ -44,16 +63,77 @@ async function prepareAndRunProjen(projenArgs: string[], startDir?: string): Pro
44
63
  runProjen(projenArgs, root);
45
64
  }
46
65
 
47
- /** Parse `argv` with commander and forward remaining args to projen. */
48
- export async function runCli(argv: string[]): Promise<void> {
49
- const program = new Command()
50
- .name("dbx-tools")
51
- .description("Bootstrap dbx-tools workspaces and forward to projen")
66
+ /**
67
+ * Mount `name` as a command that captures every following token verbatim and
68
+ * hands it to the program `load()` resolves. `helpOption(false)` is what lets
69
+ * `--help` through to the child instead of being answered here, and the child
70
+ * program owns its own flags, so this wrapper never has to restate them.
71
+ */
72
+ function addForwardedCommand(
73
+ program: Command,
74
+ name: string,
75
+ description: string,
76
+ load: () => Promise<(name: string) => Command>,
77
+ ): void {
78
+ program
79
+ .command(name)
80
+ .description(description)
81
+ .argument("[args...]", `arguments forwarded to ${name}`)
52
82
  .allowUnknownOption()
53
83
  .allowExcessArguments()
84
+ .helpOption(false)
85
+ .action(async (args: string[]) => {
86
+ const buildProgram = await load();
87
+ await buildProgram(`${program.name()} ${name}`).parseAsync(args, { from: "user" });
88
+ });
89
+ }
90
+
91
+ /** Build the `dbx` commander program (no side effects until parsed). */
92
+ export function buildProgram(name: string = PROGRAM_NAMES[0]): Command {
93
+ const program = new Command()
94
+ .name(name)
95
+ .description("Databricks developer tools: workspace lifecycle, model proxy, AppKit env")
54
96
  .showHelpAfterError()
55
- .helpOption("-h, --help", "Show dbx-tools help");
97
+ .helpOption("-h, --help", `Show ${name} help`);
98
+
99
+ program
100
+ .command("dev")
101
+ .description("Bootstrap or repair a dbx-tools workspace, then forward to projen")
102
+ .argument("[projenArgs...]", "projen task and arguments (e.g. sync --watch)")
103
+ .allowUnknownOption()
104
+ .allowExcessArguments()
105
+ .helpOption(false)
106
+ .action(async (projenArgs: string[]) => {
107
+ await prepareAndRunProjen(projenArgs);
108
+ });
109
+
110
+ addForwardedCommand(
111
+ program,
112
+ "model-proxy",
113
+ "Serve a local OpenAI-compatible proxy in front of Databricks Model Serving",
114
+ async () => (await import("@dbx-tools/cli-model-proxy/cli")).buildProgram,
115
+ );
116
+
117
+ addForwardedCommand(
118
+ program,
119
+ "appkit",
120
+ "AppKit helpers (env: print the environment an AppKit app resolves)",
121
+ async () => (await import("@dbx-tools/cli-appkit-env/cli")).buildProgram,
122
+ );
123
+
124
+ return program;
125
+ }
56
126
 
57
- program.parse(argv);
58
- await prepareAndRunProjen(program.args);
127
+ /**
128
+ * Program name for help output: whichever bin the user actually typed, so
129
+ * `dbx-tools --help` doesn't document itself as `dbx`. Falls back to `dbx`.
130
+ */
131
+ function programName(argv: string[]): string {
132
+ const invoked = argv[1] ? basename(argv[1]).replace(/\.(?:[cm]?[jt]s)$/, "") : undefined;
133
+ return PROGRAM_NAMES.find((candidate) => candidate === invoked) ?? PROGRAM_NAMES[0];
134
+ }
135
+
136
+ /** Parse `argv` (a `process.argv`) and run the matching command. */
137
+ export async function runCli(argv: string[]): Promise<void> {
138
+ await buildProgram(programName(argv)).parseAsync(argv);
59
139
  }