@eide/foir-cli 0.14.1 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +140 -11
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -2099,8 +2099,10 @@ import {
|
|
|
2099
2099
|
ForceAssignExperimentRequestSchema,
|
|
2100
2100
|
RemoveExperimentAssignmentRequestSchema,
|
|
2101
2101
|
ApplyExperimentWinnerRequestSchema,
|
|
2102
|
-
|
|
2103
|
-
|
|
2102
|
+
GetAssignmentsRequestSchema,
|
|
2103
|
+
ListExperimentDeclarationsRequestSchema,
|
|
2104
|
+
ExperimentVariantSchema,
|
|
2105
|
+
ExperimentGoalSchema
|
|
2104
2106
|
} from "@eide/foir-proto-ts/experiments/v1/experiments_pb";
|
|
2105
2107
|
import { ExperimentStatus as ExperimentStatus2 } from "@eide/foir-proto-ts/experiments/v1/experiments_pb";
|
|
2106
2108
|
var STATUS_TO_PROTO = {
|
|
@@ -2156,6 +2158,14 @@ function createExperimentsMethods(client) {
|
|
|
2156
2158
|
name: v.name,
|
|
2157
2159
|
percent: v.percent
|
|
2158
2160
|
})
|
|
2161
|
+
) ?? [],
|
|
2162
|
+
assignmentPersistence: params.assignmentPersistence,
|
|
2163
|
+
goals: params.goals?.map(
|
|
2164
|
+
(g) => create7(ExperimentGoalSchema, {
|
|
2165
|
+
key: g.key,
|
|
2166
|
+
name: g.name,
|
|
2167
|
+
description: g.description
|
|
2168
|
+
})
|
|
2159
2169
|
) ?? []
|
|
2160
2170
|
})
|
|
2161
2171
|
);
|
|
@@ -2175,7 +2185,16 @@ function createExperimentsMethods(client) {
|
|
|
2175
2185
|
name: v.name,
|
|
2176
2186
|
percent: v.percent
|
|
2177
2187
|
})
|
|
2178
|
-
)
|
|
2188
|
+
),
|
|
2189
|
+
assignmentPersistence: params.assignmentPersistence,
|
|
2190
|
+
goals: params.goals?.map(
|
|
2191
|
+
(g) => create7(ExperimentGoalSchema, {
|
|
2192
|
+
key: g.key,
|
|
2193
|
+
name: g.name,
|
|
2194
|
+
description: g.description
|
|
2195
|
+
})
|
|
2196
|
+
) ?? [],
|
|
2197
|
+
goalsClear: params.goalsClear ?? false
|
|
2179
2198
|
})
|
|
2180
2199
|
);
|
|
2181
2200
|
return resp.experiment ?? null;
|
|
@@ -2221,30 +2240,41 @@ function createExperimentsMethods(client) {
|
|
|
2221
2240
|
return resp.experiment ?? null;
|
|
2222
2241
|
},
|
|
2223
2242
|
// ── Assignments ──────────────────────────────────────────
|
|
2224
|
-
async forceAssignExperiment(
|
|
2243
|
+
async forceAssignExperiment(identity, experimentId, variantKey) {
|
|
2225
2244
|
const resp = await client.forceAssignExperiment(
|
|
2226
2245
|
create7(ForceAssignExperimentRequestSchema, {
|
|
2227
|
-
customerId,
|
|
2246
|
+
customerId: identity.customerId,
|
|
2247
|
+
viewerKey: identity.viewerKey,
|
|
2228
2248
|
experimentId,
|
|
2229
2249
|
variantKey
|
|
2230
2250
|
})
|
|
2231
2251
|
);
|
|
2232
2252
|
return resp.assignment ?? null;
|
|
2233
2253
|
},
|
|
2234
|
-
async removeExperimentAssignment(
|
|
2254
|
+
async removeExperimentAssignment(identity, experimentId) {
|
|
2235
2255
|
const resp = await client.removeExperimentAssignment(
|
|
2236
2256
|
create7(RemoveExperimentAssignmentRequestSchema, {
|
|
2237
|
-
customerId,
|
|
2257
|
+
customerId: identity.customerId,
|
|
2258
|
+
viewerKey: identity.viewerKey,
|
|
2238
2259
|
experimentId
|
|
2239
2260
|
})
|
|
2240
2261
|
);
|
|
2241
2262
|
return resp.success;
|
|
2242
2263
|
},
|
|
2243
|
-
async
|
|
2244
|
-
const resp = await client.
|
|
2245
|
-
create7(
|
|
2264
|
+
async getAssignments(identity) {
|
|
2265
|
+
const resp = await client.getAssignments(
|
|
2266
|
+
create7(GetAssignmentsRequestSchema, {
|
|
2267
|
+
customerId: identity.customerId,
|
|
2268
|
+
viewerKey: identity.viewerKey
|
|
2269
|
+
})
|
|
2246
2270
|
);
|
|
2247
2271
|
return resp.assignments ?? [];
|
|
2272
|
+
},
|
|
2273
|
+
async listExperimentDeclarations() {
|
|
2274
|
+
const resp = await client.listExperimentDeclarations(
|
|
2275
|
+
create7(ListExperimentDeclarationsRequestSchema, {})
|
|
2276
|
+
);
|
|
2277
|
+
return resp.declarations ?? [];
|
|
2248
2278
|
}
|
|
2249
2279
|
};
|
|
2250
2280
|
}
|
|
@@ -7188,7 +7218,8 @@ function registerSegmentsCommands(program2, globalOpts) {
|
|
|
7188
7218
|
// src/commands/experiments.ts
|
|
7189
7219
|
import {
|
|
7190
7220
|
ExperimentSchema,
|
|
7191
|
-
ExperimentStatsSchema
|
|
7221
|
+
ExperimentStatsSchema,
|
|
7222
|
+
ExperimentAssignmentSchema
|
|
7192
7223
|
} from "@eide/foir-proto-ts/experiments/v1/experiments_pb";
|
|
7193
7224
|
function registerExperimentsCommands(program2, globalOpts) {
|
|
7194
7225
|
const experiments = program2.command("experiments").description("Manage experiments");
|
|
@@ -7336,6 +7367,104 @@ function registerExperimentsCommands(program2, globalOpts) {
|
|
|
7336
7367
|
formatOutputProto(ExperimentStatsSchema, result, opts);
|
|
7337
7368
|
})
|
|
7338
7369
|
);
|
|
7370
|
+
experiments.command("force-assign <experimentId>").description(
|
|
7371
|
+
"Force a known identity into a specific variant (admin override)."
|
|
7372
|
+
).requiredOption("--variant <key>", "Variant key to assign").option("--customer-id <id>", "Customer identity to bucket").option(
|
|
7373
|
+
"--viewer-key <key>",
|
|
7374
|
+
"Anonymous viewer identity (cookie/localStorage value) to bucket"
|
|
7375
|
+
).action(
|
|
7376
|
+
withErrorHandler(
|
|
7377
|
+
globalOpts,
|
|
7378
|
+
async (experimentId, cmdOpts) => {
|
|
7379
|
+
const opts = globalOpts();
|
|
7380
|
+
if (!cmdOpts.customerId && !cmdOpts.viewerKey) {
|
|
7381
|
+
throw new Error(
|
|
7382
|
+
"Provide exactly one of --customer-id or --viewer-key."
|
|
7383
|
+
);
|
|
7384
|
+
}
|
|
7385
|
+
if (cmdOpts.customerId && cmdOpts.viewerKey) {
|
|
7386
|
+
throw new Error(
|
|
7387
|
+
"Provide exactly one of --customer-id or --viewer-key, not both."
|
|
7388
|
+
);
|
|
7389
|
+
}
|
|
7390
|
+
const client = await createPlatformClient(opts);
|
|
7391
|
+
const result = await client.experiments.forceAssignExperiment(
|
|
7392
|
+
{ customerId: cmdOpts.customerId, viewerKey: cmdOpts.viewerKey },
|
|
7393
|
+
experimentId,
|
|
7394
|
+
cmdOpts.variant
|
|
7395
|
+
);
|
|
7396
|
+
if (!result) throw new Error("Force-assign returned no assignment.");
|
|
7397
|
+
formatOutputProto(ExperimentAssignmentSchema, result, opts);
|
|
7398
|
+
if (!(opts.json || opts.jsonl || opts.quiet))
|
|
7399
|
+
success(
|
|
7400
|
+
`Assigned ${cmdOpts.customerId ? "customer" : "viewer"} ${cmdOpts.customerId ?? cmdOpts.viewerKey} \u2192 ${cmdOpts.variant}`
|
|
7401
|
+
);
|
|
7402
|
+
}
|
|
7403
|
+
)
|
|
7404
|
+
);
|
|
7405
|
+
experiments.command("remove-assignment <experimentId>").description("Remove the assignment for a known identity.").option("--customer-id <id>", "Customer identity to clear").option("--viewer-key <key>", "Anonymous viewer identity to clear").action(
|
|
7406
|
+
withErrorHandler(
|
|
7407
|
+
globalOpts,
|
|
7408
|
+
async (experimentId, cmdOpts) => {
|
|
7409
|
+
const opts = globalOpts();
|
|
7410
|
+
if (!cmdOpts.customerId && !cmdOpts.viewerKey) {
|
|
7411
|
+
throw new Error(
|
|
7412
|
+
"Provide exactly one of --customer-id or --viewer-key."
|
|
7413
|
+
);
|
|
7414
|
+
}
|
|
7415
|
+
if (cmdOpts.customerId && cmdOpts.viewerKey) {
|
|
7416
|
+
throw new Error(
|
|
7417
|
+
"Provide exactly one of --customer-id or --viewer-key, not both."
|
|
7418
|
+
);
|
|
7419
|
+
}
|
|
7420
|
+
const client = await createPlatformClient(opts);
|
|
7421
|
+
const ok = await client.experiments.removeExperimentAssignment(
|
|
7422
|
+
{ customerId: cmdOpts.customerId, viewerKey: cmdOpts.viewerKey },
|
|
7423
|
+
experimentId
|
|
7424
|
+
);
|
|
7425
|
+
if (opts.json || opts.jsonl)
|
|
7426
|
+
formatOutput({ removed: ok, experimentId }, opts);
|
|
7427
|
+
else if (ok) success("Assignment removed");
|
|
7428
|
+
else success("No matching assignment found");
|
|
7429
|
+
}
|
|
7430
|
+
)
|
|
7431
|
+
);
|
|
7432
|
+
experiments.command("assignments").description("List assignments for a single identity across experiments.").option("--customer-id <id>", "Customer identity to look up").option("--viewer-key <key>", "Anonymous viewer identity to look up").action(
|
|
7433
|
+
withErrorHandler(
|
|
7434
|
+
globalOpts,
|
|
7435
|
+
async (cmdOpts) => {
|
|
7436
|
+
const opts = globalOpts();
|
|
7437
|
+
if (!cmdOpts.customerId && !cmdOpts.viewerKey) {
|
|
7438
|
+
throw new Error(
|
|
7439
|
+
"Provide exactly one of --customer-id or --viewer-key."
|
|
7440
|
+
);
|
|
7441
|
+
}
|
|
7442
|
+
if (cmdOpts.customerId && cmdOpts.viewerKey) {
|
|
7443
|
+
throw new Error(
|
|
7444
|
+
"Provide exactly one of --customer-id or --viewer-key, not both."
|
|
7445
|
+
);
|
|
7446
|
+
}
|
|
7447
|
+
const client = await createPlatformClient(opts);
|
|
7448
|
+
const data = await client.experiments.getAssignments({
|
|
7449
|
+
customerId: cmdOpts.customerId,
|
|
7450
|
+
viewerKey: cmdOpts.viewerKey
|
|
7451
|
+
});
|
|
7452
|
+
formatListProto(ExperimentAssignmentSchema, data, opts, {
|
|
7453
|
+
columns: [
|
|
7454
|
+
{ key: "experimentKey", header: "Experiment", width: 24 },
|
|
7455
|
+
{ key: "variantKey", header: "Variant", width: 16 },
|
|
7456
|
+
{ key: "assignmentMethod", header: "Method", width: 10 },
|
|
7457
|
+
{
|
|
7458
|
+
key: "assignedAt",
|
|
7459
|
+
header: "Assigned",
|
|
7460
|
+
width: 12,
|
|
7461
|
+
format: (v) => timeAgo(v)
|
|
7462
|
+
}
|
|
7463
|
+
]
|
|
7464
|
+
});
|
|
7465
|
+
}
|
|
7466
|
+
)
|
|
7467
|
+
);
|
|
7339
7468
|
}
|
|
7340
7469
|
|
|
7341
7470
|
// src/commands/schedules.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eide/foir-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "Universal platform CLI for Foir platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@bufbuild/protovalidate": "^1.1.1",
|
|
51
51
|
"@connectrpc/connect": "^2.0.0",
|
|
52
52
|
"@connectrpc/connect-node": "^2.0.0",
|
|
53
|
-
"@eide/foir-proto-ts": "^0.
|
|
53
|
+
"@eide/foir-proto-ts": "^0.43.0",
|
|
54
54
|
"chalk": "^5.3.0",
|
|
55
55
|
"commander": "^12.1.0",
|
|
56
56
|
"dotenv": "^16.4.5",
|