@levr-one/cli 0.10.22 → 0.11.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/dist/{appendHandler-u-NvHPDW.js → appendHandler-zXJBeRgd.js} +4 -4
- package/dist/{artifact-upload-CF2iXUiR.js → artifact-upload-BzLxue32.js} +1 -1
- package/dist/{attachHandler-DgVCvhz7.js → attachHandler-DpRsFzK6.js} +4 -4
- package/dist/cli.js +10 -10
- package/dist/{connect-DX41Im8c.js → connect-BejNz1AN.js} +2 -2
- package/dist/{importHandler-CUUroX_n.js → importHandler-COsRys7V.js} +49 -2
- package/dist/{listHandler-CB_9cISi.js → listHandler-hmLz8zm8.js} +1 -1
- package/dist/{loginHandler-DSznhtmk.js → loginHandler-Da8Krwq6.js} +2 -2
- package/dist/{pushHandler-Q9Cbo2HC.js → pushHandler-BV2jnZdQ.js} +3 -3
- package/dist/{resolve-workspace-B3Gz3-Vh.js → resolve-workspace-DcTNXtBD.js} +1 -1
- package/dist/{runHandler-DmRAoyJc.js → runHandler-B8UYWGf9.js} +41 -2
- package/dist/sdk-client-DYv-0CfA.js +405 -0
- package/dist/{selectHandler-CdOVuuTa.js → selectHandler-DNb1KJvM.js} +1 -1
- package/dist/{statusHandler-p6CmwgjS.js → statusHandler-B_xmACZl.js} +1 -1
- package/package.json +1 -1
- package/dist/sdk-client-CTvYVr7D.js +0 -32201
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
import { getApiUrl } from "./env-CdwyPHGV.js";
|
|
2
|
+
|
|
3
|
+
//#region ../sdk-public/dist/runtime/client.js
|
|
4
|
+
function createInterceptorManager() {
|
|
5
|
+
const _fns = [];
|
|
6
|
+
return {
|
|
7
|
+
_fns,
|
|
8
|
+
use(fn) {
|
|
9
|
+
_fns.push(fn);
|
|
10
|
+
},
|
|
11
|
+
eject(fn) {
|
|
12
|
+
const idx = _fns.indexOf(fn);
|
|
13
|
+
if (idx !== -1) _fns[idx] = void 0;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function buildPath(urlTemplate, pathParams) {
|
|
18
|
+
if (!pathParams) return urlTemplate;
|
|
19
|
+
return urlTemplate.replace(/\{(\w+)\}/g, (_, key) => {
|
|
20
|
+
const val = pathParams[key];
|
|
21
|
+
if (val === void 0) return `{${key}}`;
|
|
22
|
+
const str = typeof val === "object" && val !== null ? JSON.stringify(val) : String(val);
|
|
23
|
+
return encodeURIComponent(str);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function buildQuery(query) {
|
|
27
|
+
if (!query) return "";
|
|
28
|
+
const params = new URLSearchParams();
|
|
29
|
+
for (const [key, value] of Object.entries(query)) {
|
|
30
|
+
if (value === null || value === void 0) continue;
|
|
31
|
+
if (Array.isArray(value)) {
|
|
32
|
+
for (const item of value) if (item !== null && item !== void 0) params.append(key, String(item));
|
|
33
|
+
} else if (typeof value === "object") params.append(key, JSON.stringify(value));
|
|
34
|
+
else params.append(key, String(value));
|
|
35
|
+
}
|
|
36
|
+
const str = params.toString();
|
|
37
|
+
return str ? `?${str}` : "";
|
|
38
|
+
}
|
|
39
|
+
async function setAuthHeader(headers, config, security) {
|
|
40
|
+
if (!security?.length || !config.auth) return;
|
|
41
|
+
const scheme = security[0];
|
|
42
|
+
if (!scheme) return;
|
|
43
|
+
let token;
|
|
44
|
+
if (typeof config.auth === "function") token = await config.auth(scheme);
|
|
45
|
+
else token = config.auth;
|
|
46
|
+
if (token) {
|
|
47
|
+
const prefix = token.startsWith("Bearer ") ? "" : "Bearer ";
|
|
48
|
+
headers.set("Authorization", `${prefix}${token}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function createClient(initialConfig = {}) {
|
|
52
|
+
let _config = { ...initialConfig };
|
|
53
|
+
const interceptors = {
|
|
54
|
+
request: createInterceptorManager(),
|
|
55
|
+
response: createInterceptorManager(),
|
|
56
|
+
error: createInterceptorManager()
|
|
57
|
+
};
|
|
58
|
+
const getConfig = () => ({ ..._config });
|
|
59
|
+
const setConfig = (config) => {
|
|
60
|
+
_config = { ...config };
|
|
61
|
+
return getConfig();
|
|
62
|
+
};
|
|
63
|
+
const request = async (options) => {
|
|
64
|
+
const fetchFn = _config.fetch ?? globalThis.fetch;
|
|
65
|
+
const url = `${(typeof _config.baseUrl === "function" ? _config.baseUrl() : _config.baseUrl) ?? ""}${buildPath(options.url, options.path)}${buildQuery(options.query)}`;
|
|
66
|
+
const headers = new Headers();
|
|
67
|
+
if (_config.headers) for (const [k, v] of Object.entries(_config.headers)) headers.set(k, v);
|
|
68
|
+
if (options.headers) for (const [k, v] of Object.entries(options.headers)) headers.set(k, v);
|
|
69
|
+
if (_config.workspaceId) {
|
|
70
|
+
if (!headers.has("Workspace-Id")) headers.set("Workspace-Id", _config.workspaceId);
|
|
71
|
+
}
|
|
72
|
+
await setAuthHeader(headers, _config, options.security);
|
|
73
|
+
let body;
|
|
74
|
+
if (options.body !== void 0) if (options.bodySerializer) {
|
|
75
|
+
const serialized = options.bodySerializer(options.body);
|
|
76
|
+
if (serialized instanceof FormData) {
|
|
77
|
+
body = serialized;
|
|
78
|
+
headers.delete("Content-Type");
|
|
79
|
+
} else body = serialized;
|
|
80
|
+
} else if (options.body instanceof FormData) {
|
|
81
|
+
body = options.body;
|
|
82
|
+
headers.delete("Content-Type");
|
|
83
|
+
} else {
|
|
84
|
+
body = JSON.stringify(options.body);
|
|
85
|
+
if (!headers.has("Content-Type")) headers.set("Content-Type", "application/json");
|
|
86
|
+
}
|
|
87
|
+
else headers.delete("Content-Type");
|
|
88
|
+
if (options.requestValidator) await options.requestValidator(options);
|
|
89
|
+
let req = new Request(url, {
|
|
90
|
+
method: options.method ?? "GET",
|
|
91
|
+
headers,
|
|
92
|
+
body,
|
|
93
|
+
redirect: "follow",
|
|
94
|
+
credentials: "include"
|
|
95
|
+
});
|
|
96
|
+
for (const fn of interceptors.request._fns) if (fn) req = await fn(req, options);
|
|
97
|
+
let response = await fetchFn(req);
|
|
98
|
+
for (const fn of interceptors.response._fns) if (fn) response = await fn(response, req, options);
|
|
99
|
+
const result = {
|
|
100
|
+
request: req,
|
|
101
|
+
response
|
|
102
|
+
};
|
|
103
|
+
if (response.ok) {
|
|
104
|
+
if (response.status === 204 || response.headers.get("Content-Length") === "0") return {
|
|
105
|
+
ok: true,
|
|
106
|
+
data: {},
|
|
107
|
+
error: void 0,
|
|
108
|
+
...result
|
|
109
|
+
};
|
|
110
|
+
const parseAs = options.parseAs ?? "json";
|
|
111
|
+
let data;
|
|
112
|
+
if (parseAs === "stream") return {
|
|
113
|
+
ok: true,
|
|
114
|
+
data: response.body,
|
|
115
|
+
error: void 0,
|
|
116
|
+
...result
|
|
117
|
+
};
|
|
118
|
+
if (parseAs === "auto" || parseAs === "json") if ((response.headers.get("Content-Type") ?? "").includes("json")) data = await response.json();
|
|
119
|
+
else data = await response.text();
|
|
120
|
+
else data = await response[parseAs]();
|
|
121
|
+
if (parseAs === "json" && options.responseTransformer) data = await options.responseTransformer(data);
|
|
122
|
+
return {
|
|
123
|
+
ok: true,
|
|
124
|
+
data,
|
|
125
|
+
error: void 0,
|
|
126
|
+
...result
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
const textError = await response.text();
|
|
130
|
+
let jsonError;
|
|
131
|
+
try {
|
|
132
|
+
jsonError = JSON.parse(textError);
|
|
133
|
+
} catch {}
|
|
134
|
+
let error = jsonError ?? textError;
|
|
135
|
+
for (const fn of interceptors.error._fns) if (fn) error = await fn(error, response, req, options);
|
|
136
|
+
error = error || {};
|
|
137
|
+
if (options.throwOnError) throw error;
|
|
138
|
+
return {
|
|
139
|
+
ok: false,
|
|
140
|
+
data: void 0,
|
|
141
|
+
error,
|
|
142
|
+
...result
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
return {
|
|
146
|
+
getConfig,
|
|
147
|
+
setConfig,
|
|
148
|
+
request,
|
|
149
|
+
get: (options) => request({
|
|
150
|
+
...options,
|
|
151
|
+
method: "GET"
|
|
152
|
+
}),
|
|
153
|
+
post: (options) => request({
|
|
154
|
+
...options,
|
|
155
|
+
method: "POST"
|
|
156
|
+
}),
|
|
157
|
+
put: (options) => request({
|
|
158
|
+
...options,
|
|
159
|
+
method: "PUT"
|
|
160
|
+
}),
|
|
161
|
+
patch: (options) => request({
|
|
162
|
+
...options,
|
|
163
|
+
method: "PATCH"
|
|
164
|
+
}),
|
|
165
|
+
delete: (options) => request({
|
|
166
|
+
...options,
|
|
167
|
+
method: "DELETE"
|
|
168
|
+
}),
|
|
169
|
+
interceptors
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
//#endregion
|
|
174
|
+
//#region ../sdk-public/dist/runtime/index.js
|
|
175
|
+
const defaultConfig = { baseUrl: "https://api.levr.one" };
|
|
176
|
+
const client = createClient(defaultConfig);
|
|
177
|
+
|
|
178
|
+
//#endregion
|
|
179
|
+
//#region ../sdk-public/dist/gen/attachment-upload/functions.js
|
|
180
|
+
/** POST /v1/attachment/upload */
|
|
181
|
+
const attachmentUploadUploadV1 = (options) => {
|
|
182
|
+
return (options?.client ?? client).post({
|
|
183
|
+
security: [{
|
|
184
|
+
scheme: "bearer",
|
|
185
|
+
type: "http"
|
|
186
|
+
}],
|
|
187
|
+
url: "/v1/attachment/upload",
|
|
188
|
+
bodySerializer: (body) => {
|
|
189
|
+
const fd = new FormData();
|
|
190
|
+
if (body && typeof body === "object") for (const [k, v] of Object.entries(body)) {
|
|
191
|
+
if (v == null) continue;
|
|
192
|
+
fd.append(k, v instanceof Blob ? v : String(v));
|
|
193
|
+
}
|
|
194
|
+
return fd;
|
|
195
|
+
},
|
|
196
|
+
...options
|
|
197
|
+
});
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
//#endregion
|
|
201
|
+
//#region ../sdk-public/dist/gen/auth/functions.js
|
|
202
|
+
/** GET /v1/auth/profile */
|
|
203
|
+
const authGetProfileV1 = (options) => {
|
|
204
|
+
return (options?.client ?? client).get({
|
|
205
|
+
security: [{
|
|
206
|
+
scheme: "bearer",
|
|
207
|
+
type: "http"
|
|
208
|
+
}],
|
|
209
|
+
url: "/v1/auth/profile",
|
|
210
|
+
...options
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
/** GET /v1/auth/sites */
|
|
214
|
+
const authGetSitesV1 = (options) => {
|
|
215
|
+
return (options?.client ?? client).get({
|
|
216
|
+
security: [{
|
|
217
|
+
scheme: "bearer",
|
|
218
|
+
type: "http"
|
|
219
|
+
}],
|
|
220
|
+
url: "/v1/auth/sites",
|
|
221
|
+
...options
|
|
222
|
+
});
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
//#endregion
|
|
226
|
+
//#region ../sdk-public/dist/gen/comment-issue/functions.js
|
|
227
|
+
/** POST /v1/comment-issue */
|
|
228
|
+
const commentIssueCreateV1 = (options) => {
|
|
229
|
+
return (options?.client ?? client).post({
|
|
230
|
+
security: [{
|
|
231
|
+
scheme: "bearer",
|
|
232
|
+
type: "http"
|
|
233
|
+
}],
|
|
234
|
+
url: "/v1/comment-issue",
|
|
235
|
+
...options
|
|
236
|
+
});
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
//#endregion
|
|
240
|
+
//#region ../sdk-public/dist/gen/comment-run/functions.js
|
|
241
|
+
/** POST /v1/comment-run */
|
|
242
|
+
const commentRunCreateV1 = (options) => {
|
|
243
|
+
return (options?.client ?? client).post({
|
|
244
|
+
security: [{
|
|
245
|
+
scheme: "bearer",
|
|
246
|
+
type: "http"
|
|
247
|
+
}],
|
|
248
|
+
url: "/v1/comment-run",
|
|
249
|
+
...options
|
|
250
|
+
});
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
//#endregion
|
|
254
|
+
//#region ../sdk-public/dist/gen/comment-test/functions.js
|
|
255
|
+
/** POST /v1/comment-test */
|
|
256
|
+
const commentTestCreateV1 = (options) => {
|
|
257
|
+
return (options?.client ?? client).post({
|
|
258
|
+
security: [{
|
|
259
|
+
scheme: "bearer",
|
|
260
|
+
type: "http"
|
|
261
|
+
}],
|
|
262
|
+
url: "/v1/comment-test",
|
|
263
|
+
...options
|
|
264
|
+
});
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
//#endregion
|
|
268
|
+
//#region ../sdk-public/dist/gen/import/functions.js
|
|
269
|
+
/** POST /v1/imports */
|
|
270
|
+
const importCreateV1 = (options) => {
|
|
271
|
+
return (options?.client ?? client).post({
|
|
272
|
+
security: [{
|
|
273
|
+
scheme: "bearer",
|
|
274
|
+
type: "http"
|
|
275
|
+
}],
|
|
276
|
+
url: "/v1/imports",
|
|
277
|
+
bodySerializer: (body) => {
|
|
278
|
+
const fd = new FormData();
|
|
279
|
+
if (body && typeof body === "object") for (const [k, v] of Object.entries(body)) {
|
|
280
|
+
if (v == null) continue;
|
|
281
|
+
fd.append(k, v instanceof Blob ? v : String(v));
|
|
282
|
+
}
|
|
283
|
+
return fd;
|
|
284
|
+
},
|
|
285
|
+
...options
|
|
286
|
+
});
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
//#endregion
|
|
290
|
+
//#region ../sdk-public/dist/gen/run-api/functions.js
|
|
291
|
+
/** PATCH /v1/run/run-result-variant/{runResultVariantId} */
|
|
292
|
+
const runApiUpdateRunResultVariantByIdV1 = (options) => {
|
|
293
|
+
return (options?.client ?? client).patch({
|
|
294
|
+
security: [{
|
|
295
|
+
scheme: "bearer",
|
|
296
|
+
type: "http"
|
|
297
|
+
}],
|
|
298
|
+
url: "/v1/run/run-result-variant/{runResultVariantId}",
|
|
299
|
+
...options
|
|
300
|
+
});
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
//#endregion
|
|
304
|
+
//#region src/utils/sdk-client.ts
|
|
305
|
+
/**
|
|
306
|
+
* Configure the SDK client with the resolved auth token and API URL.
|
|
307
|
+
*/
|
|
308
|
+
function configureClient(auth, workspaceId) {
|
|
309
|
+
client.setConfig({
|
|
310
|
+
baseUrl: getApiUrl(),
|
|
311
|
+
auth: () => auth.token,
|
|
312
|
+
workspaceId
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Upload a test result file via the generated SDK function.
|
|
317
|
+
* importCreateV1 handles auth, FormData serialization, and Content-Type automatically.
|
|
318
|
+
*
|
|
319
|
+
* Note: requestValidator is disabled because the generated Zod schema types
|
|
320
|
+
* `file` as z.string() (from OpenAPI `format: binary`) but we pass a File object.
|
|
321
|
+
* The server validates the actual multipart payload.
|
|
322
|
+
*/
|
|
323
|
+
async function uploadImport(options) {
|
|
324
|
+
const result = await importCreateV1({
|
|
325
|
+
body: {
|
|
326
|
+
file: options.file,
|
|
327
|
+
team_id: options.teamId,
|
|
328
|
+
format: options.format,
|
|
329
|
+
run_name: options.runName,
|
|
330
|
+
automation_source: options.automationSource,
|
|
331
|
+
automation_source_id: options.automationSourceId,
|
|
332
|
+
import_metadata: options.importMetadata ? JSON.stringify(options.importMetadata) : void 0,
|
|
333
|
+
include_results: options.includeResults ? true : void 0
|
|
334
|
+
},
|
|
335
|
+
requestValidator: void 0
|
|
336
|
+
});
|
|
337
|
+
if (result.error) {
|
|
338
|
+
const status = result.response?.status;
|
|
339
|
+
switch (status) {
|
|
340
|
+
case 401: throw new Error("Authentication failed. Check your token or run 'levr auth login'.");
|
|
341
|
+
case 403: throw new Error("Permission denied. Check your team access.");
|
|
342
|
+
case 404: throw new Error(tryReadMessage(result.error) ?? "Not found. Check --automation-source and --team-id.");
|
|
343
|
+
case 422: throw new Error("File could not be processed. Check the file format.");
|
|
344
|
+
case 429: throw new Error("Rate limited. Please try again later.");
|
|
345
|
+
default: throw new Error(`Import failed (${String(status ?? "unknown")}): ${JSON.stringify(result.error)}`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return result.data;
|
|
349
|
+
}
|
|
350
|
+
function tryReadMessage(err) {
|
|
351
|
+
if (err && typeof err === "object" && "message" in err) {
|
|
352
|
+
const m = err.message;
|
|
353
|
+
return typeof m === "string" ? m : void 0;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
async function uploadAttachment(body) {
|
|
357
|
+
const result = await attachmentUploadUploadV1({
|
|
358
|
+
body,
|
|
359
|
+
requestValidator: void 0
|
|
360
|
+
});
|
|
361
|
+
return {
|
|
362
|
+
status: result.response?.status ?? 0,
|
|
363
|
+
data: result.data,
|
|
364
|
+
error: result.error
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Server-side append to an execution result's actual_result, addressed by
|
|
369
|
+
* the variant id alone (ENG-6161 PATCH /v1/run/run-result-variant/:id). Never
|
|
370
|
+
* a read-modify-write: the server appends.
|
|
371
|
+
*/
|
|
372
|
+
async function appendActualResult(runResultVariantId, text) {
|
|
373
|
+
const result = await runApiUpdateRunResultVariantByIdV1({
|
|
374
|
+
path: { runResultVariantId },
|
|
375
|
+
body: { append_actual_result: text },
|
|
376
|
+
requestValidator: void 0
|
|
377
|
+
});
|
|
378
|
+
if (result.error) throw new Error(`Append failed (${String(result.response?.status ?? "unknown")}): ${tryReadMessage(result.error) ?? JSON.stringify(result.error)}`);
|
|
379
|
+
}
|
|
380
|
+
/** A NEW comment on an issue, test or run (append-only; ENG-6164 --embed). */
|
|
381
|
+
async function createComment(target, targetId, body) {
|
|
382
|
+
const result = target === "issue" ? await commentIssueCreateV1({
|
|
383
|
+
body: {
|
|
384
|
+
issue_id: targetId,
|
|
385
|
+
body
|
|
386
|
+
},
|
|
387
|
+
requestValidator: void 0
|
|
388
|
+
}) : target === "test" ? await commentTestCreateV1({
|
|
389
|
+
body: {
|
|
390
|
+
test_id: targetId,
|
|
391
|
+
body
|
|
392
|
+
},
|
|
393
|
+
requestValidator: void 0
|
|
394
|
+
}) : await commentRunCreateV1({
|
|
395
|
+
body: {
|
|
396
|
+
run_id: targetId,
|
|
397
|
+
body
|
|
398
|
+
},
|
|
399
|
+
requestValidator: void 0
|
|
400
|
+
});
|
|
401
|
+
if (result.error) throw new Error(`Comment failed (${String(result.response?.status ?? "unknown")}): ${tryReadMessage(result.error) ?? JSON.stringify(result.error)}`);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
//#endregion
|
|
405
|
+
export { appendActualResult, authGetProfileV1, authGetSitesV1, client, configureClient, createComment, uploadAttachment, uploadImport };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { authGetSitesV1, configureClient } from "./sdk-client-
|
|
1
|
+
import { authGetSitesV1, configureClient } from "./sdk-client-DYv-0CfA.js";
|
|
2
2
|
import "./env-CdwyPHGV.js";
|
|
3
3
|
import "./token-refresh-DeusLK8H.js";
|
|
4
4
|
import { resolveToken } from "./resolve-token-7xb7kG7h.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { authGetProfileV1, configureClient } from "./sdk-client-
|
|
1
|
+
import { authGetProfileV1, configureClient } from "./sdk-client-DYv-0CfA.js";
|
|
2
2
|
import { getApiUrl, getPatToken, readCredentials } from "./env-CdwyPHGV.js";
|
|
3
3
|
import { isTokenExpired } from "./token-refresh-DeusLK8H.js";
|
|
4
4
|
import chalk from "chalk";
|