@drip-apex/apex-cli 0.9.0 → 0.11.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 +15 -1
- package/dist/cli.js +49 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -86,6 +86,16 @@ apex schema --json
|
|
|
86
86
|
|
|
87
87
|
Use `apex` as the canonical command name. `drip` is a compatibility alias.
|
|
88
88
|
|
|
89
|
+
`apex experiments list` returns code-free summaries by default, including
|
|
90
|
+
`targeting_urls` and `variation_count`, without targeting objects, variations, or goals.
|
|
91
|
+
Use `--full --json` for full details, including code. `--full` keeps the default table unchanged.
|
|
92
|
+
Use `--fields id,test_key,name,status --json` to select top-level keys (JSON always keeps `id`),
|
|
93
|
+
or `--fields status,name` to print exactly those table columns in order.
|
|
94
|
+
`--fields` and `--full` can combine; invalid fields return the allowed keys.
|
|
95
|
+
Existing CR-011 filters still narrow the set; these flags only select row content.
|
|
96
|
+
The direct API retains its full default view; the CLI requests `view=summary`.
|
|
97
|
+
Summary timestamps include `created_at` and `archived_at`; experiments have no `updated_at` field.
|
|
98
|
+
|
|
89
99
|
`apex experiments list` hides archived experiments by default. Pass
|
|
90
100
|
`--include-archived` to include them; archived rows display their archive date
|
|
91
101
|
when the API provides `archived_at`.
|
|
@@ -129,7 +139,7 @@ including every subcommand, argument, option, and alias.
|
|
|
129
139
|
- `apex experiments` — create, inspect, operate, and synchronize experiments.
|
|
130
140
|
Use `apex experiments screenshots <id-or-slug>` to force-assign every capture, including control, to its variation server-side for deterministic screenshots. Resume a job that outlives the CLI timeout with `--job <id>`; polling continues without creating another job, and the stored job's devices and variations win, so `--devices`/`--variations` are ignored (the CLI warns). The command attaches terminal jobs to the QA run by default; use `--no-attach-qa` to opt out. Choose devices with `--devices`, filter treatments with `--variations`, and use `--json` for the signed result payload. Use `apex experiments qa evidence` with `--job`, repeatable `--file`, or `--records` to write QA evidence directly.
|
|
131
141
|
- `apex push` — synchronize `.drip.config.ts` with Apex.
|
|
132
|
-
- `apex preview` — open a variation QA preview.
|
|
142
|
+
- `apex preview` — open a variation QA preview; `--proxy` returns a `qa_run` receipt. Its `automated_evidence_count` counts the normalized `evidenceRecords` across all evidence kinds, matching the list shown by `apex experiments qa status`.
|
|
133
143
|
- `apex roadmap` — consume approved roadmap ideas and handoffs.
|
|
134
144
|
- `apex harness` — develop AB Test Harness projects with live QA sessions.
|
|
135
145
|
- `apex workspace` — check out, preview, and publish draft workspace files.
|
|
@@ -328,3 +338,7 @@ optimistic concurrency token.
|
|
|
328
338
|
| --- | --- |
|
|
329
339
|
| `approval` | Roadmap decision status (`proposed` without a decision), item stage, and decision's nullable `decided_at`. Top-level `status` remains the item lifecycle status. |
|
|
330
340
|
| `goals` | `apex_goal_id` is the linked experiment goal or null. |
|
|
341
|
+
|
|
342
|
+
QA status creates a run only when none exists. Reading an existing run never writes
|
|
343
|
+
to it: `updatedAt` is its last stored mutation time, while `computedAt` is the ISO
|
|
344
|
+
timestamp when the current checklist and summary were computed.
|
package/dist/cli.js
CHANGED
|
@@ -7112,7 +7112,7 @@ var import_node_os3 = __toESM(require("node:os"));
|
|
|
7112
7112
|
// package.json
|
|
7113
7113
|
var package_default = {
|
|
7114
7114
|
name: "@drip-apex/apex-cli",
|
|
7115
|
-
version: "0.
|
|
7115
|
+
version: "0.11.0",
|
|
7116
7116
|
license: "MIT",
|
|
7117
7117
|
description: "Apex CLI for managing experiments, approved roadmap ideas, and draft workspaces.",
|
|
7118
7118
|
private: false,
|
|
@@ -7762,6 +7762,8 @@ function listExperiments(creds, opts) {
|
|
|
7762
7762
|
if (opts?.limit) params.set("limit", String(opts.limit));
|
|
7763
7763
|
if (opts?.cursor) params.set("cursor", opts.cursor);
|
|
7764
7764
|
if (opts?.includeArchived) params.set("archived", "1");
|
|
7765
|
+
if (opts?.view) params.set("view", opts.view);
|
|
7766
|
+
if (opts?.fields !== void 0) params.set("fields", opts.fields);
|
|
7765
7767
|
const qs = params.toString();
|
|
7766
7768
|
return request(creds, "GET", `/api/v1/experiments${qs ? `?${qs}` : ""}`);
|
|
7767
7769
|
}
|
|
@@ -9639,6 +9641,7 @@ function printQaPreviewUrls(experimentId, result) {
|
|
|
9639
9641
|
function printQaRun(run3) {
|
|
9640
9642
|
console.log();
|
|
9641
9643
|
console.log(source_default.bold(`QA run ${run3.id}`));
|
|
9644
|
+
console.log(` computedAt: ${run3.computedAt}`);
|
|
9642
9645
|
console.log(` Status: ${statusBadge(run3.summary.status)}`);
|
|
9643
9646
|
console.log(` Required: ${run3.summary.completedRequired}/${run3.summary.required}`);
|
|
9644
9647
|
if (run3.approvedAt) console.log(` Approved: ${run3.approvedAt}`);
|
|
@@ -9804,16 +9807,23 @@ async function resolveExperiment(idOrSlug) {
|
|
|
9804
9807
|
res.errorDetails
|
|
9805
9808
|
);
|
|
9806
9809
|
}
|
|
9807
|
-
var list = new Command("list").alias("ls").description(
|
|
9810
|
+
var list = new Command("list").alias("ls").description(
|
|
9811
|
+
"List experiments in summary view by default; use --full for details or --fields for selected columns (archived experiments are hidden by default)"
|
|
9812
|
+
).option(
|
|
9808
9813
|
"-s, --status <status>",
|
|
9809
9814
|
"Filter by status (draft|awaiting_client_approval|changes_requested|client_approved|qa|ready_to_launch|running|paused|completed)"
|
|
9810
|
-
).option("-n, --limit <n>", "Max results", "20").option("--include-archived", "Include archived experiments").
|
|
9815
|
+
).option("-n, --limit <n>", "Max results", "20").option("--include-archived", "Include archived experiments").option("--full", "Return full experiment details instead of the default summary").option(
|
|
9816
|
+
"--fields <list>",
|
|
9817
|
+
"Comma-separated fields to return and table columns in order (JSON always keeps id)"
|
|
9818
|
+
).action(async function action3(opts) {
|
|
9811
9819
|
const creds = requireCredentials();
|
|
9812
9820
|
const spinner = await createSpinner("Fetching experiments...");
|
|
9813
9821
|
const res = await listExperiments(creds, {
|
|
9814
9822
|
status: opts.status,
|
|
9815
9823
|
limit: parseInt(opts.limit, 10),
|
|
9816
|
-
includeArchived: opts.includeArchived
|
|
9824
|
+
includeArchived: opts.includeArchived,
|
|
9825
|
+
view: opts.full ? "full" : "summary",
|
|
9826
|
+
fields: opts.fields
|
|
9817
9827
|
});
|
|
9818
9828
|
if (!res.ok) {
|
|
9819
9829
|
spinner?.fail("Failed to fetch experiments");
|
|
@@ -9826,18 +9836,32 @@ var list = new Command("list").alias("ls").description("List experiments (archiv
|
|
|
9826
9836
|
console.log(source_default.dim("No experiments found."));
|
|
9827
9837
|
return;
|
|
9828
9838
|
}
|
|
9829
|
-
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
|
|
9835
|
-
|
|
9836
|
-
|
|
9837
|
-
|
|
9838
|
-
|
|
9839
|
-
|
|
9840
|
-
|
|
9839
|
+
if (opts.fields !== void 0) {
|
|
9840
|
+
const fields3 = [
|
|
9841
|
+
...new Set(opts.fields.split(",").map((field) => field.trim()))
|
|
9842
|
+
];
|
|
9843
|
+
printTable(
|
|
9844
|
+
fields3.map((field) => field.toUpperCase()),
|
|
9845
|
+
experiments.map(
|
|
9846
|
+
(experiment) => fields3.map((field) => {
|
|
9847
|
+
const value = experiment[field];
|
|
9848
|
+
return value == null ? "-" : typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
9849
|
+
})
|
|
9850
|
+
)
|
|
9851
|
+
);
|
|
9852
|
+
} else
|
|
9853
|
+
printTable(
|
|
9854
|
+
["NAME", "SLUG", "STATUS", "ARCHIVED", "TRAFFIC", "CREATED"],
|
|
9855
|
+
experiments.map((e) => [
|
|
9856
|
+
e.name.slice(0, 40),
|
|
9857
|
+
e.slug ?? source_default.dim("-"),
|
|
9858
|
+
statusBadge(e.status),
|
|
9859
|
+
e.archived_at ? formatDate(e.archived_at) : source_default.dim("-"),
|
|
9860
|
+
`${(e.traffic_allocation * 100).toFixed(0)}%`,
|
|
9861
|
+
formatDate(e.created_at)
|
|
9862
|
+
]),
|
|
9863
|
+
[40, 25, 12, 15, 8, 15]
|
|
9864
|
+
);
|
|
9841
9865
|
if (res.data.pagination.has_more) {
|
|
9842
9866
|
console.log(source_default.dim(`
|
|
9843
9867
|
(more results available)`));
|
|
@@ -10826,7 +10850,9 @@ var applyFilesystem = new Command("apply").option("--sync", "Refresh local autho
|
|
|
10826
10850
|
fail(this, error instanceof Error ? error.message : String(error));
|
|
10827
10851
|
}
|
|
10828
10852
|
});
|
|
10829
|
-
var qaStatus = new Command("status").description(
|
|
10853
|
+
var qaStatus = new Command("status").description(
|
|
10854
|
+
"Show the latest experiment QA run (creates one only when none exists; reads never change updatedAt)"
|
|
10855
|
+
).argument(
|
|
10830
10856
|
"[folder-or-id]",
|
|
10831
10857
|
"Experiment filesystem folder, ID, slug, or test key (for example BIO-085)",
|
|
10832
10858
|
"."
|
|
@@ -11791,7 +11817,9 @@ var pushCommand = new Command("push").description("Push experiment definitions f
|
|
|
11791
11817
|
|
|
11792
11818
|
// src/commands/preview.ts
|
|
11793
11819
|
init_source();
|
|
11794
|
-
var previewCommand = new Command("preview").description(
|
|
11820
|
+
var previewCommand = new Command("preview").description(
|
|
11821
|
+
"Open QA preview URL for an experiment variation; proxy previews return a QA run receipt"
|
|
11822
|
+
).argument("<id-or-slug>", "Experiment ID or slug").argument("[variation-id]", "Variation ID (defaults to first non-control)").option("--store-url <url>", "Override experiment store_url (target website URL)").option("--proxy", "Create an artifact-injecting proxy preview").option("--ttl <hours>", "Proxy preview lifetime in hours (1-168)").option("--no-open", "Print URL instead of opening browser").action(
|
|
11795
11823
|
async (idOrSlug, variationId, opts) => {
|
|
11796
11824
|
const creds = requireCredentials();
|
|
11797
11825
|
if (opts?.proxy) {
|
|
@@ -11819,6 +11847,9 @@ var previewCommand = new Command("preview").description("Open QA preview URL for
|
|
|
11819
11847
|
const data = created.data;
|
|
11820
11848
|
output(previewCommand, data, () => {
|
|
11821
11849
|
console.log(source_default.cyan(data.preview_url));
|
|
11850
|
+
console.log(
|
|
11851
|
+
data.qa_run.created ? `QA run ${data.qa_run.id} created` : `QA run ${data.qa_run.id} refreshed (${data.qa_run.automated_evidence_count} automated evidence records)`
|
|
11852
|
+
);
|
|
11822
11853
|
const expiresAt = new Date(data.expires_at);
|
|
11823
11854
|
const remainingMs = expiresAt.getTime() - Date.now();
|
|
11824
11855
|
const value = remainingMs < 864e5 ? Math.max(1, Math.round(remainingMs / 36e5)) : Math.round(remainingMs / 864e5);
|