@revturbine/cli 0.16.0 → 0.16.2

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.
Files changed (3) hide show
  1. package/README.md +10 -10
  2. package/dist/cli.js +31 -23
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # revturbine-cli (`revturbine`)
2
2
 
3
- Validate [RevTurbine](https://revturbine.com) **Config Files** and ship them to
3
+ Validate [RevTurbine](https://revturbine.com) **Playbooks** and ship them to
4
4
  a RevTurbine instance through the playbook-version lifecycle (draft → Release) —
5
5
  from the terminal, the same operations the in-app studios perform.
6
6
 
@@ -39,11 +39,11 @@ Requires Node ≥ 22.13. Source builds use the npm 11.18.0 version declared in
39
39
  ```bash
40
40
  revturbine signup # create an account (email + password + emailed code)
41
41
  revturbine login # authorize this machine (device flow)
42
- revturbine download --live --save ./config.json
43
- # …edit ./config.json…
44
- revturbine validate ./config.json # schema-validate locally (no network)
45
- revturbine diff ./config.json --live # what would change (no writes)
46
- revturbine launch ./config.json # upload, gate, and go live
42
+ revturbine download --live --save ./revturbine.playbook.json
43
+ # …edit ./revturbine.playbook.json…
44
+ revturbine validate ./revturbine.playbook.json # schema-validate locally (no network)
45
+ revturbine diff ./revturbine.playbook.json --live # what would change (no writes)
46
+ revturbine launch ./revturbine.playbook.json # upload, gate, and go live
47
47
  ```
48
48
 
49
49
  `revturbine <command> --help` documents every flag.
@@ -54,7 +54,7 @@ Commands that read a config name the version explicitly — there is no default:
54
54
 
55
55
  | Selector | Meaning |
56
56
  |---|---|
57
- | `<file>` / `--file <path>` | a local Config File |
57
+ | `<file>` / `--file <path>` | a local Playbook file |
58
58
  | `--draft` | the tenant's single open draft (resolved automatically) |
59
59
  | `--live` | the current live Release |
60
60
  | `--release <id>` | a specific playbook version / Release |
@@ -71,9 +71,9 @@ Commands that read a config name the version explicitly — there is no default:
71
71
  | `docs` | Print the canonical documentation URL. |
72
72
  | `download` | Fetch a config version (`--live` / `--draft` / `--release <id>`); `--save`, `--format flatbuffer`. |
73
73
  | `validate` | Offline schema validation of a `<file>`, or the full server catalog against the open draft (`--draft`). |
74
- | `diff` | Compare any two versions, first → second (dry-run, no writes). |
74
+ | `diff` | Compare any two versions (dry-run, no writes). A file vs `--draft`/`--live`/`--release` previews the launch — the server side is the base, so `+`/`-` read as created/pruned on launch. |
75
75
  | `show <kind>` | Summary tables: `plans` · `entitlements` · `segments` · `placements` · `trials` for any version. |
76
- | `upload` | Stage a Config File as the open draft. |
76
+ | `upload` | Stage a Playbook file as the open draft. |
77
77
  | `launch` | Take a config live: validate (launch gate) → submit → approve → deploy. `launch <file>` or `launch --draft`. |
78
78
  | `discard` | Archive the open draft (`--yes`). |
79
79
  | `restore` | Stage a draft that restores a past release from its frozen snapshot; `--launch` takes it live. Halts if a draft is open. |
@@ -81,7 +81,7 @@ Commands that read a config name the version explicitly — there is no default:
81
81
  | `history` | The Release Version Log, newest first. |
82
82
  | `preview` | The open draft's staged changes. |
83
83
  | `evaluate` | Run the live config's placement/entitlement decisions for a user context. |
84
- | `generate types` | Generate a TypeScript module of entitlement handles (namespaced by entitlement type) from any config version, for type-safe `can()`/`gate()` call sites. `--out <path>` writes the file; the generated header records the exact command to regenerate it. `--json` for the raw handle map. |
84
+ | `generate types` | Generate a TypeScript module of typed Playbook handles from any config version — `Entitlements` (namespaced by type, with the `EntitlementHandle` union for type-safe `can()`/`gate()`/`checkEntitlement()` call sites), plus `Plans`, `Segments`, `SurfaceTemplates`, and `UiPathActionTypes`. Const objects + literal-union types (erasable — no enums). `--out <path>` writes the file; the generated header records the exact command to regenerate it. `--json` for the raw handle map. |
85
85
 
86
86
  `--json` on read commands emits machine-readable output. Results go to stdout,
87
87
  diagnostics to stderr.
package/dist/cli.js CHANGED
@@ -8967,7 +8967,7 @@ Account created. Enter the verification code emailed to ${opts.email}.`);
8967
8967
  }
8968
8968
 
8969
8969
  // src/lib/track.ts
8970
- var CLI_UNTRACKED_COMMANDS = /* @__PURE__ */ new Set(["login", "signup", "logout", "verify"]);
8970
+ var CLI_UNTRACKED_COMMANDS = /* @__PURE__ */ new Set(["login", "signup", "logout"]);
8971
8971
  function shouldTrackCommandExecution(name, hasUrl) {
8972
8972
  return hasUrl && !CLI_UNTRACKED_COMMANDS.has(name);
8973
8973
  }
@@ -9750,6 +9750,13 @@ function collectSelectors(opts, positionalFiles = []) {
9750
9750
  if (opts.release) found.push({ kind: "release", id: opts.release });
9751
9751
  return found;
9752
9752
  }
9753
+ function orderDiffSelectors(sels) {
9754
+ if (sels.length !== 2) return sels;
9755
+ const [first, second] = sels;
9756
+ if (second.kind === "live" && first.kind !== "live") return [second, first];
9757
+ if (first.kind === "file" && second.kind !== "file") return [second, first];
9758
+ return sels;
9759
+ }
9753
9760
  function describeSelector(sel) {
9754
9761
  switch (sel.kind) {
9755
9762
  case "file":
@@ -10079,7 +10086,7 @@ Command groups:
10079
10086
  Keys ingest-keys create|list|revoke
10080
10087
 
10081
10088
  Version selectors (no defaults \u2014 a command that reads a config requires one):
10082
- <file> a local Config File (positional, or --file <path>)
10089
+ <file> a local Playbook file (positional, or --file <path>)
10083
10090
  --draft the tenant's single open draft (resolved automatically)
10084
10091
  --live the current live Release
10085
10092
  --release <id> a specific playbook version / Release
@@ -10090,13 +10097,13 @@ Common workflows:
10090
10097
 
10091
10098
  # Author, validate, and ship against the default instance (revturbine.com/app)
10092
10099
  revturbine login
10093
- revturbine download --live --save ./config.json
10094
- revturbine validate ./config.json
10095
- revturbine diff ./config.json --live
10096
- revturbine launch ./config.json
10100
+ revturbine download --live --save ./revturbine.playbook.json
10101
+ revturbine validate ./revturbine.playbook.json
10102
+ revturbine diff ./revturbine.playbook.json --live
10103
+ revturbine launch ./revturbine.playbook.json
10097
10104
 
10098
10105
  # Manual review flow (stage \u2192 inspect \u2192 launch)
10099
- revturbine upload ./config.json # stage as the open draft
10106
+ revturbine upload ./revturbine.playbook.json # stage as the open draft
10100
10107
  revturbine preview # inspect the open draft
10101
10108
  revturbine validate --draft # full server catalog
10102
10109
  revturbine launch --draft
@@ -10126,7 +10133,7 @@ program.hook("postAction", async (_thisCommand, actionCommand) => {
10126
10133
  command: actionCommand.name()
10127
10134
  });
10128
10135
  });
10129
- program.name("revturbine").description("Validate RevTurbine Config Files and ship them through the playbook-version lifecycle (draft \u2192 Release).").version(`${pkgVersion} (schema ${SCHEMA_VERSION})`, "-V, --version", "Print the revturbine and bundled schema versions").option(NO_LOCAL_FLAG, "Ignore the repo-pinned CLI and run this installation").showHelpAfterError().addHelpText("after", HELP_AFTER);
10136
+ program.name("revturbine").description("Validate RevTurbine Playbooks and ship them through the playbook-version lifecycle (draft \u2192 Release).").version(`${pkgVersion} (schema ${SCHEMA_VERSION})`, "-V, --version", "Print the revturbine and bundled schema versions").option(NO_LOCAL_FLAG, "Ignore the repo-pinned CLI and run this installation").showHelpAfterError().addHelpText("after", HELP_AFTER);
10130
10137
  function runInstall(manager, args, cwd) {
10131
10138
  return new Promise((resolve, reject) => {
10132
10139
  const child = spawn2(manager, args, { cwd, stdio: "inherit", shell: true });
@@ -10427,7 +10434,7 @@ program.command("download").description("Fetch a config version from the server.
10427
10434
  }
10428
10435
  }
10429
10436
  );
10430
- program.command("validate").description("Validate a Config File offline (schema), or the open draft against the full server catalog (--draft).").argument("[file...]", "Path(s) to a Config File (offline mode)").option("--draft", "Validate the open draft server-side (full catalog)").option("-u, --url <url>", "RevTurbine instance URL (used with --draft)", DEFAULT_URL).option("-t, --tenant-id <id>", "x-tenant-id (defaults to the stored token tenant)").action(async (files, opts) => {
10437
+ program.command("validate").description("Validate a Playbook file offline (schema), or the open draft against the full server catalog (--draft).").argument("[file...]", "Path(s) to a Playbook file (offline mode)").option("--draft", "Validate the open draft server-side (full catalog)").option("-u, --url <url>", "RevTurbine instance URL (used with --draft)", DEFAULT_URL).option("-t, --tenant-id <id>", "x-tenant-id (defaults to the stored token tenant)").action(async (files, opts) => {
10431
10438
  if (opts.draft && files.length > 0) fail(EXIT.USAGE, "validate takes either <file> or --draft, not both.");
10432
10439
  if (!opts.draft && files.length === 0) {
10433
10440
  throw new SelectorError("STATE_REQUIRED \u2014 validate needs a version: <file> (offline) or --draft (server catalog).");
@@ -10469,16 +10476,17 @@ program.command("validate").description("Validate a Config File offline (schema)
10469
10476
  }
10470
10477
  diag("\u2713 No blocking findings.");
10471
10478
  });
10472
- program.command("diff").description("Compare two config versions (first \u2192 second). Dry-run, no writes.").argument("[file...]", "Local Config File path(s)").option("--draft", "The tenant's open draft").option("--live", "The current live Release").option("--release <id>", "A specific playbook version / Release").option("-u, --url <url>", "RevTurbine instance URL", DEFAULT_URL).option("-t, --tenant-id <id>", "x-tenant-id (defaults to the stored token tenant)").action(async (files, opts) => {
10479
+ program.command("diff").description("Compare two config versions (first \u2192 second; a file vs --draft/--live/--release previews the launch \u2014 the server side is the base). Dry-run, no writes.").argument("[file...]", "Local Playbook file path(s)").option("--draft", "The tenant's open draft").option("--live", "The current live Release").option("--release <id>", "A specific playbook version / Release").option("-u, --url <url>", "RevTurbine instance URL", DEFAULT_URL).option("-t, --tenant-id <id>", "x-tenant-id (defaults to the stored token tenant)").action(async (files, opts) => {
10473
10480
  const sels = requireSelectors(opts, files, { count: 2, allowed: ["file", "draft", "live", "release"], command: "diff" });
10474
- const needsServer = sels.some((s) => s.kind !== "file");
10481
+ const ordered = orderDiffSelectors(sels);
10482
+ const needsServer = ordered.some((s) => s.kind !== "file");
10475
10483
  const conn = needsServer ? connect(opts.url, opts.tenantId) : null;
10476
- const [a, b] = await Promise.all(sels.map((s) => loadVersion(conn, s)));
10477
- diag(`Diff (${sels.map((s) => s.kind === "file" ? s.path : s.kind === "release" ? `--release ${s.id}` : `--${s.kind}`).join(" \u2192 ")}):`);
10484
+ const [a, b] = await Promise.all(ordered.map((s) => loadVersion(conn, s)));
10485
+ diag(`Diff (${ordered.map((s) => s.kind === "file" ? s.path : s.kind === "release" ? `--release ${s.id}` : `--${s.kind}`).join(" \u2192 ")}):`);
10478
10486
  process.stdout.write(`${formatDiff(diffExportedConfig(a, b))}
10479
10487
  `);
10480
10488
  });
10481
- program.command("show").description(`Render a summary view of a config version. <kind> \u2208 ${SHOW_KINDS.join(" | ")}.`).argument("<kind>", `One of: ${SHOW_KINDS.join(", ")}`).option("--file <path>", "A local Config File").option("--draft", "The tenant's open draft").option("--live", "The current live Release").option("--release <id>", "A specific playbook version / Release").option("-u, --url <url>", "RevTurbine instance URL", DEFAULT_URL).option("-t, --tenant-id <id>", "x-tenant-id (defaults to the stored token tenant)").option("--json", "Machine-readable output").action(
10489
+ program.command("show").description(`Render a summary view of a config version. <kind> \u2208 ${SHOW_KINDS.join(" | ")}.`).argument("<kind>", `One of: ${SHOW_KINDS.join(", ")}`).option("--file <path>", "A local Playbook file").option("--draft", "The tenant's open draft").option("--live", "The current live Release").option("--release <id>", "A specific playbook version / Release").option("-u, --url <url>", "RevTurbine instance URL", DEFAULT_URL).option("-t, --tenant-id <id>", "x-tenant-id (defaults to the stored token tenant)").option("--json", "Machine-readable output").action(
10482
10490
  async (kind, opts) => {
10483
10491
  if (!SHOW_KINDS.includes(kind)) {
10484
10492
  fail(EXIT.USAGE, `unknown kind '${kind}' \u2014 use one of: ${SHOW_KINDS.join(", ")}.`);
@@ -10493,7 +10501,7 @@ program.command("show").description(`Render a summary view of a config version.
10493
10501
  );
10494
10502
  var PRUNE_OPTION = ["--prune", "Confirm a convergent delete past the mass-deletion guard (removes entities absent from the file)"];
10495
10503
  var NO_PRUNE_OPTION = ["--no-prune", "Additive import \u2014 keep entities that are absent from the file (disables convergent delete)"];
10496
- program.command("upload").description("Stage a Config File as the open draft (POST /api/config/import).").argument("<config>", "Path to a Config File").option("-u, --url <url>", "RevTurbine instance URL", DEFAULT_URL).option("-t, --tenant-id <id>", "x-tenant-id (defaults to the stored token tenant)").option(...PRUNE_OPTION).option(...NO_PRUNE_OPTION).action(async (configFile2, opts) => {
10504
+ program.command("upload").description("Stage a Playbook file as the open draft (POST /api/config/import).").argument("<config>", "Path to a Playbook file").option("-u, --url <url>", "RevTurbine instance URL", DEFAULT_URL).option("-t, --tenant-id <id>", "x-tenant-id (defaults to the stored token tenant)").option(...PRUNE_OPTION).option(...NO_PRUNE_OPTION).action(async (configFile2, opts) => {
10497
10505
  const config = verifyConfig(configFile2);
10498
10506
  if (config === null) fail(EXIT.VALIDATION, `Fix the issues above in ${configFile2}, then re-run.`);
10499
10507
  const conn = connect(opts.url, uploadTenantFor(opts.url, config, opts.tenantId));
@@ -10514,7 +10522,7 @@ program.command("upload").description("Stage a Config File as the open draft (PO
10514
10522
  if (playbookVersionId) diagRaw(` playbook_version_id: ${playbookVersionId}`);
10515
10523
  diag("Launch it with `revturbine launch --draft`, or from the UI (Drafts & Releases).");
10516
10524
  });
10517
- program.command("launch").description("Take a config live as a new Release: validate (launch gate), then submit \u2192 approve \u2192 deploy. Synchronous.").argument("[file]", "Config File to upload and launch directly").option("--draft", "Launch the already-open draft").option("--force", "Launch past incomplete-but-valid findings (error_launch); structural errors (error_draft) still block").option("-u, --url <url>", "RevTurbine instance URL", DEFAULT_URL).option("-t, --tenant-id <id>", "x-tenant-id (defaults to the stored token tenant)").option(...PRUNE_OPTION).option(...NO_PRUNE_OPTION).option("--yes", "Accepted for parity with discard/restore; launch has no confirmation prompt").action(async (file, opts) => {
10525
+ program.command("launch").description("Take a config live as a new Release: validate (launch gate), then submit \u2192 approve \u2192 deploy. Synchronous.").argument("[file]", "Playbook file to upload and launch directly").option("--draft", "Launch the already-open draft").option("--force", "Launch past incomplete-but-valid findings (error_launch); structural errors (error_draft) still block").option("-u, --url <url>", "RevTurbine instance URL", DEFAULT_URL).option("-t, --tenant-id <id>", "x-tenant-id (defaults to the stored token tenant)").option(...PRUNE_OPTION).option(...NO_PRUNE_OPTION).option("--yes", "Accepted for parity with discard/restore; launch has no confirmation prompt").action(async (file, opts) => {
10518
10526
  const [sel] = requireSelectors(opts, file ? [file] : [], { count: 1, allowed: ["file", "draft"], command: "launch" });
10519
10527
  let conn;
10520
10528
  let playbookVersionId;
@@ -10658,7 +10666,7 @@ program.command("evaluate").description("Run placement/entitlement decisions for
10658
10666
  var generateCmd = program.command("generate").description("Code generation from a config version (see: generate types).");
10659
10667
  generateCmd.command("types").description(
10660
10668
  "Generate a TypeScript module of Playbook handles \u2014 entitlements (namespaced by type), plans, segments, surface-template ids, and ui-path action types \u2014 for type-safe call sites."
10661
- ).argument("[file...]", "Path to a Config File").option("--draft", "The tenant's open draft").option("--live", "The current live Release").option("--release <id>", "A specific playbook version / Release").option("-o, --out <path>", "Write the generated module to this path (parent dirs created); default stdout").option("--json", "Emit the handle map as JSON instead of TypeScript").option("-u, --url <url>", "RevTurbine instance URL", DEFAULT_URL).option("-t, --tenant-id <id>", "x-tenant-id (defaults to the stored token tenant)").action(
10669
+ ).argument("[file...]", "Path to a Playbook file").option("--draft", "The tenant's open draft").option("--live", "The current live Release").option("--release <id>", "A specific playbook version / Release").option("-o, --out <path>", "Write the generated module to this path (parent dirs created); default stdout").option("--json", "Emit the handle map as JSON instead of TypeScript").option("-u, --url <url>", "RevTurbine instance URL", DEFAULT_URL).option("-t, --tenant-id <id>", "x-tenant-id (defaults to the stored token tenant)").action(
10662
10670
  async (files, opts) => {
10663
10671
  const [sel] = requireSelectors(opts, files, {
10664
10672
  count: 1,
@@ -10728,23 +10736,23 @@ var COMMAND_EXAMPLES = {
10728
10736
  download: [
10729
10737
  "",
10730
10738
  "Examples:",
10731
- " revturbine download --live --save ./config.json The live config \u2192 file",
10739
+ " revturbine download --live --save ./revturbine.playbook.json The live config \u2192 file",
10732
10740
  " revturbine download --draft The open draft (rendered on demand) \u2192 stdout",
10733
10741
  " revturbine download --release cs_1a2b3c --format flatbuffer --save ./bundle.fb"
10734
10742
  ].join("\n"),
10735
10743
  validate: [
10736
10744
  "",
10737
10745
  "Examples:",
10738
- " revturbine validate ./config.json Offline schema validation (no network)",
10746
+ " revturbine validate ./revturbine.playbook.json Offline schema validation (no network)",
10739
10747
  " revturbine validate --draft Full server catalog against the open draft"
10740
10748
  ].join("\n"),
10741
10749
  diff: [
10742
10750
  "",
10743
10751
  "Examples:",
10744
- " revturbine diff ./config.json --live Local edits vs the live config",
10752
+ " revturbine diff ./revturbine.playbook.json --live Local edits vs the live config",
10745
10753
  " revturbine diff --live --draft What the open draft would change"
10746
10754
  ].join("\n"),
10747
- show: ["", "Examples:", " revturbine show plans --live", " revturbine show segments --file ./config.json"].join("\n"),
10755
+ show: ["", "Examples:", " revturbine show plans --live", " revturbine show segments --file ./revturbine.playbook.json"].join("\n"),
10748
10756
  generate: [
10749
10757
  "",
10750
10758
  "Examples:",
@@ -10756,11 +10764,11 @@ var COMMAND_EXAMPLES = {
10756
10764
  "entitlement type) and the `EntitlementHandle` union for can()/gate()",
10757
10765
  "call sites. Its header records the exact command to regenerate it."
10758
10766
  ].join("\n"),
10759
- upload: ["", "Example:", " revturbine upload ./config.json Stage as the open draft"].join("\n"),
10767
+ upload: ["", "Example:", " revturbine upload ./revturbine.playbook.json Stage as the open draft"].join("\n"),
10760
10768
  launch: [
10761
10769
  "",
10762
10770
  "Examples:",
10763
- " revturbine launch ./config.json Upload, gate, and go live",
10771
+ " revturbine launch ./revturbine.playbook.json Upload, gate, and go live",
10764
10772
  " revturbine launch --draft Launch the already-open draft"
10765
10773
  ].join("\n"),
10766
10774
  evaluate: [
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@revturbine/cli",
3
- "version": "0.16.0",
4
- "description": "revturbine — verify RevTurbine ExportedConfig files and ship them to a RevTurbine instance through the Change Set lifecycle.",
3
+ "version": "0.16.2",
4
+ "description": "revturbine — validate RevTurbine Playbooks and ship them to a RevTurbine instance through the playbook-version lifecycle (draft → Release).",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",