@framedash/cli 0.1.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/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/commands/alerts.d.ts +2 -0
- package/dist/commands/alerts.d.ts.map +1 -0
- package/dist/commands/alerts.js +171 -0
- package/dist/commands/alerts.js.map +1 -0
- package/dist/commands/auth.d.ts +2 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +20 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/content.d.ts +2 -0
- package/dist/commands/content.d.ts.map +1 -0
- package/dist/commands/content.js +104 -0
- package/dist/commands/content.js.map +1 -0
- package/dist/commands/dashboard.d.ts +2 -0
- package/dist/commands/dashboard.d.ts.map +1 -0
- package/dist/commands/dashboard.js +22 -0
- package/dist/commands/dashboard.js.map +1 -0
- package/dist/commands/funnel.d.ts +2 -0
- package/dist/commands/funnel.d.ts.map +1 -0
- package/dist/commands/funnel.js +43 -0
- package/dist/commands/funnel.js.map +1 -0
- package/dist/commands/map-capture.d.ts +17 -0
- package/dist/commands/map-capture.d.ts.map +1 -0
- package/dist/commands/map-capture.js +200 -0
- package/dist/commands/map-capture.js.map +1 -0
- package/dist/commands/maps.d.ts +2 -0
- package/dist/commands/maps.d.ts.map +1 -0
- package/dist/commands/maps.js +38 -0
- package/dist/commands/maps.js.map +1 -0
- package/dist/commands/query.d.ts +2 -0
- package/dist/commands/query.d.ts.map +1 -0
- package/dist/commands/query.js +70 -0
- package/dist/commands/query.js.map +1 -0
- package/dist/commands/retention.d.ts +2 -0
- package/dist/commands/retention.d.ts.map +1 -0
- package/dist/commands/retention.js +22 -0
- package/dist/commands/retention.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +20 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +47 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +114 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/create-client.d.ts +3 -0
- package/dist/lib/create-client.d.ts.map +1 -0
- package/dist/lib/create-client.js +30 -0
- package/dist/lib/create-client.js.map +1 -0
- package/dist/lib/formatters.d.ts +4 -0
- package/dist/lib/formatters.d.ts.map +1 -0
- package/dist/lib/formatters.js +71 -0
- package/dist/lib/formatters.js.map +1 -0
- package/dist/lib/logger.d.ts +9 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +15 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/metadata.d.ts +36 -0
- package/dist/lib/metadata.d.ts.map +1 -0
- package/dist/lib/metadata.js +40 -0
- package/dist/lib/metadata.js.map +1 -0
- package/dist/lib/run-command.d.ts +28 -0
- package/dist/lib/run-command.d.ts.map +1 -0
- package/dist/lib/run-command.js +53 -0
- package/dist/lib/run-command.js.map +1 -0
- package/dist/lib/uploader.d.ts +19 -0
- package/dist/lib/uploader.d.ts.map +1 -0
- package/dist/lib/uploader.js +61 -0
- package/dist/lib/uploader.js.map +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { readdir, readFile, realpath, stat } from "node:fs/promises";
|
|
2
|
+
import { extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
3
|
+
import { parseArgs } from "node:util";
|
|
4
|
+
import { resolveApiKey } from "../lib/config.js";
|
|
5
|
+
import { error, log, success } from "../lib/logger.js";
|
|
6
|
+
import { mapCaptureMetadataSchema } from "../lib/metadata.js";
|
|
7
|
+
import { uploadMapCapture } from "../lib/uploader.js";
|
|
8
|
+
const ALLOWED_IMAGE_EXTS = new Set([".png", ".jpg", ".jpeg", ".webp"]);
|
|
9
|
+
const MAP_CAPTURE_HELP = `Usage: framedash map-capture [options]
|
|
10
|
+
|
|
11
|
+
Upload captured map images and metadata to Framedash SaaS.
|
|
12
|
+
|
|
13
|
+
Reads JSON sidecar metadata files from --input-dir, validates them,
|
|
14
|
+
and optionally uploads the associated images to the Framedash API.
|
|
15
|
+
|
|
16
|
+
Required:
|
|
17
|
+
--input-dir <path> Directory containing JSON metadata files and images
|
|
18
|
+
|
|
19
|
+
Upload options (all required together):
|
|
20
|
+
--upload Enable upload to Framedash API
|
|
21
|
+
--api-key <key> Admin API key. Prefer FRAMEDASH_API_KEY env or
|
|
22
|
+
--api-key-file: a key passed as --api-key is visible
|
|
23
|
+
in the process list and shell history.
|
|
24
|
+
--api-key-file <path> Read the admin API key from a file ('-' for stdin)
|
|
25
|
+
--project-id <uuid> Target project ID, or set FRAMEDASH_PROJECT_ID env
|
|
26
|
+
|
|
27
|
+
Optional:
|
|
28
|
+
--base-url <url> API base URL (default: https://app.framedash.dev)
|
|
29
|
+
--dry-run Validate files without uploading
|
|
30
|
+
|
|
31
|
+
Examples:
|
|
32
|
+
# Validate metadata files only
|
|
33
|
+
framedash map-capture --input-dir ./captures --dry-run
|
|
34
|
+
|
|
35
|
+
# Upload to Framedash (key from env, not the command line)
|
|
36
|
+
FRAMEDASH_API_KEY=... FRAMEDASH_PROJECT_ID=... \\
|
|
37
|
+
framedash map-capture --input-dir ./captures --upload`;
|
|
38
|
+
/** CLI entry point for map-capture — parses args then delegates to mapCapture(). */
|
|
39
|
+
export async function mapCaptureCommand(args) {
|
|
40
|
+
const { values } = parseArgs({
|
|
41
|
+
args,
|
|
42
|
+
options: {
|
|
43
|
+
"input-dir": { type: "string" },
|
|
44
|
+
"api-key": { type: "string" },
|
|
45
|
+
"api-key-file": { type: "string" },
|
|
46
|
+
"project-id": { type: "string" },
|
|
47
|
+
"base-url": { type: "string", default: "https://app.framedash.dev" },
|
|
48
|
+
upload: { type: "boolean", default: false },
|
|
49
|
+
"dry-run": { type: "boolean", default: false },
|
|
50
|
+
help: { type: "boolean", short: "h", default: false },
|
|
51
|
+
},
|
|
52
|
+
allowPositionals: false,
|
|
53
|
+
});
|
|
54
|
+
if (values.help) {
|
|
55
|
+
log(MAP_CAPTURE_HELP);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
// Resolve the API key only when an upload will actually run, so a validation
|
|
59
|
+
// dry run with --api-key-file - does not block on stdin (or fail on a missing
|
|
60
|
+
// file) for a key it never uses.
|
|
61
|
+
const willUpload = Boolean(values.upload) && !values["dry-run"];
|
|
62
|
+
const result = await mapCapture({
|
|
63
|
+
inputDir: values["input-dir"],
|
|
64
|
+
upload: values.upload,
|
|
65
|
+
dryRun: values["dry-run"],
|
|
66
|
+
apiKey: willUpload ? resolveApiKey(values) : undefined,
|
|
67
|
+
projectId: values["project-id"] ?? process.env.FRAMEDASH_PROJECT_ID,
|
|
68
|
+
baseUrl: values["base-url"] ?? "https://app.framedash.dev",
|
|
69
|
+
});
|
|
70
|
+
if (!result.ok) {
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
export async function mapCapture(opts) {
|
|
75
|
+
const fail = { ok: false, successCount: 0, errorCount: 0 };
|
|
76
|
+
if (!opts.inputDir) {
|
|
77
|
+
error("--input-dir is required");
|
|
78
|
+
return fail;
|
|
79
|
+
}
|
|
80
|
+
const upload = Boolean(opts.upload);
|
|
81
|
+
const dryRun = Boolean(opts.dryRun);
|
|
82
|
+
if (upload && !dryRun) {
|
|
83
|
+
if (!opts.apiKey) {
|
|
84
|
+
error("--api-key (or FRAMEDASH_API_KEY env) is required with --upload");
|
|
85
|
+
return fail;
|
|
86
|
+
}
|
|
87
|
+
if (!opts.projectId) {
|
|
88
|
+
error("--project-id (or FRAMEDASH_PROJECT_ID env) is required with --upload");
|
|
89
|
+
return fail;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const resolvedDir = resolve(opts.inputDir);
|
|
93
|
+
let dirStat;
|
|
94
|
+
try {
|
|
95
|
+
dirStat = await stat(resolvedDir);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
error(`Input directory not found: ${resolvedDir}`);
|
|
99
|
+
return fail;
|
|
100
|
+
}
|
|
101
|
+
if (!dirStat.isDirectory()) {
|
|
102
|
+
error(`Not a directory: ${resolvedDir}`);
|
|
103
|
+
return fail;
|
|
104
|
+
}
|
|
105
|
+
const files = await readdir(resolvedDir);
|
|
106
|
+
const jsonFiles = files.filter((f) => f.endsWith(".json"));
|
|
107
|
+
if (jsonFiles.length === 0) {
|
|
108
|
+
error(`No JSON metadata files found in ${resolvedDir}`);
|
|
109
|
+
return fail;
|
|
110
|
+
}
|
|
111
|
+
log(`Found ${jsonFiles.length} metadata file(s) in ${resolvedDir}`);
|
|
112
|
+
const realInputDir = await realpath(resolvedDir);
|
|
113
|
+
let successCount = 0;
|
|
114
|
+
let errorCount = 0;
|
|
115
|
+
for (const jsonFile of jsonFiles) {
|
|
116
|
+
const jsonPath = join(resolvedDir, jsonFile);
|
|
117
|
+
try {
|
|
118
|
+
const raw = await readFile(jsonPath, "utf-8");
|
|
119
|
+
let parsed;
|
|
120
|
+
try {
|
|
121
|
+
parsed = JSON.parse(raw);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
error(`${jsonFile}: Invalid JSON`);
|
|
125
|
+
errorCount++;
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const result = mapCaptureMetadataSchema.safeParse(parsed);
|
|
129
|
+
if (!result.success) {
|
|
130
|
+
const issues = result.error.issues.map((i) => i.message).join("; ");
|
|
131
|
+
error(`${jsonFile}: Invalid metadata \u2014 ${issues}`);
|
|
132
|
+
errorCount++;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const metadata = result.data;
|
|
136
|
+
// Verify image file exists and is within input directory
|
|
137
|
+
if (isAbsolute(metadata.image_path)) {
|
|
138
|
+
error(`${jsonFile}: Absolute image paths are not allowed: ${metadata.image_path}`);
|
|
139
|
+
errorCount++;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const imagePath = await realpath(resolve(resolvedDir, metadata.image_path)).catch(() => null);
|
|
143
|
+
if (!imagePath) {
|
|
144
|
+
error(`${jsonFile}: Image not found: ${metadata.image_path}`);
|
|
145
|
+
errorCount++;
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
const rel = relative(realInputDir, imagePath);
|
|
149
|
+
if (rel.startsWith("..") || isAbsolute(rel)) {
|
|
150
|
+
error(`${jsonFile}: Image path escapes input directory: ${metadata.image_path}`);
|
|
151
|
+
errorCount++;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const imgStat = await stat(imagePath);
|
|
155
|
+
if (!imgStat.isFile()) {
|
|
156
|
+
error(`${jsonFile}: Image path is not a file: ${metadata.image_path}`);
|
|
157
|
+
errorCount++;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
const imgExt = extname(imagePath).toLowerCase();
|
|
161
|
+
if (!ALLOWED_IMAGE_EXTS.has(imgExt)) {
|
|
162
|
+
error(`${jsonFile}: Unsupported image format: ${imgExt}`);
|
|
163
|
+
errorCount++;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (dryRun) {
|
|
167
|
+
success(`${jsonFile}: map_id=${metadata.map_id}, ` +
|
|
168
|
+
`image=${metadata.image_path}, ` +
|
|
169
|
+
`bounds=[${metadata.world_bounds.min.x},${metadata.world_bounds.min.y}]` +
|
|
170
|
+
`→[${metadata.world_bounds.max.x},${metadata.world_bounds.max.y}], ` +
|
|
171
|
+
`size=${metadata.image_dimensions.width}x${metadata.image_dimensions.height}`);
|
|
172
|
+
successCount++;
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (upload) {
|
|
176
|
+
const uploadResult = await uploadMapCapture({
|
|
177
|
+
metadata,
|
|
178
|
+
imagePath,
|
|
179
|
+
apiKey: opts.apiKey,
|
|
180
|
+
projectId: opts.projectId,
|
|
181
|
+
baseUrl: opts.baseUrl ?? "https://app.framedash.dev",
|
|
182
|
+
});
|
|
183
|
+
success(`${metadata.map_id}: ${uploadResult.action} ` +
|
|
184
|
+
`(${metadata.image_dimensions.width}x${metadata.image_dimensions.height})`);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
success(`${jsonFile}: Valid (map_id=${metadata.map_id})`);
|
|
188
|
+
}
|
|
189
|
+
successCount++;
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
error(`${jsonFile}: ${err instanceof Error ? err.message : String(err)}`);
|
|
193
|
+
errorCount++;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
log("");
|
|
197
|
+
log(`Done: ${successCount} succeeded, ${errorCount} failed`);
|
|
198
|
+
return { ok: errorCount === 0, successCount, errorCount };
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=map-capture.js.map
|
|
@@ -0,0 +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,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAEvE,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;wDA4B+B,CAAC;AAEzD,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAc;IACrD,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;QAC5B,IAAI;QACJ,OAAO,EAAE;YACR,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC/B,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC7B,cAAc,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAClC,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAChC,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,EAAE;YACpE,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;YAC3C,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;YAC9C,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE;SACrD;QACD,gBAAgB,EAAE,KAAK;KACvB,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QACjB,GAAG,CAAC,gBAAgB,CAAC,CAAC;QACtB,OAAO;IACR,CAAC;IAED,6EAA6E;IAC7E,8EAA8E;IAC9E,iCAAiC;IACjC,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;QAC/B,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC;QAC7B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC;QACzB,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;QACtD,SAAS,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB;QACnE,OAAO,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,2BAA2B;KAC1D,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;AACF,CAAC;AAiBD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAuB;IACvD,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAW,CAAC;IAEpE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACpB,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEpC,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAClB,KAAK,CAAC,gEAAgE,CAAC,CAAC;YACxE,OAAO,IAAI,CAAC;QACb,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACrB,KAAK,CAAC,sEAAsE,CAAC,CAAC;YAC9E,OAAO,IAAI,CAAC;QACb,CAAC;IACF,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAE3C,IAAI,OAAc,CAAC;IACnB,IAAI,CAAC;QACJ,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACR,KAAK,CAAC,8BAA8B,WAAW,EAAE,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC;IACb,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;QAC5B,KAAK,CAAC,oBAAoB,WAAW,EAAE,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAE3D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,KAAK,CAAC,mCAAmC,WAAW,EAAE,CAAC,CAAC;QACxD,OAAO,IAAI,CAAC;IACb,CAAC;IAED,GAAG,CAAC,SAAS,SAAS,CAAC,MAAM,wBAAwB,WAAW,EAAE,CAAC,CAAC;IAEpE,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,CAAC;IACjD,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC7C,IAAI,CAAC;YACJ,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC9C,IAAI,MAAe,CAAC;YACpB,IAAI,CAAC;gBACJ,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1B,CAAC;YAAC,MAAM,CAAC;gBACR,KAAK,CAAC,GAAG,QAAQ,gBAAgB,CAAC,CAAC;gBACnC,UAAU,EAAE,CAAC;gBACb,SAAS;YACV,CAAC;YAED,MAAM,MAAM,GAAG,wBAAwB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YAC1D,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACrB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACpE,KAAK,CAAC,GAAG,QAAQ,6BAA6B,MAAM,EAAE,CAAC,CAAC;gBACxD,UAAU,EAAE,CAAC;gBACb,SAAS;YACV,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC;YAE7B,yDAAyD;YACzD,IAAI,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBACrC,KAAK,CAAC,GAAG,QAAQ,2CAA2C,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;gBACnF,UAAU,EAAE,CAAC;gBACb,SAAS;YACV,CAAC;YACD,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;YAC9F,IAAI,CAAC,SAAS,EAAE,CAAC;gBAChB,KAAK,CAAC,GAAG,QAAQ,sBAAsB,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;gBAC9D,UAAU,EAAE,CAAC;gBACb,SAAS;YACV,CAAC;YACD,MAAM,GAAG,GAAG,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;YAC9C,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7C,KAAK,CAAC,GAAG,QAAQ,yCAAyC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;gBACjF,UAAU,EAAE,CAAC;gBACb,SAAS;YACV,CAAC;YACD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC;YACtC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;gBACvB,KAAK,CAAC,GAAG,QAAQ,+BAA+B,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;gBACvE,UAAU,EAAE,CAAC;gBACb,SAAS;YACV,CAAC;YAED,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;YAChD,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACrC,KAAK,CAAC,GAAG,QAAQ,+BAA+B,MAAM,EAAE,CAAC,CAAC;gBAC1D,UAAU,EAAE,CAAC;gBACb,SAAS;YACV,CAAC;YAED,IAAI,MAAM,EAAE,CAAC;gBACZ,OAAO,CACN,GAAG,QAAQ,YAAY,QAAQ,CAAC,MAAM,IAAI;oBACzC,SAAS,QAAQ,CAAC,UAAU,IAAI;oBAChC,WAAW,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG;oBACxE,KAAK,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK;oBACpE,QAAQ,QAAQ,CAAC,gBAAgB,CAAC,KAAK,IAAI,QAAQ,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAC9E,CAAC;gBACF,YAAY,EAAE,CAAC;gBACf,SAAS;YACV,CAAC;YAED,IAAI,MAAM,EAAE,CAAC;gBACZ,MAAM,YAAY,GAAG,MAAM,gBAAgB,CAAC;oBAC3C,QAAQ;oBACR,SAAS;oBACT,MAAM,EAAE,IAAI,CAAC,MAAgB;oBAC7B,SAAS,EAAE,IAAI,CAAC,SAAmB;oBACnC,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,2BAA2B;iBACpD,CAAC,CAAC;gBACH,OAAO,CACN,GAAG,QAAQ,CAAC,MAAM,KAAK,YAAY,CAAC,MAAM,GAAG;oBAC5C,IAAI,QAAQ,CAAC,gBAAgB,CAAC,KAAK,IAAI,QAAQ,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAC3E,CAAC;YACH,CAAC;iBAAM,CAAC;gBACP,OAAO,CAAC,GAAG,QAAQ,mBAAmB,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;YAC3D,CAAC;YAED,YAAY,EAAE,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,KAAK,CAAC,GAAG,QAAQ,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC1E,UAAU,EAAE,CAAC;QACd,CAAC;IACF,CAAC;IAED,GAAG,CAAC,EAAE,CAAC,CAAC;IACR,GAAG,CAAC,SAAS,YAAY,eAAe,UAAU,SAAS,CAAC,CAAC;IAC7D,OAAO,EAAE,EAAE,EAAE,UAAU,KAAK,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maps.d.ts","sourceRoot":"","sources":["../../src/commands/maps.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,IAAI,mCAGf,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { formatOutput } from "../lib/formatters.js";
|
|
2
|
+
import { error, log, success } from "../lib/logger.js";
|
|
3
|
+
import { runCommand, withSubcommands } from "../lib/run-command.js";
|
|
4
|
+
const HELP = `Usage: framedash maps <subcommand> [options]
|
|
5
|
+
|
|
6
|
+
Manage maps.
|
|
7
|
+
|
|
8
|
+
Subcommands:
|
|
9
|
+
list List maps
|
|
10
|
+
delete <map-id> Delete a map
|
|
11
|
+
|
|
12
|
+
Run 'framedash maps <subcommand> --help' for more info.`;
|
|
13
|
+
export const maps = withSubcommands("maps", HELP, {
|
|
14
|
+
list: mapsList,
|
|
15
|
+
delete: mapsDelete,
|
|
16
|
+
});
|
|
17
|
+
async function mapsList(args) {
|
|
18
|
+
await runCommand({ args, help: "Usage: framedash maps list [--format json|table|csv] [global options]" }, async ({ client, config }) => {
|
|
19
|
+
const data = await client.get(client.projectPath("maps"));
|
|
20
|
+
log(formatOutput(data, config.format));
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
async function mapsDelete(args) {
|
|
24
|
+
await runCommand({
|
|
25
|
+
args,
|
|
26
|
+
help: "Usage: framedash maps delete <map-id> [global options]",
|
|
27
|
+
allowPositionals: true,
|
|
28
|
+
}, async ({ client, positionals }) => {
|
|
29
|
+
const mapId = positionals[0];
|
|
30
|
+
if (!mapId) {
|
|
31
|
+
error("Map ID is required: framedash maps delete <map-id>");
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
await client.delete(client.projectPath(`maps/${encodeURIComponent(mapId)}`));
|
|
35
|
+
success(`Map ${mapId} deleted`);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=maps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maps.js","sourceRoot":"","sources":["../../src/commands/maps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEpE,MAAM,IAAI,GAAG;;;;;;;;wDAQ2C,CAAC;AAEzD,MAAM,CAAC,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,EAAE,IAAI,EAAE;IACjD,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,UAAU;CAClB,CAAC,CAAC;AAEH,KAAK,UAAU,QAAQ,CAAC,IAAc;IACrC,MAAM,UAAU,CACf,EAAE,IAAI,EAAE,IAAI,EAAE,uEAAuE,EAAE,EACvF,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;QAC5B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;QAC1D,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACxC,CAAC,CACD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,IAAc;IACvC,MAAM,UAAU,CACf;QACC,IAAI;QACJ,IAAI,EAAE,wDAAwD;QAC9D,gBAAgB,EAAE,IAAI;KACtB,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE;QACjC,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QAC7B,IAAI,CAAC,KAAK,EAAE,CAAC;YACZ,KAAK,CAAC,oDAAoD,CAAC,CAAC;YAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;QAED,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,QAAQ,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7E,OAAO,CAAC,OAAO,KAAK,UAAU,CAAC,CAAC;IACjC,CAAC,CACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +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,CA6CzD"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { parsePositiveInt } from "../lib/config.js";
|
|
3
|
+
import { formatOutput } from "../lib/formatters.js";
|
|
4
|
+
import { error, log } from "../lib/logger.js";
|
|
5
|
+
import { runCommand } from "../lib/run-command.js";
|
|
6
|
+
export async function query(args) {
|
|
7
|
+
await runCommand({
|
|
8
|
+
args,
|
|
9
|
+
help: HELP,
|
|
10
|
+
options: {
|
|
11
|
+
limit: { type: "string" },
|
|
12
|
+
file: { type: "string", short: "f" },
|
|
13
|
+
},
|
|
14
|
+
allowPositionals: true,
|
|
15
|
+
}, async ({ client, config, values, positionals }) => {
|
|
16
|
+
if (values.file && positionals.length > 0) {
|
|
17
|
+
error("Cannot use both --file and a positional SQL argument. Provide one or the other.");
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
let sql;
|
|
21
|
+
if (values.file) {
|
|
22
|
+
try {
|
|
23
|
+
sql = await readFile(values.file, "utf-8");
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
const msg = err instanceof Error ? err.message : "unknown error";
|
|
27
|
+
error(`Failed to read SQL file: ${values.file} (${msg})`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else if (positionals.length > 0) {
|
|
32
|
+
sql = positionals.join(" ");
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
error("SQL query is required. Provide as argument or use --file.");
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
const body = {
|
|
39
|
+
sql,
|
|
40
|
+
project_id: config.projectId,
|
|
41
|
+
};
|
|
42
|
+
if (values.limit) {
|
|
43
|
+
body.limit = parsePositiveInt(values.limit, "limit");
|
|
44
|
+
}
|
|
45
|
+
const data = await client.post("/api/v1/query", body);
|
|
46
|
+
log(formatOutput(data, config.format));
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const HELP = `Usage: framedash query <sql> [options]
|
|
50
|
+
framedash query --file query.sql [options]
|
|
51
|
+
|
|
52
|
+
Execute a read-only ClickHouse query.
|
|
53
|
+
|
|
54
|
+
Arguments:
|
|
55
|
+
<sql> SQL query string
|
|
56
|
+
|
|
57
|
+
Options:
|
|
58
|
+
-f, --file <path> Read SQL from file
|
|
59
|
+
--limit <n> Max rows (default: 1000)
|
|
60
|
+
--api-key <key> API key (or FRAMEDASH_API_KEY env)
|
|
61
|
+
--project-id <uuid> Project ID (or FRAMEDASH_PROJECT_ID env)
|
|
62
|
+
--base-url <url> API base URL (default: https://app.framedash.dev)
|
|
63
|
+
--format <fmt> Output format: json, table, csv (default: json)
|
|
64
|
+
-h, --help Show help
|
|
65
|
+
|
|
66
|
+
Examples:
|
|
67
|
+
framedash query "SELECT count() FROM events"
|
|
68
|
+
framedash query "SELECT event_name, count() FROM events GROUP BY event_name" --format table
|
|
69
|
+
framedash query --file complex-query.sql --limit 100`;
|
|
70
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +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;;;;;;;;;;;;;;;;;;;;uDAoB0C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../../src/commands/retention.ts"],"names":[],"mappings":"AAIA,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAS7D"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { formatOutput } from "../lib/formatters.js";
|
|
2
|
+
import { log } from "../lib/logger.js";
|
|
3
|
+
import { runCommand } from "../lib/run-command.js";
|
|
4
|
+
export async function retention(args) {
|
|
5
|
+
await runCommand({ args, help: HELP, options: { days: { type: "string" } } }, async ({ client, config, values }) => {
|
|
6
|
+
const params = new URLSearchParams({ days: values.days ?? "30" });
|
|
7
|
+
const data = await client.get(client.projectPath(`retention?${params}`));
|
|
8
|
+
log(formatOutput(data, config.format));
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
const HELP = `Usage: framedash retention [options]
|
|
12
|
+
|
|
13
|
+
Show player retention cohorts.
|
|
14
|
+
|
|
15
|
+
Options:
|
|
16
|
+
--days <n> Time period in days: 1, 7, 14, 30 (default: 30)
|
|
17
|
+
--api-key <key> API key (or FRAMEDASH_API_KEY env)
|
|
18
|
+
--project-id <uuid> Project ID (or FRAMEDASH_PROJECT_ID env)
|
|
19
|
+
--base-url <url> API base URL (default: https://app.framedash.dev)
|
|
20
|
+
--format <fmt> Output format: json, table, csv (default: json)
|
|
21
|
+
-h, --help Show help`;
|
|
22
|
+
//# sourceMappingURL=retention.js.map
|
|
@@ -0,0 +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,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,IAAI,EAAG,MAAM,CAAC,IAAe,IAAI,IAAI,EAAE,CAAC,CAAC;QAC9E,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,aAAa,MAAM,EAAE,CAAC,CAAC,CAAC;QACzE,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 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAIA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAK1D"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { formatOutput } from "../lib/formatters.js";
|
|
2
|
+
import { log } from "../lib/logger.js";
|
|
3
|
+
import { runCommand } from "../lib/run-command.js";
|
|
4
|
+
export async function status(args) {
|
|
5
|
+
await runCommand({ args, help: HELP }, async ({ client, config }) => {
|
|
6
|
+
const data = await client.get(client.projectPath("status"));
|
|
7
|
+
log(formatOutput(data, config.format));
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
const HELP = `Usage: framedash status [options]
|
|
11
|
+
|
|
12
|
+
Show project status and key metrics.
|
|
13
|
+
|
|
14
|
+
Options:
|
|
15
|
+
--api-key <key> API key (or FRAMEDASH_API_KEY env)
|
|
16
|
+
--project-id <uuid> Project ID (or FRAMEDASH_PROJECT_ID env)
|
|
17
|
+
--base-url <url> API base URL (default: https://app.framedash.dev)
|
|
18
|
+
--format <fmt> Output format: json, table, csv (default: json)
|
|
19
|
+
-h, --help Show help`;
|
|
20
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.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,MAAM,CAAC,IAAc;IAC1C,MAAM,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;QACnE,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC5D,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,IAAI,GAAG;;;;;;;;;mCASsB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { error, log } from "./lib/logger.js";
|
|
4
|
+
const VERSION = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"))
|
|
5
|
+
.version;
|
|
6
|
+
const HELP = `Usage: framedash <command> [options]
|
|
7
|
+
|
|
8
|
+
Commands:
|
|
9
|
+
auth Verify API key and list projects
|
|
10
|
+
status Show project status and key metrics
|
|
11
|
+
dashboard Show dashboard metrics
|
|
12
|
+
retention Show player retention cohorts
|
|
13
|
+
funnel Analyze event funnels
|
|
14
|
+
query Execute a read-only ClickHouse query
|
|
15
|
+
alerts Manage alert rules (list, create, update, delete)
|
|
16
|
+
maps Manage maps (list, delete)
|
|
17
|
+
content Manage content registry (list, import, delete)
|
|
18
|
+
map-capture Upload captured map images
|
|
19
|
+
|
|
20
|
+
Global Options:
|
|
21
|
+
--api-key <key> API key. Prefer FRAMEDASH_API_KEY env or --api-key-file:
|
|
22
|
+
a key passed as --api-key is visible in the process
|
|
23
|
+
list and shell history.
|
|
24
|
+
--api-key-file <path> Read the API key from a file ('-' for stdin)
|
|
25
|
+
--project-id <uuid> Project ID (or FRAMEDASH_PROJECT_ID env)
|
|
26
|
+
--base-url <url> API base URL (default: https://app.framedash.dev)
|
|
27
|
+
--format <fmt> Output format: json, table, csv (default: json)
|
|
28
|
+
-h, --help Show help
|
|
29
|
+
-v, --version Show version
|
|
30
|
+
|
|
31
|
+
Run 'framedash <command> --help' for command-specific options.`;
|
|
32
|
+
/** Type-safe command registry — typos in export names become build-time errors. */
|
|
33
|
+
const COMMANDS = {
|
|
34
|
+
auth: () => import("./commands/auth.js").then((m) => m.auth),
|
|
35
|
+
status: () => import("./commands/status.js").then((m) => m.status),
|
|
36
|
+
dashboard: () => import("./commands/dashboard.js").then((m) => m.dashboard),
|
|
37
|
+
retention: () => import("./commands/retention.js").then((m) => m.retention),
|
|
38
|
+
funnel: () => import("./commands/funnel.js").then((m) => m.funnel),
|
|
39
|
+
query: () => import("./commands/query.js").then((m) => m.query),
|
|
40
|
+
alerts: () => import("./commands/alerts.js").then((m) => m.alerts),
|
|
41
|
+
maps: () => import("./commands/maps.js").then((m) => m.maps),
|
|
42
|
+
content: () => import("./commands/content.js").then((m) => m.content),
|
|
43
|
+
"map-capture": () => import("./commands/map-capture.js").then((m) => m.mapCaptureCommand),
|
|
44
|
+
};
|
|
45
|
+
const command = process.argv[2];
|
|
46
|
+
const commandArgs = process.argv.slice(3);
|
|
47
|
+
if (command === "-v" || command === "--version") {
|
|
48
|
+
log(`framedash v${VERSION}`);
|
|
49
|
+
process.exit(0);
|
|
50
|
+
}
|
|
51
|
+
if (!command || command === "-h" || command === "--help") {
|
|
52
|
+
log(HELP);
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
if (!Object.hasOwn(COMMANDS, command)) {
|
|
57
|
+
error(`Unknown command: ${command}`);
|
|
58
|
+
log(HELP);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
// biome-ignore lint/style/noNonNullAssertion: validated by Object.hasOwn above
|
|
62
|
+
const fn = await COMMANDS[command]();
|
|
63
|
+
await fn(commandArgs);
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
if (err instanceof Error && "code" in err && err.code === "ERR_PARSE_ARGS_UNKNOWN_OPTION") {
|
|
67
|
+
error(err.message);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
error(err instanceof Error ? err.message : String(err));
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export type OutputFormat = "json" | "table" | "csv";
|
|
2
|
+
export type CliConfig = {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
projectId: string;
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
format: OutputFormat;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Resolve the API key, preferring sources that keep it out of the process
|
|
10
|
+
* argument list: --api-key flag, then --api-key-file (a path, or "-" for stdin),
|
|
11
|
+
* then the FRAMEDASH_API_KEY env var. Returns undefined if none is set.
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveApiKey(values: Record<string, unknown>): string | undefined;
|
|
14
|
+
/** Resolve global CLI config from parsed flags and environment variables. */
|
|
15
|
+
export declare function resolveConfig(values: Record<string, unknown>): CliConfig;
|
|
16
|
+
/** Resolve config for commands that don't require --project-id (e.g. auth). */
|
|
17
|
+
export declare function resolveConfigWithoutProject(values: Record<string, unknown>): Omit<CliConfig, "projectId">;
|
|
18
|
+
/** Parse a string flag as a positive integer with a descriptive error. */
|
|
19
|
+
export declare function parsePositiveInt(value: string, flagName: string): number;
|
|
20
|
+
/** Parse a string flag as a non-negative number with a descriptive error. */
|
|
21
|
+
export declare function parseNumber(value: string, flagName: string): number;
|
|
22
|
+
/**
|
|
23
|
+
* Global parseArgs option definitions shared by all commands.
|
|
24
|
+
* Spread into each command's parseArgs call.
|
|
25
|
+
*/
|
|
26
|
+
export declare const GLOBAL_OPTIONS: {
|
|
27
|
+
"api-key": {
|
|
28
|
+
type: "string";
|
|
29
|
+
};
|
|
30
|
+
"api-key-file": {
|
|
31
|
+
type: "string";
|
|
32
|
+
};
|
|
33
|
+
"project-id": {
|
|
34
|
+
type: "string";
|
|
35
|
+
};
|
|
36
|
+
"base-url": {
|
|
37
|
+
type: "string";
|
|
38
|
+
};
|
|
39
|
+
format: {
|
|
40
|
+
type: "string";
|
|
41
|
+
};
|
|
42
|
+
help: {
|
|
43
|
+
type: "boolean";
|
|
44
|
+
short: "h";
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAEpD,MAAM,MAAM,SAAS,GAAG;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,YAAY,CAAC;CACrB,CAAC;AA6BF;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,SAAS,CA+BjF;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAgBxE;AAED,+EAA+E;AAC/E,wBAAgB,2BAA2B,CAC1C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAS9B;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOxE;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOnE;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;CAO1B,CAAC"}
|