@framedash/cli 0.1.1 → 0.1.3
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 +62 -5
- package/dist/commands/alerts.d.ts.map +1 -1
- package/dist/commands/alerts.js +2 -1
- package/dist/commands/alerts.js.map +1 -1
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +25 -2
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/builds.d.ts +2 -0
- package/dist/commands/builds.d.ts.map +1 -0
- package/dist/commands/builds.js +31 -0
- package/dist/commands/builds.js.map +1 -0
- package/dist/commands/content.d.ts.map +1 -1
- package/dist/commands/content.js +2 -2
- package/dist/commands/content.js.map +1 -1
- package/dist/commands/dashboard.d.ts.map +1 -1
- package/dist/commands/dashboard.js +3 -3
- package/dist/commands/dashboard.js.map +1 -1
- package/dist/commands/funnel.d.ts.map +1 -1
- package/dist/commands/funnel.js +7 -8
- package/dist/commands/funnel.js.map +1 -1
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +142 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +2 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +79 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/map-capture.d.ts +2 -1
- package/dist/commands/map-capture.d.ts.map +1 -1
- package/dist/commands/map-capture.js +42 -12
- package/dist/commands/map-capture.js.map +1 -1
- package/dist/commands/perf-diff.d.ts +2 -0
- package/dist/commands/perf-diff.d.ts.map +1 -0
- package/dist/commands/perf-diff.js +125 -0
- package/dist/commands/perf-diff.js.map +1 -0
- package/dist/commands/query.d.ts.map +1 -1
- package/dist/commands/query.js +12 -0
- package/dist/commands/query.js.map +1 -1
- package/dist/commands/retention.d.ts.map +1 -1
- package/dist/commands/retention.js +3 -3
- package/dist/commands/retention.js.map +1 -1
- package/dist/commands/run-profile-test.d.ts +7 -0
- package/dist/commands/run-profile-test.d.ts.map +1 -0
- package/dist/commands/run-profile-test.js +503 -0
- package/dist/commands/run-profile-test.js.map +1 -0
- package/dist/commands/threshold-profiles.d.ts +2 -0
- package/dist/commands/threshold-profiles.d.ts.map +1 -0
- package/dist/commands/threshold-profiles.js +24 -0
- package/dist/commands/threshold-profiles.js.map +1 -0
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/config.d.ts +42 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +44 -14
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/create-client.d.ts +27 -1
- package/dist/lib/create-client.d.ts.map +1 -1
- package/dist/lib/create-client.js +167 -24
- package/dist/lib/create-client.js.map +1 -1
- package/dist/lib/formatters.js +93 -1
- package/dist/lib/formatters.js.map +1 -1
- package/dist/lib/logger.d.ts +2 -0
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +4 -0
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/oauth/loopback-server.d.ts +27 -0
- package/dist/lib/oauth/loopback-server.d.ts.map +1 -0
- package/dist/lib/oauth/loopback-server.js +164 -0
- package/dist/lib/oauth/loopback-server.js.map +1 -0
- package/dist/lib/oauth/manager.d.ts +36 -0
- package/dist/lib/oauth/manager.d.ts.map +1 -0
- package/dist/lib/oauth/manager.js +130 -0
- package/dist/lib/oauth/manager.js.map +1 -0
- package/dist/lib/oauth/pkce.d.ts +15 -0
- package/dist/lib/oauth/pkce.d.ts.map +1 -0
- package/dist/lib/oauth/pkce.js +24 -0
- package/dist/lib/oauth/pkce.js.map +1 -0
- package/dist/lib/oauth/token-endpoint.d.ts +39 -0
- package/dist/lib/oauth/token-endpoint.d.ts.map +1 -0
- package/dist/lib/oauth/token-endpoint.js +117 -0
- package/dist/lib/oauth/token-endpoint.js.map +1 -0
- package/dist/lib/oauth/token-store.d.ts +34 -0
- package/dist/lib/oauth/token-store.d.ts.map +1 -0
- package/dist/lib/oauth/token-store.js +164 -0
- package/dist/lib/oauth/token-store.js.map +1 -0
- package/dist/lib/perf-diff-eval.d.ts +58 -0
- package/dist/lib/perf-diff-eval.d.ts.map +1 -0
- package/dist/lib/perf-diff-eval.js +49 -0
- package/dist/lib/perf-diff-eval.js.map +1 -0
- package/dist/lib/run-command.js +2 -2
- package/dist/lib/run-command.js.map +1 -1
- package/dist/lib/run-profile-test-lib.d.ts +156 -0
- package/dist/lib/run-profile-test-lib.d.ts.map +1 -0
- package/dist/lib/run-profile-test-lib.js +171 -0
- package/dist/lib/run-profile-test-lib.js.map +1 -0
- package/dist/lib/uploader.d.ts +14 -1
- package/dist/lib/uploader.d.ts.map +1 -1
- package/dist/lib/uploader.js +26 -12
- package/dist/lib/uploader.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { type UploadCredential } from "../lib/uploader.js";
|
|
1
2
|
/** CLI entry point for map-capture — parses args then delegates to mapCapture(). */
|
|
2
3
|
export declare function mapCaptureCommand(args: string[]): Promise<void>;
|
|
3
4
|
export type MapCaptureOptions = {
|
|
4
5
|
inputDir: string | undefined;
|
|
5
6
|
upload: boolean | undefined;
|
|
6
7
|
dryRun: boolean | undefined;
|
|
7
|
-
|
|
8
|
+
credential: UploadCredential | undefined;
|
|
8
9
|
projectId: string | undefined;
|
|
9
10
|
baseUrl: string | undefined;
|
|
10
11
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map-capture.d.ts","sourceRoot":"","sources":["../../src/commands/map-capture.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"map-capture.d.ts","sourceRoot":"","sources":["../../src/commands/map-capture.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,gBAAgB,EAAoB,MAAM,oBAAoB,CAAC;AAqC7E,oFAAoF;AACpF,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCrE;AA4BD,MAAM,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,UAAU,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACzC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAsB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAkJnF"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { readdir, readFile, realpath, stat } from "node:fs/promises";
|
|
2
2
|
import { extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
3
3
|
import { parseArgs } from "node:util";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveCredential } from "../lib/config.js";
|
|
5
|
+
import { getSharedOAuthManager } from "../lib/create-client.js";
|
|
5
6
|
import { error, log, success } from "../lib/logger.js";
|
|
6
7
|
import { mapCaptureMetadataSchema } from "../lib/metadata.js";
|
|
7
8
|
import { uploadMapCapture } from "../lib/uploader.js";
|
|
@@ -18,10 +19,13 @@ Required:
|
|
|
18
19
|
|
|
19
20
|
Upload options (all required together):
|
|
20
21
|
--upload Enable upload to Framedash API
|
|
21
|
-
--api-key <key>
|
|
22
|
-
--api-key-file: a key passed
|
|
23
|
-
in the process list and shell
|
|
24
|
-
|
|
22
|
+
--api-key <key> API key (needs the resources:write scope). Prefer
|
|
23
|
+
FRAMEDASH_API_KEY env or --api-key-file: a key passed
|
|
24
|
+
as --api-key is visible in the process list and shell
|
|
25
|
+
history. Without any API key, a stored browser login
|
|
26
|
+
('framedash login --scopes "analytics:read
|
|
27
|
+
resources:write"') is used.
|
|
28
|
+
--api-key-file <path> Read the API key from a file ('-' for stdin)
|
|
25
29
|
--project-id <uuid> Target project ID, or set FRAMEDASH_PROJECT_ID env
|
|
26
30
|
|
|
27
31
|
Optional:
|
|
@@ -55,22 +59,47 @@ export async function mapCaptureCommand(args) {
|
|
|
55
59
|
log(MAP_CAPTURE_HELP);
|
|
56
60
|
return;
|
|
57
61
|
}
|
|
58
|
-
// Resolve
|
|
62
|
+
// Resolve credentials only when an upload will actually run, so a validation
|
|
59
63
|
// dry run with --api-key-file - does not block on stdin (or fail on a missing
|
|
60
|
-
// file) for a
|
|
64
|
+
// file) for a credential it never uses.
|
|
61
65
|
const willUpload = Boolean(values.upload) && !values["dry-run"];
|
|
66
|
+
const baseUrl = values["base-url"] ?? "https://app.framedash.dev";
|
|
62
67
|
const result = await mapCapture({
|
|
63
68
|
inputDir: values["input-dir"],
|
|
64
69
|
upload: values.upload,
|
|
65
70
|
dryRun: values["dry-run"],
|
|
66
|
-
|
|
71
|
+
credential: willUpload ? resolveUploadCredential(values, baseUrl) : undefined,
|
|
67
72
|
projectId: values["project-id"] ?? process.env.FRAMEDASH_PROJECT_ID,
|
|
68
|
-
baseUrl
|
|
73
|
+
baseUrl,
|
|
69
74
|
});
|
|
70
75
|
if (!result.ok) {
|
|
71
76
|
process.exit(1);
|
|
72
77
|
}
|
|
73
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Map the CLI-wide credential resolution (api-key flag/file/env > stored
|
|
81
|
+
* OAuth login) onto the uploader's credential shape. OAuth rides on the
|
|
82
|
+
* process-shared token manager so uploads participate in the same
|
|
83
|
+
* refresh-rotation state as every other client.
|
|
84
|
+
*/
|
|
85
|
+
function resolveUploadCredential(values, baseUrl) {
|
|
86
|
+
let resolved;
|
|
87
|
+
try {
|
|
88
|
+
resolved = resolveCredential(values, baseUrl);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
// resolveCredential parses the base URL; map-capture does not pre-validate
|
|
92
|
+
// --base-url, so surface a clean CLI error instead of an uncaught throw.
|
|
93
|
+
error(`Invalid --base-url: ${err instanceof Error ? err.message : String(err)}`);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
if (!resolved)
|
|
97
|
+
return undefined;
|
|
98
|
+
if (resolved.kind === "api-key") {
|
|
99
|
+
return { kind: "api-key", apiKey: resolved.apiKey };
|
|
100
|
+
}
|
|
101
|
+
return { kind: "oauth", manager: getSharedOAuthManager(baseUrl, resolved) };
|
|
102
|
+
}
|
|
74
103
|
export async function mapCapture(opts) {
|
|
75
104
|
const fail = { ok: false, successCount: 0, errorCount: 0 };
|
|
76
105
|
if (!opts.inputDir) {
|
|
@@ -80,8 +109,9 @@ export async function mapCapture(opts) {
|
|
|
80
109
|
const upload = Boolean(opts.upload);
|
|
81
110
|
const dryRun = Boolean(opts.dryRun);
|
|
82
111
|
if (upload && !dryRun) {
|
|
83
|
-
if (!opts.
|
|
84
|
-
error("--api-key
|
|
112
|
+
if (!opts.credential) {
|
|
113
|
+
error("--api-key, --api-key-file, FRAMEDASH_API_KEY, or a stored 'framedash login' " +
|
|
114
|
+
"is required with --upload");
|
|
85
115
|
return fail;
|
|
86
116
|
}
|
|
87
117
|
if (!opts.projectId) {
|
|
@@ -176,7 +206,7 @@ export async function mapCapture(opts) {
|
|
|
176
206
|
const uploadResult = await uploadMapCapture({
|
|
177
207
|
metadata,
|
|
178
208
|
imagePath,
|
|
179
|
-
|
|
209
|
+
credential: opts.credential,
|
|
180
210
|
projectId: opts.projectId,
|
|
181
211
|
baseUrl: opts.baseUrl ?? "https://app.framedash.dev",
|
|
182
212
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map-capture.js","sourceRoot":"","sources":["../../src/commands/map-capture.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"map-capture.js","sourceRoot":"","sources":["../../src/commands/map-capture.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"perf-diff.d.ts","sourceRoot":"","sources":["../../src/commands/perf-diff.ts"],"names":[],"mappings":"AAYA,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4G5D"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { buildBuildComparePath } from "@framedash/api-client";
|
|
2
|
+
import { formatOutput } from "../lib/formatters.js";
|
|
3
|
+
import { error, log, success } from "../lib/logger.js";
|
|
4
|
+
import { evaluateRegression, formatMetricDiff, isRegressionMetric, } from "../lib/perf-diff-eval.js";
|
|
5
|
+
import { runCommand } from "../lib/run-command.js";
|
|
6
|
+
export async function perfDiff(args) {
|
|
7
|
+
await runCommand({
|
|
8
|
+
args,
|
|
9
|
+
help: HELP,
|
|
10
|
+
options: {
|
|
11
|
+
baseline: { type: "string" },
|
|
12
|
+
candidate: { type: "string" },
|
|
13
|
+
metric: { type: "string" },
|
|
14
|
+
days: { type: "string" },
|
|
15
|
+
map: { type: "string" },
|
|
16
|
+
platform: { type: "string" },
|
|
17
|
+
threshold: { type: "string" },
|
|
18
|
+
"fail-on-regression": { type: "boolean" },
|
|
19
|
+
},
|
|
20
|
+
}, async ({ client, config, values }) => {
|
|
21
|
+
// Trim so the local equality/required checks match the server (the route
|
|
22
|
+
// trims too) and a stray-whitespace build id does not waste an API round-trip.
|
|
23
|
+
const baseline = values.baseline?.trim();
|
|
24
|
+
const candidate = values.candidate?.trim();
|
|
25
|
+
if (!baseline || !candidate) {
|
|
26
|
+
error("--baseline and --candidate are required (build IDs; see 'framedash builds')");
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
// A build compared against itself is a zero diff that would pass the gate;
|
|
30
|
+
// fail fast on a misconfigured CI (e.g. BASE_SHA == GITHUB_SHA).
|
|
31
|
+
if (baseline === candidate) {
|
|
32
|
+
error("--baseline and --candidate must be different build IDs");
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
let metric;
|
|
36
|
+
if (values.metric !== undefined) {
|
|
37
|
+
const raw = values.metric.trim();
|
|
38
|
+
if (!isRegressionMetric(raw)) {
|
|
39
|
+
error(`Invalid --metric '${raw}'. Allowed: frame_time, memory, gpu_time`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
metric = raw;
|
|
43
|
+
}
|
|
44
|
+
let thresholdPct = 0;
|
|
45
|
+
if (values.threshold !== undefined) {
|
|
46
|
+
thresholdPct = Number(values.threshold);
|
|
47
|
+
if (!Number.isFinite(thresholdPct) || thresholdPct < 0) {
|
|
48
|
+
error("--threshold must be a non-negative number (percent)");
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const comparison = await client.get(client.projectPath(buildBuildComparePath({
|
|
53
|
+
baseline,
|
|
54
|
+
candidate,
|
|
55
|
+
days: values.days,
|
|
56
|
+
mapId: values.map,
|
|
57
|
+
platform: values.platform,
|
|
58
|
+
})));
|
|
59
|
+
// A non-error 2xx with a malformed body must not crash the gate with a raw
|
|
60
|
+
// TypeError; fail closed with a clear message instead.
|
|
61
|
+
if (!comparison || !Array.isArray(comparison.diffs)) {
|
|
62
|
+
error("Unexpected response from the builds/compare API (no comparison data).");
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
// Always print the comparison so CI logs carry the numbers. JSON gets the
|
|
66
|
+
// full object (baseline/candidate stats + diffs); table/csv get the diff rows.
|
|
67
|
+
if (config.format === "json") {
|
|
68
|
+
log(formatOutput(comparison, "json"));
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
log(formatOutput(comparison.diffs, config.format));
|
|
72
|
+
}
|
|
73
|
+
if (!values["fail-on-regression"])
|
|
74
|
+
return;
|
|
75
|
+
const verdict = evaluateRegression(comparison, { metric, thresholdPct });
|
|
76
|
+
// Fail closed: if --fail-on-regression was requested but nothing was
|
|
77
|
+
// comparable (wrong build IDs, or the chosen metric has no data on the
|
|
78
|
+
// platform), do not let the build pass an unmeasured gate.
|
|
79
|
+
if (verdict.evaluated.length === 0) {
|
|
80
|
+
error(metric
|
|
81
|
+
? `No comparable '${metric}' data between these builds; cannot evaluate a regression.`
|
|
82
|
+
: "No comparable performance data between these builds; cannot evaluate a regression.");
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
if (verdict.failed) {
|
|
86
|
+
error(`Performance regression detected (threshold ${thresholdPct}%): ${verdict.offenders
|
|
87
|
+
.map(formatMetricDiff)
|
|
88
|
+
.join("; ")}`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
success(`No performance regression beyond ${thresholdPct}% (${verdict.evaluated.length} metric(s) checked).`);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
const HELP = `Usage: framedash perf-diff --baseline <id> --candidate <id> [options]
|
|
95
|
+
|
|
96
|
+
Compare two builds' performance (P50/P95 frame time, memory, GPU time) and,
|
|
97
|
+
with --fail-on-regression, exit non-zero when the candidate regressed -- so a CI
|
|
98
|
+
job can gate a merge on a build-over-build performance regression. Build IDs are
|
|
99
|
+
whatever your SDK reported as build_id (set it from CI, e.g. the git SHA); list
|
|
100
|
+
them with 'framedash builds'.
|
|
101
|
+
|
|
102
|
+
Required:
|
|
103
|
+
--baseline <id> Known-good build_id to compare against
|
|
104
|
+
--candidate <id> New build_id under test
|
|
105
|
+
|
|
106
|
+
Options:
|
|
107
|
+
--metric <name> Gate on one metric only: frame_time, memory, gpu_time
|
|
108
|
+
(default: all). Lower is better; a positive % is a regression.
|
|
109
|
+
--threshold <pct> Tolerate a regression up to this percent (default: 0 =
|
|
110
|
+
any worsening fails). e.g. --threshold 5 ignores <=5% noise.
|
|
111
|
+
--fail-on-regression Exit 1 if a regression beyond the threshold is found
|
|
112
|
+
(otherwise perf-diff only reports and exits 0)
|
|
113
|
+
--days <n> Time period in days: 7, 14, 30, 90 (default: 30)
|
|
114
|
+
--map <id> Restrict the comparison to one map
|
|
115
|
+
--platform <name> Restrict the comparison to one platform
|
|
116
|
+
--api-key <key> API key (or FRAMEDASH_API_KEY env)
|
|
117
|
+
--project-id <uuid> Project ID (or FRAMEDASH_PROJECT_ID env)
|
|
118
|
+
--base-url <url> API base URL (default: https://app.framedash.dev)
|
|
119
|
+
--format <fmt> Output format: json, table, csv (default: json)
|
|
120
|
+
-h, --help Show help
|
|
121
|
+
|
|
122
|
+
Example (GitHub Actions gate):
|
|
123
|
+
framedash perf-diff --baseline "$BASE_SHA" --candidate "$GITHUB_SHA" \\
|
|
124
|
+
--threshold 5 --fail-on-regression`;
|
|
125
|
+
//# sourceMappingURL=perf-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"perf-diff.js","sourceRoot":"","sources":["../../src/commands/perf-diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/commands/query.ts"],"names":[],"mappings":"AAMA,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/commands/query.ts"],"names":[],"mappings":"AAMA,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyDzD"}
|
package/dist/commands/query.js
CHANGED
|
@@ -13,6 +13,15 @@ export async function query(args) {
|
|
|
13
13
|
},
|
|
14
14
|
allowPositionals: true,
|
|
15
15
|
}, async ({ client, config, values, positionals }) => {
|
|
16
|
+
// The raw-query endpoint requires the data:admin scope, which OAuth
|
|
17
|
+
// grants can never carry (OAUTH_ALLOWED_SCOPES is deliberately limited
|
|
18
|
+
// to analytics:read + resources:write). Falling back to a stored login
|
|
19
|
+
// would always 403, so fail early with the actionable fix instead.
|
|
20
|
+
if (config.credential.kind === "oauth") {
|
|
21
|
+
error("framedash query requires an API key with the data:admin scope. OAuth login " +
|
|
22
|
+
"cannot grant data:admin; set FRAMEDASH_API_KEY or use --api-key / --api-key-file.");
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
16
25
|
if (values.file && positionals.length > 0) {
|
|
17
26
|
error("Cannot use both --file and a positional SQL argument. Provide one or the other.");
|
|
18
27
|
process.exit(1);
|
|
@@ -51,6 +60,9 @@ const HELP = `Usage: framedash query <sql> [options]
|
|
|
51
60
|
|
|
52
61
|
Execute a read-only ClickHouse query.
|
|
53
62
|
|
|
63
|
+
Requires an API key with the data:admin scope ('framedash login' OAuth
|
|
64
|
+
tokens cannot be used: data:admin is not grantable via OAuth).
|
|
65
|
+
|
|
54
66
|
Arguments:
|
|
55
67
|
<sql> SQL query string
|
|
56
68
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/commands/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,IAAc;IACzC,MAAM,UAAU,CACf;QACC,IAAI;QACJ,IAAI,EAAE,IAAI;QACV,OAAO,EAAE;YACR,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YACzB,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;SACpC;QACD,gBAAgB,EAAE,IAAI;KACtB,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE;QACjD,IAAI,MAAM,CAAC,IAAI,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3C,KAAK,CAAC,iFAAiF,CAAC,CAAC;YACzF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;QAED,IAAI,GAAW,CAAC;QAChB,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YACjB,IAAI,CAAC;gBACJ,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,IAAc,EAAE,OAAO,CAAC,CAAC;YACtD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;gBACjE,KAAK,CAAC,4BAA4B,MAAM,CAAC,IAAI,KAAK,GAAG,GAAG,CAAC,CAAC;gBAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACjB,CAAC;QACF,CAAC;aAAM,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACP,KAAK,CAAC,2DAA2D,CAAC,CAAC;YACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;QAED,MAAM,IAAI,GAA4B;YACrC,GAAG;YACH,UAAU,EAAE,MAAM,CAAC,SAAS;SAC5B,CAAC;QACF,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAClB,IAAI,CAAC,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,KAAe,EAAE,OAAO,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;QACtD,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACxC,CAAC,CACD,CAAC;AACH,CAAC;AAED,MAAM,IAAI,GAAG
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/commands/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,IAAc;IACzC,MAAM,UAAU,CACf;QACC,IAAI;QACJ,IAAI,EAAE,IAAI;QACV,OAAO,EAAE;YACR,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YACzB,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;SACpC;QACD,gBAAgB,EAAE,IAAI;KACtB,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE;QACjD,oEAAoE;QACpE,uEAAuE;QACvE,uEAAuE;QACvE,mEAAmE;QACnE,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACxC,KAAK,CACJ,6EAA6E;gBAC5E,mFAAmF,CACpF,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3C,KAAK,CAAC,iFAAiF,CAAC,CAAC;YACzF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;QAED,IAAI,GAAW,CAAC;QAChB,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YACjB,IAAI,CAAC;gBACJ,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,IAAc,EAAE,OAAO,CAAC,CAAC;YACtD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;gBACjE,KAAK,CAAC,4BAA4B,MAAM,CAAC,IAAI,KAAK,GAAG,GAAG,CAAC,CAAC;gBAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACjB,CAAC;QACF,CAAC;aAAM,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACP,KAAK,CAAC,2DAA2D,CAAC,CAAC;YACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;QAED,MAAM,IAAI,GAA4B;YACrC,GAAG;YACH,UAAU,EAAE,MAAM,CAAC,SAAS;SAC5B,CAAC;QACF,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAClB,IAAI,CAAC,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,KAAe,EAAE,OAAO,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;QACtD,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACxC,CAAC,CACD,CAAC;AACH,CAAC;AAED,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;uDAuB0C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../../src/commands/retention.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../../src/commands/retention.ts"],"names":[],"mappings":"AAKA,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAU7D"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { buildRetentionPath } from "@framedash/api-client";
|
|
1
2
|
import { formatOutput } from "../lib/formatters.js";
|
|
2
3
|
import { log } from "../lib/logger.js";
|
|
3
4
|
import { runCommand } from "../lib/run-command.js";
|
|
4
5
|
export async function retention(args) {
|
|
5
6
|
await runCommand({ args, help: HELP, options: { days: { type: "string" } } }, async ({ client, config, values }) => {
|
|
6
|
-
const
|
|
7
|
-
const data = await client.get(client.projectPath(`retention?${params}`));
|
|
7
|
+
const data = await client.get(client.projectPath(buildRetentionPath({ days: values.days ?? "30" })));
|
|
8
8
|
log(formatOutput(data, config.format));
|
|
9
9
|
});
|
|
10
10
|
}
|
|
@@ -13,7 +13,7 @@ const HELP = `Usage: framedash retention [options]
|
|
|
13
13
|
Show player retention cohorts.
|
|
14
14
|
|
|
15
15
|
Options:
|
|
16
|
-
--days <n> Time period in days:
|
|
16
|
+
--days <n> Time period in days: 7, 14, 30, 90 (default: 30)
|
|
17
17
|
--api-key <key> API key (or FRAMEDASH_API_KEY env)
|
|
18
18
|
--project-id <uuid> Project ID (or FRAMEDASH_PROJECT_ID env)
|
|
19
19
|
--base-url <url> API base URL (default: https://app.framedash.dev)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retention.js","sourceRoot":"","sources":["../../src/commands/retention.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAc;IAC7C,MAAM,UAAU,CACf,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,EAC3D,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;QACpC,MAAM,
|
|
1
|
+
{"version":3,"file":"retention.js","sourceRoot":"","sources":["../../src/commands/retention.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAc;IAC7C,MAAM,UAAU,CACf,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,EAC3D,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;QACpC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAC5B,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAG,MAAM,CAAC,IAAe,IAAI,IAAI,EAAE,CAAC,CAAC,CACjF,CAAC;QACF,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACxC,CAAC,CACD,CAAC;AACH,CAAC;AAED,MAAM,IAAI,GAAG;;;;;;;;;;mCAUsB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turnkey CI profiling gate: export the FRAMEDASH_* session contract, launch the
|
|
3
|
+
* configured game/profiling command, wait for its perf data to ingest, then run
|
|
4
|
+
* the perf-diff regression gate against a baseline build.
|
|
5
|
+
*/
|
|
6
|
+
export declare function runProfileTest(args: string[]): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=run-profile-test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-profile-test.d.ts","sourceRoot":"","sources":["../../src/commands/run-profile-test.ts"],"names":[],"mappings":"AAiaA;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsJlE"}
|