@openbat/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/README.md +292 -0
- package/bin/openbat +3 -0
- package/dist/api-client.d.mts +41 -0
- package/dist/api-client.d.ts +41 -0
- package/dist/api-client.js +175 -0
- package/dist/api-client.mjs +6 -0
- package/dist/chunk-CRJZM45P.mjs +152 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1221 -0
- package/dist/index.mjs +1051 -0
- package/package.json +65 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
var __typeError = (msg) => {
|
|
2
|
+
throw TypeError(msg);
|
|
3
|
+
};
|
|
4
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
5
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
6
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
7
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
8
|
+
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
9
|
+
|
|
10
|
+
// src/api-client.ts
|
|
11
|
+
import { URL } from "url";
|
|
12
|
+
var KEY_REGEX = /ob_(?:live|read|admin|pat)_[0-9a-f]{32}/g;
|
|
13
|
+
function redact(s) {
|
|
14
|
+
return s.replace(KEY_REGEX, (k) => `${k.slice(0, 16)}\u2026<hidden>`);
|
|
15
|
+
}
|
|
16
|
+
function assertHttpsOrLocalhost(baseUrl) {
|
|
17
|
+
let url;
|
|
18
|
+
try {
|
|
19
|
+
url = new URL(baseUrl);
|
|
20
|
+
} catch {
|
|
21
|
+
throw new Error(`Invalid base URL: ${redact(baseUrl)}`);
|
|
22
|
+
}
|
|
23
|
+
if (url.protocol === "https:") return;
|
|
24
|
+
if (url.protocol === "http:" && (url.hostname === "localhost" || url.hostname === "127.0.0.1")) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
throw new Error(
|
|
28
|
+
"Refusing to use a non-HTTPS base URL. localhost / 127.0.0.1 are allowed for dev."
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
var _apiKey, _ApiClient_instances, mutate_fn;
|
|
32
|
+
var ApiClient = class {
|
|
33
|
+
constructor(opts) {
|
|
34
|
+
__privateAdd(this, _ApiClient_instances);
|
|
35
|
+
__privateAdd(this, _apiKey);
|
|
36
|
+
assertHttpsOrLocalhost(opts.baseUrl);
|
|
37
|
+
this.baseUrl = opts.baseUrl.replace(/\/$/, "");
|
|
38
|
+
__privateSet(this, _apiKey, opts.apiKey);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Issue a GET against `path` (must begin with `/`). Returns the parsed
|
|
42
|
+
* JSON on 200. Throws an Error whose message is safe to print (key
|
|
43
|
+
* redacted, status included).
|
|
44
|
+
*/
|
|
45
|
+
async get(path) {
|
|
46
|
+
const url = `${this.baseUrl}${path}`;
|
|
47
|
+
let res;
|
|
48
|
+
try {
|
|
49
|
+
res = await fetch(url, {
|
|
50
|
+
method: "GET",
|
|
51
|
+
headers: {
|
|
52
|
+
"x-openbat-key": __privateGet(this, _apiKey),
|
|
53
|
+
accept: "application/json"
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
} catch (err) {
|
|
57
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
58
|
+
throw new Error(`Request to ${redact(url)} failed: ${redact(msg)}`);
|
|
59
|
+
}
|
|
60
|
+
return parseResponse(res, url);
|
|
61
|
+
}
|
|
62
|
+
/** Issue a POST with a JSON body. */
|
|
63
|
+
async post(path, body) {
|
|
64
|
+
return __privateMethod(this, _ApiClient_instances, mutate_fn).call(this, "POST", path, body);
|
|
65
|
+
}
|
|
66
|
+
/** Issue a PATCH with a JSON body. */
|
|
67
|
+
async patch(path, body) {
|
|
68
|
+
return __privateMethod(this, _ApiClient_instances, mutate_fn).call(this, "PATCH", path, body);
|
|
69
|
+
}
|
|
70
|
+
/** Issue a DELETE. Body is rarely used; we still allow it. */
|
|
71
|
+
async delete(path, body) {
|
|
72
|
+
return __privateMethod(this, _ApiClient_instances, mutate_fn).call(this, "DELETE", path, body);
|
|
73
|
+
}
|
|
74
|
+
/** Pass-through for streaming endpoints (export). Returns the raw body. */
|
|
75
|
+
async getRaw(path) {
|
|
76
|
+
const url = `${this.baseUrl}${path}`;
|
|
77
|
+
const res = await fetch(url, {
|
|
78
|
+
method: "GET",
|
|
79
|
+
headers: {
|
|
80
|
+
"x-openbat-key": __privateGet(this, _apiKey)
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
if (!res.ok || !res.body) {
|
|
84
|
+
const errText = await res.text().catch(() => "");
|
|
85
|
+
throw new Error(
|
|
86
|
+
`GET ${redact(url)} \u2192 ${res.status} ${res.statusText}${errText ? `: ${redact(errText.slice(0, 200))}` : ""}`
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
body: res.body,
|
|
91
|
+
contentType: res.headers.get("content-type") ?? "application/octet-stream"
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
_apiKey = new WeakMap();
|
|
96
|
+
_ApiClient_instances = new WeakSet();
|
|
97
|
+
mutate_fn = async function(method, path, body) {
|
|
98
|
+
const url = `${this.baseUrl}${path}`;
|
|
99
|
+
let res;
|
|
100
|
+
try {
|
|
101
|
+
res = await fetch(url, {
|
|
102
|
+
method,
|
|
103
|
+
headers: {
|
|
104
|
+
"x-openbat-key": __privateGet(this, _apiKey),
|
|
105
|
+
"content-type": "application/json",
|
|
106
|
+
accept: "application/json"
|
|
107
|
+
},
|
|
108
|
+
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
109
|
+
});
|
|
110
|
+
} catch (err) {
|
|
111
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
112
|
+
throw new Error(`Request to ${redact(url)} failed: ${redact(msg)}`);
|
|
113
|
+
}
|
|
114
|
+
return parseResponse(res, url);
|
|
115
|
+
};
|
|
116
|
+
async function parseResponse(res, url) {
|
|
117
|
+
if (res.status === 401) {
|
|
118
|
+
throw new Error(
|
|
119
|
+
"Unauthorized. The API key was rejected (invalid, wrong kind for this endpoint, expired, or revoked)."
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
if (res.status === 403) {
|
|
123
|
+
throw new Error(
|
|
124
|
+
"Forbidden. The credential is valid but lacks permission for this operation (e.g. read-scope PAT can't mutate)."
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
if (res.status === 429) {
|
|
128
|
+
const retry = res.headers.get("retry-after");
|
|
129
|
+
throw new Error(
|
|
130
|
+
`Rate limited.${retry ? ` Retry after ${retry}s.` : ""}`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
if (!res.ok) {
|
|
134
|
+
let errBody = null;
|
|
135
|
+
try {
|
|
136
|
+
errBody = await res.json();
|
|
137
|
+
} catch {
|
|
138
|
+
}
|
|
139
|
+
throw new Error(
|
|
140
|
+
`GET ${redact(url)} \u2192 ${res.status} ${res.statusText}${errBody?.error ? `: ${redact(errBody.error)}` : ""}`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
return await res.json();
|
|
145
|
+
} catch {
|
|
146
|
+
throw new Error(`Response from ${redact(url)} was not valid JSON`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export {
|
|
151
|
+
ApiClient
|
|
152
|
+
};
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|