@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,114 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { assertSafeBaseUrl } from "@framedash/api-client";
|
|
3
|
+
import { error } from "./logger.js";
|
|
4
|
+
function resolveBaseAndFormat(values) {
|
|
5
|
+
const baseUrl = values["base-url"] ??
|
|
6
|
+
process.env.FRAMEDASH_BASE_URL ??
|
|
7
|
+
"https://app.framedash.dev";
|
|
8
|
+
// The API key is sent on every request; refuse a base URL that would expose
|
|
9
|
+
// it (http to a non-loopback host, or a poisoned --base-url / FRAMEDASH_BASE_URL).
|
|
10
|
+
try {
|
|
11
|
+
assertSafeBaseUrl(baseUrl);
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
error(err instanceof Error ? err.message : `Invalid base URL: ${baseUrl}`);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
const formatStr = values.format ?? process.env.FRAMEDASH_FORMAT ?? "json";
|
|
18
|
+
if (formatStr !== "json" && formatStr !== "table" && formatStr !== "csv") {
|
|
19
|
+
error(`Invalid format: ${formatStr}. Use json, table, or csv.`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
return { baseUrl, format: formatStr };
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the API key, preferring sources that keep it out of the process
|
|
26
|
+
* argument list: --api-key flag, then --api-key-file (a path, or "-" for stdin),
|
|
27
|
+
* then the FRAMEDASH_API_KEY env var. Returns undefined if none is set.
|
|
28
|
+
*/
|
|
29
|
+
export function resolveApiKey(values) {
|
|
30
|
+
const flag = values["api-key"];
|
|
31
|
+
if (flag)
|
|
32
|
+
return flag;
|
|
33
|
+
const file = values["api-key-file"];
|
|
34
|
+
if (file) {
|
|
35
|
+
const label = file === "-" ? "stdin" : file;
|
|
36
|
+
// readFileSync(0) blocks forever on an interactive TTY; require piped input.
|
|
37
|
+
if (file === "-" && process.stdin.isTTY) {
|
|
38
|
+
error("Cannot read the API key from stdin: no piped input (stdin is a terminal)");
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
let raw;
|
|
42
|
+
try {
|
|
43
|
+
// fd 0 reads piped stdin synchronously (e.g. `... | framedash --api-key-file -`).
|
|
44
|
+
raw = file === "-" ? readFileSync(0, "utf8") : readFileSync(file, "utf8");
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
error(`Failed to read --api-key-file (${label}): ${err instanceof Error ? err.message : String(err)}`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
const key = raw.trim();
|
|
51
|
+
if (!key) {
|
|
52
|
+
error(`--api-key-file (${label}) is empty`);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
return key;
|
|
56
|
+
}
|
|
57
|
+
return process.env.FRAMEDASH_API_KEY;
|
|
58
|
+
}
|
|
59
|
+
/** Resolve global CLI config from parsed flags and environment variables. */
|
|
60
|
+
export function resolveConfig(values) {
|
|
61
|
+
const apiKey = resolveApiKey(values);
|
|
62
|
+
if (!apiKey) {
|
|
63
|
+
error("--api-key, --api-key-file, or FRAMEDASH_API_KEY env is required");
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
const projectId = values["project-id"] ?? process.env.FRAMEDASH_PROJECT_ID;
|
|
67
|
+
if (!projectId) {
|
|
68
|
+
error("--project-id or FRAMEDASH_PROJECT_ID env is required");
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
const { baseUrl, format } = resolveBaseAndFormat(values);
|
|
72
|
+
return { apiKey, projectId, baseUrl, format };
|
|
73
|
+
}
|
|
74
|
+
/** Resolve config for commands that don't require --project-id (e.g. auth). */
|
|
75
|
+
export function resolveConfigWithoutProject(values) {
|
|
76
|
+
const apiKey = resolveApiKey(values);
|
|
77
|
+
if (!apiKey) {
|
|
78
|
+
error("--api-key, --api-key-file, or FRAMEDASH_API_KEY env is required");
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
const { baseUrl, format } = resolveBaseAndFormat(values);
|
|
82
|
+
return { apiKey, baseUrl, format };
|
|
83
|
+
}
|
|
84
|
+
/** Parse a string flag as a positive integer with a descriptive error. */
|
|
85
|
+
export function parsePositiveInt(value, flagName) {
|
|
86
|
+
const num = Number(value);
|
|
87
|
+
if (!Number.isInteger(num) || num <= 0) {
|
|
88
|
+
error(`--${flagName} must be a positive integer, got: ${value}`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
return num;
|
|
92
|
+
}
|
|
93
|
+
/** Parse a string flag as a non-negative number with a descriptive error. */
|
|
94
|
+
export function parseNumber(value, flagName) {
|
|
95
|
+
const num = Number(value);
|
|
96
|
+
if (Number.isNaN(num)) {
|
|
97
|
+
error(`--${flagName} must be a number, got: ${value}`);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
return num;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Global parseArgs option definitions shared by all commands.
|
|
104
|
+
* Spread into each command's parseArgs call.
|
|
105
|
+
*/
|
|
106
|
+
export const GLOBAL_OPTIONS = {
|
|
107
|
+
"api-key": { type: "string" },
|
|
108
|
+
"api-key-file": { type: "string" },
|
|
109
|
+
"project-id": { type: "string" },
|
|
110
|
+
"base-url": { type: "string" },
|
|
111
|
+
format: { type: "string" },
|
|
112
|
+
help: { type: "boolean", short: "h" },
|
|
113
|
+
};
|
|
114
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-client.d.ts","sourceRoot":"","sources":["../../src/lib/create-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAiB,MAAM,uBAAuB,CAAC;AAGjE,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,CAyB1F"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ApiClient } from "@framedash/api-client";
|
|
2
|
+
import { error } from "./logger.js";
|
|
3
|
+
export function createClient(baseUrl, apiKey, projectId) {
|
|
4
|
+
return new ApiClient({
|
|
5
|
+
baseUrl,
|
|
6
|
+
apiKey,
|
|
7
|
+
projectId,
|
|
8
|
+
onError(err) {
|
|
9
|
+
if (err.status === 429) {
|
|
10
|
+
const retryAfter = err.retryAfter;
|
|
11
|
+
if (retryAfter !== undefined) {
|
|
12
|
+
error(`Rate limit exceeded (429). Retry after ${retryAfter}s.`);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
const reset = err.headers.get("X-RateLimit-Reset");
|
|
16
|
+
const resetNum = reset ? Number(reset) : Number.NaN;
|
|
17
|
+
const resetStr = !Number.isNaN(resetNum) && resetNum > 0
|
|
18
|
+
? new Date(resetNum * 1000).toLocaleTimeString()
|
|
19
|
+
: "unknown";
|
|
20
|
+
error(`Rate limit exceeded (429). Resets at ${resetStr}.`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
error(err.message);
|
|
25
|
+
}
|
|
26
|
+
process.exit(1);
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=create-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-client.js","sourceRoot":"","sources":["../../src/lib/create-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAiB,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,MAAc,EAAE,SAAiB;IAC9E,OAAO,IAAI,SAAS,CAAC;QACpB,OAAO;QACP,MAAM;QACN,SAAS;QACT,OAAO,CAAC,GAAa;YACpB,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACxB,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC;gBAClC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;oBAC9B,KAAK,CAAC,0CAA0C,UAAU,IAAI,CAAC,CAAC;gBACjE,CAAC;qBAAM,CAAC;oBACP,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;oBACnD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;oBACpD,MAAM,QAAQ,GACb,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC;wBACtC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,kBAAkB,EAAE;wBAChD,CAAC,CAAC,SAAS,CAAC;oBACd,KAAK,CAAC,wCAAwC,QAAQ,GAAG,CAAC,CAAC;gBAC5D,CAAC;YACF,CAAC;iBAAM,CAAC;gBACP,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACpB,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;KACD,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../../src/lib/formatters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,0DAA0D;AAC1D,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CASxE"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/** Format data for CLI output in the requested format. */
|
|
2
|
+
export function formatOutput(data, format) {
|
|
3
|
+
switch (format) {
|
|
4
|
+
case "json":
|
|
5
|
+
return JSON.stringify(data, null, 2);
|
|
6
|
+
case "table":
|
|
7
|
+
return formatTable(data);
|
|
8
|
+
case "csv":
|
|
9
|
+
return formatCsv(data);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function formatTable(data) {
|
|
13
|
+
const rows = toRows(data);
|
|
14
|
+
if (rows.length === 0)
|
|
15
|
+
return "(no data)";
|
|
16
|
+
const firstRow = rows[0];
|
|
17
|
+
if (!firstRow)
|
|
18
|
+
return "(no data)";
|
|
19
|
+
const keys = Object.keys(firstRow);
|
|
20
|
+
const widths = keys.map((k) => Math.max(k.length, ...rows.map((r) => cellString(r[k]).length)));
|
|
21
|
+
const header = keys.map((k, i) => k.padEnd(widths[i] ?? k.length)).join(" ");
|
|
22
|
+
const separator = widths.map((w) => "-".repeat(w)).join(" ");
|
|
23
|
+
const body = rows
|
|
24
|
+
.map((row) => keys.map((k, i) => cellString(row[k]).padEnd(widths[i] ?? k.length)).join(" "))
|
|
25
|
+
.join("\n");
|
|
26
|
+
return `${header}\n${separator}\n${body}`;
|
|
27
|
+
}
|
|
28
|
+
function formatCsv(data) {
|
|
29
|
+
const rows = toRows(data);
|
|
30
|
+
if (rows.length === 0)
|
|
31
|
+
return "";
|
|
32
|
+
const firstRow = rows[0];
|
|
33
|
+
if (!firstRow)
|
|
34
|
+
return "";
|
|
35
|
+
const keys = Object.keys(firstRow);
|
|
36
|
+
const header = keys.map(escapeCsv).join(",");
|
|
37
|
+
const body = rows
|
|
38
|
+
.map((row) => keys.map((k) => escapeCsv(cellString(row[k]))).join(","))
|
|
39
|
+
.join("\n");
|
|
40
|
+
return `${header}\n${body}`;
|
|
41
|
+
}
|
|
42
|
+
/** Convert a cell value to a string for tabular output, JSON-encoding nested objects/arrays. */
|
|
43
|
+
function cellString(value) {
|
|
44
|
+
if (value === null || value === undefined)
|
|
45
|
+
return "";
|
|
46
|
+
if (typeof value === "object")
|
|
47
|
+
return JSON.stringify(value);
|
|
48
|
+
return String(value);
|
|
49
|
+
}
|
|
50
|
+
function escapeCsv(value) {
|
|
51
|
+
// Prevent CSV formula injection (OWASP) — also catch whitespace-prefixed formulas
|
|
52
|
+
const trimmed = value.trimStart();
|
|
53
|
+
if (trimmed.length > 0 && /^[=+\-@]/.test(trimmed)) {
|
|
54
|
+
value = `'${value}`;
|
|
55
|
+
}
|
|
56
|
+
if (value.includes(",") || value.includes('"') || value.includes("\n") || value.includes("\r")) {
|
|
57
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
58
|
+
}
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
function toRows(data) {
|
|
62
|
+
if (Array.isArray(data)) {
|
|
63
|
+
return data.map((item) => typeof item === "object" && item !== null
|
|
64
|
+
? item
|
|
65
|
+
: { value: item });
|
|
66
|
+
}
|
|
67
|
+
if (typeof data === "object" && data !== null)
|
|
68
|
+
return [data];
|
|
69
|
+
return [{ value: data }];
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=formatters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.js","sourceRoot":"","sources":["../../src/lib/formatters.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple logging helpers for CLI output.
|
|
3
|
+
* Data goes to stdout (log), status messages go to stderr (success/error).
|
|
4
|
+
* This lets users pipe structured output to jq/csvtool while still seeing messages.
|
|
5
|
+
*/
|
|
6
|
+
export declare function log(message: string): void;
|
|
7
|
+
export declare function success(message: string): void;
|
|
8
|
+
export declare function error(message: string): void;
|
|
9
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEzC;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7C;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE3C"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple logging helpers for CLI output.
|
|
3
|
+
* Data goes to stdout (log), status messages go to stderr (success/error).
|
|
4
|
+
* This lets users pipe structured output to jq/csvtool while still seeing messages.
|
|
5
|
+
*/
|
|
6
|
+
export function log(message) {
|
|
7
|
+
process.stdout.write(`${message}\n`);
|
|
8
|
+
}
|
|
9
|
+
export function success(message) {
|
|
10
|
+
process.stderr.write(` \u2713 ${message}\n`);
|
|
11
|
+
}
|
|
12
|
+
export function error(message) {
|
|
13
|
+
process.stderr.write(` \u2717 ${message}\n`);
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,UAAU,GAAG,CAAC,OAAe;IAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,OAAe;IACtC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,OAAO,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,OAAe;IACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,OAAO,IAAI,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Zod schema for the JSON sidecar metadata file produced by
|
|
4
|
+
* engine capture scripts (UE5 Commandlet / Unity EditorScript).
|
|
5
|
+
*
|
|
6
|
+
* Matches brief-tech.md Section 8.4 format.
|
|
7
|
+
*/
|
|
8
|
+
export declare const mapCaptureMetadataSchema: z.ZodObject<{
|
|
9
|
+
version: z.ZodLiteral<"1.0">;
|
|
10
|
+
map_id: z.ZodString;
|
|
11
|
+
image_path: z.ZodString;
|
|
12
|
+
image_dimensions: z.ZodObject<{
|
|
13
|
+
width: z.ZodNumber;
|
|
14
|
+
height: z.ZodNumber;
|
|
15
|
+
}, z.core.$strip>;
|
|
16
|
+
world_bounds: z.ZodObject<{
|
|
17
|
+
min: z.ZodObject<{
|
|
18
|
+
x: z.ZodNumber;
|
|
19
|
+
y: z.ZodNumber;
|
|
20
|
+
z: z.ZodNumber;
|
|
21
|
+
}, z.core.$strip>;
|
|
22
|
+
max: z.ZodObject<{
|
|
23
|
+
x: z.ZodNumber;
|
|
24
|
+
y: z.ZodNumber;
|
|
25
|
+
z: z.ZodNumber;
|
|
26
|
+
}, z.core.$strip>;
|
|
27
|
+
}, z.core.$strip>;
|
|
28
|
+
projection: z.ZodOptional<z.ZodString>;
|
|
29
|
+
capture_axis: z.ZodOptional<z.ZodString>;
|
|
30
|
+
coordinate_system: z.ZodOptional<z.ZodString>;
|
|
31
|
+
engine: z.ZodOptional<z.ZodString>;
|
|
32
|
+
build_id: z.ZodOptional<z.ZodString>;
|
|
33
|
+
captured_at: z.ZodOptional<z.ZodString>;
|
|
34
|
+
}, z.core.$strip>;
|
|
35
|
+
export type MapCaptureMetadata = z.infer<typeof mapCaptureMetadataSchema>;
|
|
36
|
+
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/lib/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAyBxB;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;iBAYnC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// Canonical source: ingest-core/src/config.ts MAX_MAP_ID_LEN
|
|
3
|
+
const MAX_MAP_ID_LEN = 128;
|
|
4
|
+
const dimensionsSchema = z.object({
|
|
5
|
+
width: z.number().int().positive(),
|
|
6
|
+
height: z.number().int().positive(),
|
|
7
|
+
});
|
|
8
|
+
const vector3Schema = z.object({
|
|
9
|
+
x: z.number().finite(),
|
|
10
|
+
y: z.number().finite(),
|
|
11
|
+
z: z.number().finite(),
|
|
12
|
+
});
|
|
13
|
+
const worldBoundsSchema = z
|
|
14
|
+
.object({
|
|
15
|
+
min: vector3Schema,
|
|
16
|
+
max: vector3Schema,
|
|
17
|
+
})
|
|
18
|
+
.refine((b) => b.max.x > b.min.x && b.max.y > b.min.y, {
|
|
19
|
+
message: "World max bounds must be greater than min bounds",
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* Zod schema for the JSON sidecar metadata file produced by
|
|
23
|
+
* engine capture scripts (UE5 Commandlet / Unity EditorScript).
|
|
24
|
+
*
|
|
25
|
+
* Matches brief-tech.md Section 8.4 format.
|
|
26
|
+
*/
|
|
27
|
+
export const mapCaptureMetadataSchema = z.object({
|
|
28
|
+
version: z.literal("1.0"),
|
|
29
|
+
map_id: z.string().min(1).max(MAX_MAP_ID_LEN),
|
|
30
|
+
image_path: z.string().min(1),
|
|
31
|
+
image_dimensions: dimensionsSchema,
|
|
32
|
+
world_bounds: worldBoundsSchema,
|
|
33
|
+
projection: z.string().optional(),
|
|
34
|
+
capture_axis: z.string().optional(),
|
|
35
|
+
coordinate_system: z.string().optional(),
|
|
36
|
+
engine: z.string().optional(),
|
|
37
|
+
build_id: z.string().max(255).optional(),
|
|
38
|
+
captured_at: z.string().datetime().optional(),
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/lib/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,6DAA6D;AAC7D,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAClC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;CACnC,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE;IACtB,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE;IACtB,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE;CACtB,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAAG,CAAC;KACzB,MAAM,CAAC;IACP,GAAG,EAAE,aAAa;IAClB,GAAG,EAAE,aAAa;CAClB,CAAC;KACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE;IACtD,OAAO,EAAE,kDAAkD;CAC3D,CAAC,CAAC;AAEJ;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;IACzB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC;IAC7C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,gBAAgB,EAAE,gBAAgB;IAClC,YAAY,EAAE,iBAAiB;IAC/B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACxC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IACxC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CAC7C,CAAC,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type ParseArgsConfig } from "node:util";
|
|
2
|
+
import type { ApiClient } from "@framedash/api-client";
|
|
3
|
+
import { type CliConfig } from "./config.js";
|
|
4
|
+
export type CommandOptions = {
|
|
5
|
+
args: string[];
|
|
6
|
+
help: string;
|
|
7
|
+
options?: ParseArgsConfig["options"];
|
|
8
|
+
allowPositionals?: boolean;
|
|
9
|
+
noProject?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export type CommandContext = {
|
|
12
|
+
config: CliConfig;
|
|
13
|
+
client: ApiClient;
|
|
14
|
+
values: Record<string, string | boolean | undefined>;
|
|
15
|
+
positionals: string[];
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Shared command runner that handles parseArgs, help, config resolution,
|
|
19
|
+
* and client creation. Commands only need to supply their specific logic.
|
|
20
|
+
*/
|
|
21
|
+
export declare function runCommand(opts: CommandOptions, handler: (ctx: CommandContext) => Promise<void>): Promise<void>;
|
|
22
|
+
export type SubcommandMap = Record<string, (args: string[]) => Promise<void>>;
|
|
23
|
+
/**
|
|
24
|
+
* Create a subcommand dispatcher that handles help display and
|
|
25
|
+
* routes to the correct handler based on the first positional arg.
|
|
26
|
+
*/
|
|
27
|
+
export declare function withSubcommands(name: string, help: string, subcommands: SubcommandMap): (args: string[]) => Promise<void>;
|
|
28
|
+
//# sourceMappingURL=run-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-command.d.ts","sourceRoot":"","sources":["../../src/lib/run-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAa,MAAM,WAAW,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EACN,KAAK,SAAS,EAId,MAAM,aAAa,CAAC;AAIrB,MAAM,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC;IACrC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC5B,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;IACrD,WAAW,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,wBAAsB,UAAU,CAC/B,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAC7C,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AAE9E;;;GAGG;AACH,wBAAgB,eAAe,CAC9B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,aAAa,GACxB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAmBnC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
import { GLOBAL_OPTIONS, resolveConfig, resolveConfigWithoutProject, } from "./config.js";
|
|
3
|
+
import { createClient } from "./create-client.js";
|
|
4
|
+
import { error, log } from "./logger.js";
|
|
5
|
+
/**
|
|
6
|
+
* Shared command runner that handles parseArgs, help, config resolution,
|
|
7
|
+
* and client creation. Commands only need to supply their specific logic.
|
|
8
|
+
*/
|
|
9
|
+
export async function runCommand(opts, handler) {
|
|
10
|
+
const { values, positionals } = parseArgs({
|
|
11
|
+
args: opts.args,
|
|
12
|
+
options: { ...GLOBAL_OPTIONS, ...opts.options },
|
|
13
|
+
allowPositionals: opts.allowPositionals ?? false,
|
|
14
|
+
});
|
|
15
|
+
if (values.help) {
|
|
16
|
+
log(opts.help);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const typedValues = values;
|
|
20
|
+
if (opts.noProject) {
|
|
21
|
+
const baseConfig = resolveConfigWithoutProject(typedValues);
|
|
22
|
+
const config = { ...baseConfig, projectId: "" };
|
|
23
|
+
const client = createClient(config.baseUrl, config.apiKey, "");
|
|
24
|
+
await handler({ config, client, values: typedValues, positionals });
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
const config = resolveConfig(typedValues);
|
|
28
|
+
const client = createClient(config.baseUrl, config.apiKey, config.projectId);
|
|
29
|
+
await handler({ config, client, values: typedValues, positionals });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Create a subcommand dispatcher that handles help display and
|
|
34
|
+
* routes to the correct handler based on the first positional arg.
|
|
35
|
+
*/
|
|
36
|
+
export function withSubcommands(name, help, subcommands) {
|
|
37
|
+
return async (args) => {
|
|
38
|
+
const subcommand = args[0];
|
|
39
|
+
if (!subcommand || subcommand === "--help" || subcommand === "-h") {
|
|
40
|
+
log(help);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (!Object.hasOwn(subcommands, subcommand)) {
|
|
44
|
+
error(`Unknown ${name} subcommand: ${subcommand}`);
|
|
45
|
+
log(help);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// biome-ignore lint/style/noNonNullAssertion: validated by Object.hasOwn above
|
|
50
|
+
await subcommands[subcommand](args.slice(1));
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=run-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-command.js","sourceRoot":"","sources":["../../src/lib/run-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,SAAS,EAAE,MAAM,WAAW,CAAC;AAE5D,OAAO,EAEN,cAAc,EACd,aAAa,EACb,2BAA2B,GAC3B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAiBzC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC/B,IAAoB,EACpB,OAA+C;IAE/C,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC;QACzC,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE,EAAE,GAAG,cAAc,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE;QAC/C,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,IAAI,KAAK;KAChD,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QACjB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,OAAO;IACR,CAAC;IAED,MAAM,WAAW,GAAG,MAAsD,CAAC;IAE3E,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACpB,MAAM,UAAU,GAAG,2BAA2B,CAAC,WAAW,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAc,EAAE,GAAG,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;QAC3D,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC/D,MAAM,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;IACrE,CAAC;SAAM,CAAC;QACP,MAAM,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QAC7E,MAAM,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;IACrE,CAAC;AACF,CAAC;AAID;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC9B,IAAY,EACZ,IAAY,EACZ,WAA0B;IAE1B,OAAO,KAAK,EAAE,IAAc,EAAiB,EAAE;QAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAE3B,IAAI,CAAC,UAAU,IAAI,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YACnE,GAAG,CAAC,IAAI,CAAC,CAAC;YACV,OAAO;QACR,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC,EAAE,CAAC;YAC7C,KAAK,CAAC,WAAW,IAAI,gBAAgB,UAAU,EAAE,CAAC,CAAC;YACnD,GAAG,CAAC,IAAI,CAAC,CAAC;YACV,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAChB,OAAO;QACR,CAAC;QAED,+EAA+E;QAC/E,MAAM,WAAW,CAAC,UAAU,CAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { MapCaptureMetadata } from "./metadata.js";
|
|
2
|
+
export type UploadOptions = {
|
|
3
|
+
metadata: MapCaptureMetadata;
|
|
4
|
+
imagePath: string;
|
|
5
|
+
apiKey: string;
|
|
6
|
+
projectId: string;
|
|
7
|
+
baseUrl: string;
|
|
8
|
+
};
|
|
9
|
+
export type UploadResult = {
|
|
10
|
+
success: boolean;
|
|
11
|
+
mapId: string;
|
|
12
|
+
action: "created" | "updated";
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Upload a map image + metadata to the Framedash API.
|
|
16
|
+
* Sends multipart/form-data to POST /api/v1/maps/upload.
|
|
17
|
+
*/
|
|
18
|
+
export declare function uploadMapCapture(opts: UploadOptions): Promise<UploadResult>;
|
|
19
|
+
//# sourceMappingURL=uploader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploader.d.ts","sourceRoot":"","sources":["../../src/lib/uploader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAYxD,MAAM,MAAM,aAAa,GAAG;IAC3B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;CAC9B,CAAC;AAEF;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAoDjF"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { basename, extname } from "node:path";
|
|
3
|
+
import { assertSafeBaseUrl } from "@framedash/api-client";
|
|
4
|
+
/** Upload timeout: generous vs the JSON client since it streams an image blob. */
|
|
5
|
+
const UPLOAD_TIMEOUT_MS = 120_000;
|
|
6
|
+
const MIME_MAP = {
|
|
7
|
+
".png": "image/png",
|
|
8
|
+
".jpg": "image/jpeg",
|
|
9
|
+
".jpeg": "image/jpeg",
|
|
10
|
+
".webp": "image/webp",
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Upload a map image + metadata to the Framedash API.
|
|
14
|
+
* Sends multipart/form-data to POST /api/v1/maps/upload.
|
|
15
|
+
*/
|
|
16
|
+
export async function uploadMapCapture(opts) {
|
|
17
|
+
assertSafeBaseUrl(opts.baseUrl);
|
|
18
|
+
const imageBuffer = await readFile(opts.imagePath);
|
|
19
|
+
const ext = extname(opts.imagePath).toLowerCase();
|
|
20
|
+
const mimeType = MIME_MAP[ext];
|
|
21
|
+
if (!mimeType) {
|
|
22
|
+
throw new Error(`Unsupported image format: ${ext}`);
|
|
23
|
+
}
|
|
24
|
+
const formData = new FormData();
|
|
25
|
+
formData.set("mapId", opts.metadata.map_id);
|
|
26
|
+
formData.set("name", opts.metadata.map_id);
|
|
27
|
+
formData.set("worldMinX", String(opts.metadata.world_bounds.min.x));
|
|
28
|
+
formData.set("worldMinY", String(opts.metadata.world_bounds.min.y));
|
|
29
|
+
formData.set("worldMaxX", String(opts.metadata.world_bounds.max.x));
|
|
30
|
+
formData.set("worldMaxY", String(opts.metadata.world_bounds.max.y));
|
|
31
|
+
formData.set("imageWidth", String(opts.metadata.image_dimensions.width));
|
|
32
|
+
formData.set("imageHeight", String(opts.metadata.image_dimensions.height));
|
|
33
|
+
const blob = new Blob([imageBuffer], { type: mimeType });
|
|
34
|
+
formData.set("image", blob, basename(opts.imagePath));
|
|
35
|
+
// Trim trailing slashes (as ApiClient does) so a base URL like
|
|
36
|
+
// "https://host/" does not produce "https://host//api/..." -- the app would
|
|
37
|
+
// 308-redirect the double slash, which redirect:"manual" below now rejects.
|
|
38
|
+
const base = opts.baseUrl.replace(/\/+$/, "");
|
|
39
|
+
const url = `${base}/api/v1/maps/upload`;
|
|
40
|
+
const response = await fetch(url, {
|
|
41
|
+
method: "POST",
|
|
42
|
+
headers: {
|
|
43
|
+
"X-API-Key": opts.apiKey,
|
|
44
|
+
"X-Project-Id": opts.projectId,
|
|
45
|
+
},
|
|
46
|
+
body: formData,
|
|
47
|
+
redirect: "manual",
|
|
48
|
+
signal: AbortSignal.timeout(UPLOAD_TIMEOUT_MS),
|
|
49
|
+
});
|
|
50
|
+
// Do not follow a redirect: fetch would re-send the X-API-Key header to the
|
|
51
|
+
// redirect target (undici keeps custom headers across cross-origin redirects).
|
|
52
|
+
if (response.type === "opaqueredirect" || (response.status >= 300 && response.status < 400)) {
|
|
53
|
+
throw new Error(`Upload failed: unexpected redirect (status ${response.status || "opaque"}); refusing to resend credentials to the redirect target`);
|
|
54
|
+
}
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
const body = await response.text();
|
|
57
|
+
throw new Error(`Upload failed (${response.status}): ${body}`);
|
|
58
|
+
}
|
|
59
|
+
return (await response.json());
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=uploader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploader.js","sourceRoot":"","sources":["../../src/lib/uploader.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@framedash/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"bin": {
|
|
13
|
+
"framedash": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"default": "./dist/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18.0.0"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"zod": "^4.3.6",
|
|
28
|
+
"@framedash/api-client": "0.1.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^22.19.0",
|
|
32
|
+
"@vitest/coverage-v8": "^3.2.0",
|
|
33
|
+
"typescript": "^5.7.0",
|
|
34
|
+
"vitest": "^3.2.0"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc -p tsconfig.build.json",
|
|
38
|
+
"type-check": "tsc --noEmit",
|
|
39
|
+
"test": "vitest run",
|
|
40
|
+
"test:coverage": "vitest run --coverage",
|
|
41
|
+
"clean": "rm -rf dist"
|
|
42
|
+
}
|
|
43
|
+
}
|