@revenexx/cli 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -19
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.mjs +20688 -9347
- package/dist/index.cjs +4 -64
- package/dist/index.js +4 -64
- package/dist/lib/client.d.ts +0 -46
- package/dist/lib/client.d.ts.map +1 -1
- package/dist/lib/commands/generators/base.d.ts +1 -1
- package/dist/lib/commands/generic.d.ts.map +1 -1
- package/dist/lib/commands/repl.d.ts.map +1 -1
- package/dist/lib/commands/services/carts-io.d.ts +3 -0
- package/dist/lib/commands/services/carts-io.d.ts.map +1 -0
- package/dist/lib/commands/services/carts-items.d.ts +3 -0
- package/dist/lib/commands/services/carts-items.d.ts.map +1 -0
- package/dist/lib/commands/services/customers-contacts.d.ts +3 -0
- package/dist/lib/commands/services/customers-contacts.d.ts.map +1 -0
- package/dist/lib/commands/services/customers-organizations.d.ts +3 -0
- package/dist/lib/commands/services/customers-organizations.d.ts.map +1 -0
- package/dist/lib/commands/services/customers-roles.d.ts +3 -0
- package/dist/lib/commands/services/customers-roles.d.ts.map +1 -0
- package/dist/lib/commands/services/customers-segments.d.ts +3 -0
- package/dist/lib/commands/services/customers-segments.d.ts.map +1 -0
- package/dist/lib/commands/services/customers-value-lists.d.ts +3 -0
- package/dist/lib/commands/services/customers-value-lists.d.ts.map +1 -0
- package/dist/lib/commands/services/customers.d.ts.map +1 -1
- package/dist/lib/commands/services/forms.d.ts.map +1 -1
- package/dist/lib/commands/services/health.d.ts +3 -0
- package/dist/lib/commands/services/health.d.ts.map +1 -0
- package/dist/lib/commands/services/inventories-locations.d.ts +3 -0
- package/dist/lib/commands/services/inventories-locations.d.ts.map +1 -0
- package/dist/lib/commands/services/inventories-reservations.d.ts +3 -0
- package/dist/lib/commands/services/inventories-reservations.d.ts.map +1 -0
- package/dist/lib/commands/services/inventories-stock.d.ts +3 -0
- package/dist/lib/commands/services/inventories-stock.d.ts.map +1 -0
- package/dist/lib/commands/services/io.d.ts.map +1 -1
- package/dist/lib/commands/services/orders.d.ts.map +1 -1
- package/dist/lib/commands/services/pages-collaboration.d.ts +3 -0
- package/dist/lib/commands/services/pages-collaboration.d.ts.map +1 -0
- package/dist/lib/commands/services/pages-delivery.d.ts +3 -0
- package/dist/lib/commands/services/pages-delivery.d.ts.map +1 -0
- package/dist/lib/commands/services/pages-editor.d.ts +3 -0
- package/dist/lib/commands/services/pages-editor.d.ts.map +1 -0
- package/dist/lib/commands/services/payments-ledger.d.ts +3 -0
- package/dist/lib/commands/services/payments-ledger.d.ts.map +1 -0
- package/dist/lib/commands/services/payments-methods.d.ts +3 -0
- package/dist/lib/commands/services/payments-methods.d.ts.map +1 -0
- package/dist/lib/commands/services/payments-providers.d.ts +3 -0
- package/dist/lib/commands/services/payments-providers.d.ts.map +1 -0
- package/dist/lib/commands/services/products-assets.d.ts +3 -0
- package/dist/lib/commands/services/products-assets.d.ts.map +1 -0
- package/dist/lib/commands/services/products-categories.d.ts +3 -0
- package/dist/lib/commands/services/products-categories.d.ts.map +1 -0
- package/dist/lib/commands/services/products-data-model.d.ts +3 -0
- package/dist/lib/commands/services/products-data-model.d.ts.map +1 -0
- package/dist/lib/commands/services/products-references.d.ts +3 -0
- package/dist/lib/commands/services/products-references.d.ts.map +1 -0
- package/dist/lib/commands/services/shipping-carriers.d.ts +3 -0
- package/dist/lib/commands/services/shipping-carriers.d.ts.map +1 -0
- package/dist/lib/commands/services/shipping-methods.d.ts +3 -0
- package/dist/lib/commands/services/shipping-methods.d.ts.map +1 -0
- package/dist/lib/commands/services/shipping-value-lists.d.ts +3 -0
- package/dist/lib/commands/services/shipping-value-lists.d.ts.map +1 -0
- package/dist/lib/commands/tui.d.ts.map +1 -1
- package/dist/lib/commands/update.d.ts +22 -0
- package/dist/lib/commands/update.d.ts.map +1 -1
- package/dist/lib/commands/watch.d.ts +23 -0
- package/dist/lib/commands/watch.d.ts.map +1 -0
- package/dist/lib/constants.d.ts +3 -1
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/parser.d.ts.map +1 -1
- package/dist/lib/sdks.d.ts.map +1 -1
- package/dist/lib/tui/app.d.ts.map +1 -1
- package/dist/lib/tui/command-tree.d.ts +3 -2
- package/dist/lib/tui/command-tree.d.ts.map +1 -1
- package/dist/lib/tui/executor.d.ts +0 -9
- package/dist/lib/tui/executor.d.ts.map +1 -1
- package/dist/lib/tui/slash-commands.d.ts +62 -0
- package/dist/lib/tui/slash-commands.d.ts.map +1 -0
- package/dist/lib/tui/watch-create.d.ts +17 -0
- package/dist/lib/tui/watch-create.d.ts.map +1 -0
- package/dist/lib/tui/watch-pane.d.ts +7 -0
- package/dist/lib/tui/watch-pane.d.ts.map +1 -0
- package/dist/lib/type-generation/languages/csharp.d.ts.map +1 -1
- package/dist/lib/type-generation/languages/dart.d.ts.map +1 -1
- package/dist/lib/type-generation/languages/java.d.ts.map +1 -1
- package/dist/lib/type-generation/languages/javascript.d.ts.map +1 -1
- package/dist/lib/type-generation/languages/kotlin.d.ts.map +1 -1
- package/dist/lib/type-generation/languages/php.d.ts.map +1 -1
- package/dist/lib/type-generation/languages/swift.d.ts.map +1 -1
- package/dist/lib/type-generation/languages/typescript.d.ts.map +1 -1
- package/dist/lib/watch/condition.d.ts +51 -0
- package/dist/lib/watch/condition.d.ts.map +1 -0
- package/dist/lib/watch/duration.d.ts +28 -0
- package/dist/lib/watch/duration.d.ts.map +1 -0
- package/dist/lib/watch/field-path.d.ts +54 -0
- package/dist/lib/watch/field-path.d.ts.map +1 -0
- package/dist/lib/watch/notify.d.ts +49 -0
- package/dist/lib/watch/notify.d.ts.map +1 -0
- package/dist/lib/watch/registry.d.ts +25 -0
- package/dist/lib/watch/registry.d.ts.map +1 -0
- package/dist/lib/watch/run-queue.d.ts +55 -0
- package/dist/lib/watch/run-queue.d.ts.map +1 -0
- package/dist/lib/watch/scheduler.d.ts +78 -0
- package/dist/lib/watch/scheduler.d.ts.map +1 -0
- package/dist/lib/watch/session.d.ts +17 -0
- package/dist/lib/watch/session.d.ts.map +1 -0
- package/dist/lib/watch/types.d.ts +144 -0
- package/dist/lib/watch/types.d.ts.map +1 -0
- package/dist/lib/watch/use-watchers.d.ts +25 -0
- package/dist/lib/watch/use-watchers.d.ts.map +1 -0
- package/dist/tests/executor.test.d.ts +2 -0
- package/dist/tests/executor.test.d.ts.map +1 -0
- package/dist/tests/watch-condition.test.d.ts +2 -0
- package/dist/tests/watch-condition.test.d.ts.map +1 -0
- package/dist/tests/watch-field-path.test.d.ts +2 -0
- package/dist/tests/watch-field-path.test.d.ts.map +1 -0
- package/dist/tests/watch-notify.test.d.ts +2 -0
- package/dist/tests/watch-notify.test.d.ts.map +1 -0
- package/dist/tests/watch-registry.test.d.ts +2 -0
- package/dist/tests/watch-registry.test.d.ts.map +1 -0
- package/dist/tests/watch-run-queue.test.d.ts +2 -0
- package/dist/tests/watch-run-queue.test.d.ts.map +1 -0
- package/dist/tests/watch-scheduler.test.d.ts +2 -0
- package/dist/tests/watch-scheduler.test.d.ts.map +1 -0
- package/package.json +1 -1
- package/dist/lib/commands/services/greetings.d.ts +0 -3
- package/dist/lib/commands/services/greetings.d.ts.map +0 -1
- package/dist/lib/commands/services/inventories.d.ts +0 -3
- package/dist/lib/commands/services/inventories.d.ts.map +0 -1
- package/dist/lib/commands/services/payments.d.ts +0 -3
- package/dist/lib/commands/services/payments.d.ts.map +0 -1
- package/dist/lib/commands/services/shipping.d.ts +0 -3
- package/dist/lib/commands/services/shipping.d.ts.map +0 -1
- package/dist/lib/commands/services/tokens.d.ts +0 -3
- package/dist/lib/commands/services/tokens.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ Revenexx command-line interface for managing your platform.
|
|
|
13
13
|
|
|
14
14
|
## Installation
|
|
15
15
|
|
|
16
|
-
The Revenexx CLI is a
|
|
16
|
+
The Revenexx CLI is a command line tool to help you interact with the Revenexx API. Install it from [npm](https://www.npmjs.com/package/@revenexx/cli) or, on macOS and Linux, with [Homebrew](https://brew.sh) — the Homebrew formula installs a self-contained binary, so no Node.js is needed. Single-file binaries for every supported platform are also attached to each [GitHub release](https://github.com/revenexx-sdks/cli/releases/latest) for manual download.
|
|
17
17
|
|
|
18
18
|
### Install using NPM
|
|
19
19
|
---
|
|
@@ -28,41 +28,49 @@ Once the installation is complete, you can verify the install using
|
|
|
28
28
|
|
|
29
29
|
```sh
|
|
30
30
|
$ revenexx -v
|
|
31
|
-
0.
|
|
31
|
+
0.3.0
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
###
|
|
34
|
+
### MacOS / Linux via [Homebrew](https://brew.sh)
|
|
35
35
|
---
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
The CLI ships its own tap, [`revenexx-sdks/homebrew-cli`](https://github.com/revenexx-sdks/homebrew-cli) (Homebrew strips the `homebrew-` prefix, so it is addressed as `revenexx-sdks/cli`). No Node.js needed — the formula installs the prebuilt binary for your platform:
|
|
38
38
|
|
|
39
|
-
### Linux / MacOS Terminal
|
|
40
39
|
```bash
|
|
41
|
-
$
|
|
40
|
+
$ brew install revenexx-sdks/cli/revenexx
|
|
42
41
|
```
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
> **Coming soon** — Homebrew support is not yet available.
|
|
43
|
+
Or add the tap once and refer to the formula by name afterwards:
|
|
47
44
|
|
|
48
45
|
```bash
|
|
46
|
+
$ brew tap revenexx-sdks/cli
|
|
49
47
|
$ brew install revenexx
|
|
50
48
|
```
|
|
51
49
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
$
|
|
50
|
+
Upgrading to a newer release:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
$ brew update && brew upgrade revenexx-sdks/cli/revenexx
|
|
56
54
|
```
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
|
|
56
|
+
`revenexx update` detects a Homebrew install and runs those two commands for you.
|
|
57
|
+
|
|
58
|
+
### Manual download
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
Every release attaches a single-file binary per platform — `revenexx-darwin-arm64`, `revenexx-linux-x64`, `revenexx-win-x64.exe` and so on. Grab the one for your platform from the [latest release](https://github.com/revenexx-sdks/cli/releases/latest), make it executable, and put it on your `PATH`:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
$ chmod +x revenexx-darwin-arm64
|
|
65
|
+
$ mv revenexx-darwin-arm64 /usr/local/bin/revenexx
|
|
60
66
|
```
|
|
61
67
|
|
|
68
|
+
On Windows, use `npm` — or download the `.exe` from the same release page.
|
|
69
|
+
|
|
62
70
|
Once the installation completes, you can verify your install using
|
|
63
71
|
```
|
|
64
72
|
$ revenexx -v
|
|
65
|
-
0.
|
|
73
|
+
0.3.0
|
|
66
74
|
```
|
|
67
75
|
|
|
68
76
|
## Getting Started
|
|
@@ -124,9 +132,10 @@ $ revenexx p ls # built-in aliases: same as `products list`
|
|
|
124
132
|
$ revenexx alias set deploy "apps create-deployment --activate true"
|
|
125
133
|
$ revenexx repl # interactive shell — many commands, one session
|
|
126
134
|
$ revenexx tui # full-screen app — browse commands, forms, results
|
|
135
|
+
$ revenexx watch add --until 'status terminal' -- imports get --id imp_42
|
|
127
136
|
```
|
|
128
137
|
|
|
129
|
-
A **production safety banner** is printed before most commands showing which tenant/endpoint you're hitting (prominent and red for production). Silence it with `-q`/`--quiet`. See [Command aliases](../README.md#command-aliases), [Production safety banner](../README.md#production-safety-banner), [`status`](../README.md#status), [Interactive shell (`repl`)](../README.md#interactive-shell-repl)
|
|
138
|
+
A **production safety banner** is printed before most commands showing which tenant/endpoint you're hitting (prominent and red for production). Silence it with `-q`/`--quiet`. See [Command aliases](../README.md#command-aliases), [Production safety banner](../README.md#production-safety-banner), [`status`](../README.md#status), [Interactive shell (`repl`)](../README.md#interactive-shell-repl), [Full-screen app (`tui`)](../README.md#full-screen-app-tui) and [Background watchers (`watch`)](../README.md#background-watchers-watch) in the README.
|
|
130
139
|
|
|
131
140
|
> ### Note
|
|
132
141
|
> By default, requests to domains with self-signed SSL certificates (or no certificates) are rejected. If you trust the host, you can bypass certificate validation using
|
|
@@ -144,6 +153,8 @@ The CLI has one command tree reachable three ways — every service command, plu
|
|
|
144
153
|
| **Interactive shell** ([`repl`](#interactive-shell-repl)) | `revenexx repl` | Fire several commands in a row without re-typing `revenexx`. |
|
|
145
154
|
| **Direct / one-shot** | `revenexx products list --json …` | Scripting, CI, pipes — flag-driven and non-interactive. |
|
|
146
155
|
|
|
156
|
+
Any of the interactive modes can also leave a [background watcher](#background-watchers-watch) polling a resource while you carry on.
|
|
157
|
+
|
|
147
158
|
Running `revenexx` with no arguments on an interactive terminal launches the **full-screen app**. A partial or named invocation (`revenexx p`, `revenexx products`) still opens the guided command picker and resolves to a single one-shot command. Anything non-interactive — a pipe, CI, `--json`, or `--help` — prints help and never opens an interactive surface, so scripts stay byte-stable.
|
|
148
159
|
|
|
149
160
|
**Opting out of the TUI default:** set `REVENEXX_NO_TUI=1` (any value other than `0`/`false`) to make a bare `revenexx` fall back to the guided picker. For a per-project default, add a `defaultMode:` key to `.revenexx.yaml` — `tui` (default), `guided` (the picker), or `help` (print usage). Explicit subcommands (`repl`, `tui`, any service command) always win regardless of this setting.
|
|
@@ -338,6 +349,7 @@ revenexx> exit
|
|
|
338
349
|
|
|
339
350
|
- **Tab** completes top-level command names, then a service's subcommands.
|
|
340
351
|
- `help` (or `?`) prints the command list; `exit` (or `quit`, `q`, Ctrl-D) leaves the shell.
|
|
352
|
+
- `watch add …` leaves a [background watcher](#background-watchers-watch) polling while you keep typing; it prints a line and rings the bell when it finishes.
|
|
341
353
|
- Missing required options **prompt interactively** just like they do outside the shell (search/select), so `p get` will ask for the product id. Ctrl-C cancels the current line without leaving the shell.
|
|
342
354
|
- The [production safety banner](#production-safety-banner) is shown before **every** command in the session (prominent and red for production) — the safeguard matters most in a rapid-fire shell. Launch with `revenexx --quiet repl` to silence it for the session.
|
|
343
355
|
|
|
@@ -358,8 +370,60 @@ $ revenexx tui # explicit, always works
|
|
|
358
370
|
- **Forms:** `Tab`/`Shift+Tab` move between fields, `←`/`→`/`Space` cycle toggles and choices, `Enter` advances or runs, `^r` runs from any field. Values are validated on submit; secrets (password/token/api-key) are masked. Resource-id fields open the matching list as a **filterable table** — type to narrow it (server-side when the endpoint supports `search`, otherwise across the loaded rows), `↑`/`↓` to move, `Enter` to pick the highlighted record's id.
|
|
359
371
|
- **JSON body fields:** an `object` parameter (e.g. `--data`) opens a full-screen **key/value editor** — `Enter` adds a field (or appends an array item), `Tab` switches between the key and value cell, `^d` deletes the focused field, `^s` saves it back to the form. Values are entered as JSON (`"text"`, `42`, `true`) and validated live, so the request body round-trips exactly. **Nested JSON** is edited in place: a value that is an object or array shows as `{ n fields }` / `[ n items ]`, and `→` drills into it one level deeper (breadcrumb `data › meta › [0]`, any depth); `Esc` goes back up a level (and cancels at the top). Type `{}` or `[]` into a value to start a nested container.
|
|
360
372
|
- **Results:** table with `↑`/`↓` rows, `Enter` for row detail, `/` to filter the loaded rows (type to narrow across all columns, `Esc` clears), `←`/`→` to scroll columns, `n`/`p` to page, `o` to cycle output format (`table`/`json`/`jsonl`/`csv`), `y` to copy (`Y` copies the whole output), `c` to open the matching `create` form, `u` to open the matching `update` pre-filled, `d` to `delete` the record (behind the confirm modal), `e` to edit parameters. `u`/`d` act on the row under the cursor in a list, or on the single record from a `get`; `c` needs no row, so it works from an empty list too.
|
|
373
|
+
- **Watchlist:** type `/watch` to set up a background watcher and `/watchlist` to see them — see [Background watchers](#background-watchers-watch).
|
|
361
374
|
- The header carries a persistent, filled yellow `▲ PRODUCTION` chip (the same [production safety](#production-safety-banner) signal) for the whole session.
|
|
362
|
-
- Not browsable in the TUI (still available as one-shot commands): `tui`, `repl`, `update`, `generate`, `types`, `completion`.
|
|
375
|
+
- Not browsable in the TUI (still available as one-shot commands): `tui`, `repl`, `watch`, `update`, `generate`, `types`, `completion`.
|
|
376
|
+
|
|
377
|
+
## Background watchers (`watch`)
|
|
378
|
+
|
|
379
|
+
A long-running operation — an import, a deployment, an order going through — usually ends with re-running the same `get` by hand until the status moves. A **watcher** does that for you: it polls one get-by-id command in the background and tells you when a field reaches the condition you named.
|
|
380
|
+
|
|
381
|
+
```sh
|
|
382
|
+
# Block until the import finishes, then carry on (exit code says how it ended)
|
|
383
|
+
$ revenexx watch add --until 'status terminal' -- imports get --id imp_42 \
|
|
384
|
+
&& revenexx products list
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
Inside `repl` or `tui` the same command registers a watcher and hands the prompt straight back, so you keep working while it polls:
|
|
388
|
+
|
|
389
|
+
```sh
|
|
390
|
+
revenexx> watch add --until 'status terminal' --every 5s -- imports get --id imp_42
|
|
391
|
+
✓ watcher #1 · imports get imp_42 · status terminal · every 5s
|
|
392
|
+
revenexx> products list # keep working
|
|
393
|
+
…
|
|
394
|
+
⏱ watcher #1 satisfied · status: processing → done · 42s ← prints itself, and rings the bell
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
**Sub-commands**
|
|
398
|
+
|
|
399
|
+
| Command | Does |
|
|
400
|
+
|---|---|
|
|
401
|
+
| `watch add --until <expr> -- <get command>` | Start a watcher. Outside a session it blocks until the watcher settles. |
|
|
402
|
+
| `watch list` | Show this session's watchers with live state (`--json` for the full records). |
|
|
403
|
+
| `watch rm <id>` / `watch rm --all` | Cancel one, or every active one. |
|
|
404
|
+
|
|
405
|
+
**Conditions** — `--until` takes an optional field path followed by one of:
|
|
406
|
+
|
|
407
|
+
| Condition | Fires when the field… |
|
|
408
|
+
|---|---|
|
|
409
|
+
| `terminal` | stops moving — `done`, `ready`, `failed`, `cancelled`, … (both the wins **and** the failures, so a failed job stops the watcher instead of running out the clock) |
|
|
410
|
+
| `changed` | differs from its value on the first poll |
|
|
411
|
+
| `equals <value>` | matches exactly, case-insensitively (`equals 200` matches the number `200`) |
|
|
412
|
+
| `matches <regex>` | matches a regular expression (`/pattern/flags` also accepted) |
|
|
413
|
+
| `truthy` | becomes non-empty — `[]`, `{}`, `""`, `"false"` and `"0"` all count as empty |
|
|
414
|
+
|
|
415
|
+
Override the terminal set per watcher with `terminal(ready,failed)`, or process-wide with `REVENEXX_WATCH_TERMINAL_STATES`.
|
|
416
|
+
|
|
417
|
+
**Field paths** are dot paths into the response: `status`, `items.0.state`, `page.total`, `items.length`. There is no implicit descent into a list envelope — a page has as many statuses as it has rows, so say which one you mean. A field that isn't there yet is *not* an error; the watcher keeps polling until it appears or the budget runs out.
|
|
418
|
+
|
|
419
|
+
**Flags:** `--every` (interval, default 5s, floor 2s), `--for` (give up after, default 5m), `--field` (if you'd rather keep the path out of `--until`), `--wait-for-create` (treat `404` as "not yet" rather than fatal).
|
|
420
|
+
|
|
421
|
+
**Exit codes** for the blocking form, extending [the CLI's table](#machine-readable-errors--exit-codes): `0` satisfied, `7` timed out, `130` cancelled, otherwise the failing poll's own code (so `4` still means auth and `8` still means rate-limited).
|
|
422
|
+
|
|
423
|
+
- Watchers are **session-scoped and in-memory**: they live for the length of the `repl`/`tui` session (or the blocking command) and are torn down on exit. Nothing survives the process.
|
|
424
|
+
- Polling goes through the same transport as everything else, so the request timeout, retry/backoff and `429 Retry-After` handling all apply. The interval has a floor and ±15% jitter, and at most 8 watchers run at once.
|
|
425
|
+
- A poll already in flight cannot be cut short (the gateway client has no cancellation), so a watcher can overrun `--for` by up to one poll.
|
|
426
|
+
- Needs an interactive terminal. In a script, write the loop yourself around `<get command> --json` — that keeps piped output byte-identical.
|
|
363
427
|
|
|
364
428
|
## Global Configuration
|
|
365
429
|
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AAEA,OAAO,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AAEA,OAAO,eAAe,CAAC;AAgFvB,OAAO,gCAAgC,CAAC"}
|