@honeyhive/control-plane-sdk 1.1.0 → 1.2.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/CHANGELOG.md +14 -0
- package/README.md +1 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/apiKeys.d.ts +46 -0
- package/dist/apiKeys.d.ts.map +1 -0
- package/dist/apiKeys.js +97 -0
- package/dist/apiKeys.js.map +1 -0
- package/dist/generated/apiTypes.d.ts +4 -0
- package/dist/generated/apiTypes.d.ts.map +1 -1
- package/dist/generated/client.d.ts +20 -11
- package/dist/generated/client.d.ts.map +1 -1
- package/dist/generated/client.js +53 -42
- package/dist/generated/client.js.map +1 -1
- package/dist/generated/types.d.ts +22 -26
- package/dist/generated/types.d.ts.map +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/util.d.ts +12 -5
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +22 -65
- package/dist/util.js.map +1 -1
- package/package.json +2 -2
- package/release_notes.md +9 -8
- package/src/apiKeys.ts +103 -0
- package/src/generated/apiTypes.ts +4 -0
- package/src/generated/client.ts +66 -42
- package/src/generated/types.ts +22 -26
- package/src/generated/version.ts +1 -1
- package/src/util.ts +32 -75
package/src/generated/client.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// AUTO-GENERATED — do not edit manually. Run `pnpm turbo run generate` to regenerate.
|
|
2
2
|
|
|
3
|
+
import { type Client as OpenapiFetchClient } from 'openapi-fetch';
|
|
4
|
+
|
|
3
5
|
import { type paths } from './types.js';
|
|
4
6
|
import {
|
|
5
7
|
type ListAlertsRequest,
|
|
@@ -35,12 +37,23 @@ import {
|
|
|
35
37
|
} from './apiTypes.js';
|
|
36
38
|
import { type ClientConfig, type FetchOptions, createApiClient, unwrap } from '../util.js';
|
|
37
39
|
|
|
40
|
+
/** Every security scheme the API's OpenAPI spec defines. */
|
|
41
|
+
export type SecurityScheme = 'ControlPlaneApiKey';
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* What `createApiClient` returns: for every security scheme the spec defines,
|
|
45
|
+
* the openapi-fetch client that carries the credential for it. The hand-written
|
|
46
|
+
* chassis builds this table, so a scheme added to or removed from the spec
|
|
47
|
+
* fails to compile there until the table says which client serves it.
|
|
48
|
+
*/
|
|
49
|
+
export type ApiClients = Record<SecurityScheme, OpenapiFetchClient<paths>>;
|
|
50
|
+
|
|
38
51
|
/** @inline */
|
|
39
52
|
class AlertsNamespace {
|
|
40
|
-
#
|
|
53
|
+
#clients: ApiClients;
|
|
41
54
|
|
|
42
|
-
constructor(
|
|
43
|
-
this.#
|
|
55
|
+
constructor(clients: ApiClients) {
|
|
56
|
+
this.#clients = clients;
|
|
44
57
|
}
|
|
45
58
|
|
|
46
59
|
/**
|
|
@@ -52,8 +65,9 @@ class AlertsNamespace {
|
|
|
52
65
|
*/
|
|
53
66
|
public list(request: ListAlertsRequest, options?: FetchOptions): Promise<ListAlertsResponse> {
|
|
54
67
|
const { project_id, page, limit, status, sort_by, sort_order } = request;
|
|
68
|
+
const httpClient = this.#clients.ControlPlaneApiKey;
|
|
55
69
|
return unwrap(
|
|
56
|
-
|
|
70
|
+
httpClient.GET('/v1/projects/{project_id}/alerts', {
|
|
57
71
|
params: { path: { project_id }, query: { page, limit, status, sort_by, sort_order } },
|
|
58
72
|
...options,
|
|
59
73
|
}),
|
|
@@ -71,8 +85,9 @@ class AlertsNamespace {
|
|
|
71
85
|
*/
|
|
72
86
|
public create(request: CreateAlertRequest, options?: FetchOptions): Promise<CreateAlertResponse> {
|
|
73
87
|
const { project_id, ...body } = request;
|
|
88
|
+
const httpClient = this.#clients.ControlPlaneApiKey;
|
|
74
89
|
return unwrap(
|
|
75
|
-
|
|
90
|
+
httpClient.POST('/v1/projects/{project_id}/alerts', {
|
|
76
91
|
params: { path: { project_id } },
|
|
77
92
|
body,
|
|
78
93
|
...options,
|
|
@@ -89,8 +104,9 @@ class AlertsNamespace {
|
|
|
89
104
|
*/
|
|
90
105
|
public get(request: GetAlertRequest, options?: FetchOptions): Promise<GetAlertResponse> {
|
|
91
106
|
const { project_id, alert_id } = request;
|
|
107
|
+
const httpClient = this.#clients.ControlPlaneApiKey;
|
|
92
108
|
return unwrap(
|
|
93
|
-
|
|
109
|
+
httpClient.GET('/v1/projects/{project_id}/alerts/{alert_id}', {
|
|
94
110
|
params: { path: { project_id, alert_id } },
|
|
95
111
|
...options,
|
|
96
112
|
}),
|
|
@@ -100,10 +116,10 @@ class AlertsNamespace {
|
|
|
100
116
|
|
|
101
117
|
/** @inline */
|
|
102
118
|
class WorkspacesNamespace {
|
|
103
|
-
#
|
|
119
|
+
#clients: ApiClients;
|
|
104
120
|
|
|
105
|
-
constructor(
|
|
106
|
-
this.#
|
|
121
|
+
constructor(clients: ApiClients) {
|
|
122
|
+
this.#clients = clients;
|
|
107
123
|
}
|
|
108
124
|
|
|
109
125
|
/**
|
|
@@ -140,8 +156,9 @@ class WorkspacesNamespace {
|
|
|
140
156
|
options?: FetchOptions,
|
|
141
157
|
): Promise<CreateWorkspaceResponse> {
|
|
142
158
|
const { virtual_dataplane_id, ...body } = request;
|
|
159
|
+
const httpClient = this.#clients.ControlPlaneApiKey;
|
|
143
160
|
return unwrap(
|
|
144
|
-
|
|
161
|
+
httpClient.POST('/v1/virtual_dataplanes/{virtual_dataplane_id}/workspaces', {
|
|
145
162
|
params: { path: { virtual_dataplane_id } },
|
|
146
163
|
body,
|
|
147
164
|
...options,
|
|
@@ -160,8 +177,9 @@ class WorkspacesNamespace {
|
|
|
160
177
|
*/
|
|
161
178
|
public get(request: GetWorkspaceRequest, options?: FetchOptions): Promise<GetWorkspaceResponse> {
|
|
162
179
|
const { workspace_id } = request;
|
|
180
|
+
const httpClient = this.#clients.ControlPlaneApiKey;
|
|
163
181
|
return unwrap(
|
|
164
|
-
|
|
182
|
+
httpClient.GET('/v1/workspaces/{workspace_id}', {
|
|
165
183
|
params: { path: { workspace_id } },
|
|
166
184
|
...options,
|
|
167
185
|
}),
|
|
@@ -182,8 +200,9 @@ class WorkspacesNamespace {
|
|
|
182
200
|
options?: FetchOptions,
|
|
183
201
|
): Promise<UpdateWorkspaceResponse> {
|
|
184
202
|
const { workspace_id, ...body } = request;
|
|
203
|
+
const httpClient = this.#clients.ControlPlaneApiKey;
|
|
185
204
|
return unwrap(
|
|
186
|
-
|
|
205
|
+
httpClient.PUT('/v1/workspaces/{workspace_id}', {
|
|
187
206
|
params: { path: { workspace_id } },
|
|
188
207
|
body,
|
|
189
208
|
...options,
|
|
@@ -213,8 +232,9 @@ class WorkspacesNamespace {
|
|
|
213
232
|
options?: FetchOptions,
|
|
214
233
|
): Promise<DeleteWorkspaceResponse> {
|
|
215
234
|
const { workspace_id, dangerously_delete_child_scopes } = request;
|
|
235
|
+
const httpClient = this.#clients.ControlPlaneApiKey;
|
|
216
236
|
return unwrap(
|
|
217
|
-
|
|
237
|
+
httpClient.DELETE('/v1/workspaces/{workspace_id}', {
|
|
218
238
|
params: { path: { workspace_id }, query: { dangerously_delete_child_scopes } },
|
|
219
239
|
...options,
|
|
220
240
|
}),
|
|
@@ -224,10 +244,10 @@ class WorkspacesNamespace {
|
|
|
224
244
|
|
|
225
245
|
/** @inline */
|
|
226
246
|
class ProjectsNamespace {
|
|
227
|
-
#
|
|
247
|
+
#clients: ApiClients;
|
|
228
248
|
|
|
229
|
-
constructor(
|
|
230
|
-
this.#
|
|
249
|
+
constructor(clients: ApiClients) {
|
|
250
|
+
this.#clients = clients;
|
|
231
251
|
}
|
|
232
252
|
|
|
233
253
|
/**
|
|
@@ -259,8 +279,9 @@ class ProjectsNamespace {
|
|
|
259
279
|
options?: FetchOptions,
|
|
260
280
|
): Promise<CreateProjectResponse> {
|
|
261
281
|
const { workspace_id, ...body } = request;
|
|
282
|
+
const httpClient = this.#clients.ControlPlaneApiKey;
|
|
262
283
|
return unwrap(
|
|
263
|
-
|
|
284
|
+
httpClient.POST('/v1/workspaces/{workspace_id}/projects', {
|
|
264
285
|
params: { path: { workspace_id } },
|
|
265
286
|
body,
|
|
266
287
|
...options,
|
|
@@ -276,11 +297,9 @@ class ProjectsNamespace {
|
|
|
276
297
|
*/
|
|
277
298
|
public get(request: GetProjectRequest, options?: FetchOptions): Promise<GetProjectResponse> {
|
|
278
299
|
const { project_id } = request;
|
|
300
|
+
const httpClient = this.#clients.ControlPlaneApiKey;
|
|
279
301
|
return unwrap(
|
|
280
|
-
|
|
281
|
-
params: { path: { project_id } },
|
|
282
|
-
...options,
|
|
283
|
-
}),
|
|
302
|
+
httpClient.GET('/v1/projects/{project_id}', { params: { path: { project_id } }, ...options }),
|
|
284
303
|
);
|
|
285
304
|
}
|
|
286
305
|
|
|
@@ -296,8 +315,9 @@ class ProjectsNamespace {
|
|
|
296
315
|
options?: FetchOptions,
|
|
297
316
|
): Promise<UpdateProjectResponse> {
|
|
298
317
|
const { project_id, ...body } = request;
|
|
318
|
+
const httpClient = this.#clients.ControlPlaneApiKey;
|
|
299
319
|
return unwrap(
|
|
300
|
-
|
|
320
|
+
httpClient.PUT('/v1/projects/{project_id}', {
|
|
301
321
|
params: { path: { project_id } },
|
|
302
322
|
body,
|
|
303
323
|
...options,
|
|
@@ -317,8 +337,9 @@ class ProjectsNamespace {
|
|
|
317
337
|
options?: FetchOptions,
|
|
318
338
|
): Promise<DeleteProjectResponse> {
|
|
319
339
|
const { project_id } = request;
|
|
340
|
+
const httpClient = this.#clients.ControlPlaneApiKey;
|
|
320
341
|
return unwrap(
|
|
321
|
-
|
|
342
|
+
httpClient.DELETE('/v1/projects/{project_id}', {
|
|
322
343
|
params: { path: { project_id } },
|
|
323
344
|
...options,
|
|
324
345
|
}),
|
|
@@ -328,10 +349,10 @@ class ProjectsNamespace {
|
|
|
328
349
|
|
|
329
350
|
/** @inline */
|
|
330
351
|
class VirtualDataplanesNamespace {
|
|
331
|
-
#
|
|
352
|
+
#clients: ApiClients;
|
|
332
353
|
|
|
333
|
-
constructor(
|
|
334
|
-
this.#
|
|
354
|
+
constructor(clients: ApiClients) {
|
|
355
|
+
this.#clients = clients;
|
|
335
356
|
}
|
|
336
357
|
|
|
337
358
|
/**
|
|
@@ -355,12 +376,11 @@ class VirtualDataplanesNamespace {
|
|
|
355
376
|
* A cluster admits an organization only if your control plane administrator configured it to,
|
|
356
377
|
* so a `cluster_id` you can read from a sibling virtual data plane is not necessarily one you
|
|
357
378
|
* may place a new virtual data plane on. A cluster that does not admit this organization
|
|
358
|
-
* returns a
|
|
359
|
-
*
|
|
360
|
-
* to place the virtual data plane on another cluster.
|
|
379
|
+
* returns a 404. When this endpoint inferred the cluster, send an explicit `cluster_id` to
|
|
380
|
+
* place the virtual data plane on another cluster.
|
|
361
381
|
*
|
|
362
382
|
* Deployments differ in who places virtual data planes. Where HoneyHive assigns them to
|
|
363
|
-
* organizations automatically, this endpoint returns a
|
|
383
|
+
* organizations automatically, this endpoint returns a 404 for every request and the
|
|
364
384
|
* placement is not yours to make. Deployments whose administrators own the scope tree are
|
|
365
385
|
* the ones this endpoint serves.
|
|
366
386
|
*
|
|
@@ -385,8 +405,9 @@ class VirtualDataplanesNamespace {
|
|
|
385
405
|
options?: FetchOptions,
|
|
386
406
|
): Promise<CreateVirtualDataplaneResponse> {
|
|
387
407
|
const { org_id, ...body } = request;
|
|
408
|
+
const httpClient = this.#clients.ControlPlaneApiKey;
|
|
388
409
|
return unwrap(
|
|
389
|
-
|
|
410
|
+
httpClient.POST('/v1/orgs/{org_id}/virtual_dataplanes', {
|
|
390
411
|
params: { path: { org_id } },
|
|
391
412
|
body,
|
|
392
413
|
...options,
|
|
@@ -413,8 +434,9 @@ class VirtualDataplanesNamespace {
|
|
|
413
434
|
options?: FetchOptions,
|
|
414
435
|
): Promise<GetVirtualDataplaneResponse> {
|
|
415
436
|
const { virtual_dataplane_id } = request;
|
|
437
|
+
const httpClient = this.#clients.ControlPlaneApiKey;
|
|
416
438
|
return unwrap(
|
|
417
|
-
|
|
439
|
+
httpClient.GET('/v1/virtual_dataplanes/{virtual_dataplane_id}', {
|
|
418
440
|
params: { path: { virtual_dataplane_id } },
|
|
419
441
|
...options,
|
|
420
442
|
}),
|
|
@@ -433,15 +455,16 @@ class VirtualDataplanesNamespace {
|
|
|
433
455
|
* `name`, or sends the current one, changes nothing.
|
|
434
456
|
*
|
|
435
457
|
* This endpoint is unavailable where HoneyHive assigns virtual data planes automatically,
|
|
436
|
-
* and returns a
|
|
458
|
+
* and returns a 404 there.
|
|
437
459
|
*/
|
|
438
460
|
public update(
|
|
439
461
|
request: UpdateVirtualDataplaneRequest,
|
|
440
462
|
options?: FetchOptions,
|
|
441
463
|
): Promise<UpdateVirtualDataplaneResponse> {
|
|
442
464
|
const { virtual_dataplane_id, ...body } = request;
|
|
465
|
+
const httpClient = this.#clients.ControlPlaneApiKey;
|
|
443
466
|
return unwrap(
|
|
444
|
-
|
|
467
|
+
httpClient.PUT('/v1/virtual_dataplanes/{virtual_dataplane_id}', {
|
|
445
468
|
params: { path: { virtual_dataplane_id } },
|
|
446
469
|
body,
|
|
447
470
|
...options,
|
|
@@ -467,15 +490,16 @@ class VirtualDataplanesNamespace {
|
|
|
467
490
|
* archived, so read that first if you need the list.
|
|
468
491
|
*
|
|
469
492
|
* This endpoint is unavailable where HoneyHive assigns virtual data planes automatically,
|
|
470
|
-
* and returns a
|
|
493
|
+
* and returns a 404 there.
|
|
471
494
|
*/
|
|
472
495
|
public delete(
|
|
473
496
|
request: DeleteVirtualDataplaneRequest,
|
|
474
497
|
options?: FetchOptions,
|
|
475
498
|
): Promise<DeleteVirtualDataplaneResponse> {
|
|
476
499
|
const { virtual_dataplane_id, dangerously_delete_child_scopes } = request;
|
|
500
|
+
const httpClient = this.#clients.ControlPlaneApiKey;
|
|
477
501
|
return unwrap(
|
|
478
|
-
|
|
502
|
+
httpClient.DELETE('/v1/virtual_dataplanes/{virtual_dataplane_id}', {
|
|
479
503
|
params: { path: { virtual_dataplane_id }, query: { dangerously_delete_child_scopes } },
|
|
480
504
|
...options,
|
|
481
505
|
}),
|
|
@@ -484,17 +508,17 @@ class VirtualDataplanesNamespace {
|
|
|
484
508
|
}
|
|
485
509
|
|
|
486
510
|
export class Client {
|
|
487
|
-
#
|
|
511
|
+
#clients: ApiClients;
|
|
488
512
|
readonly alerts: AlertsNamespace;
|
|
489
513
|
readonly workspaces: WorkspacesNamespace;
|
|
490
514
|
readonly projects: ProjectsNamespace;
|
|
491
515
|
readonly virtualDataplanes: VirtualDataplanesNamespace;
|
|
492
516
|
|
|
493
517
|
constructor(options: ClientConfig = {}) {
|
|
494
|
-
this.#
|
|
495
|
-
this.alerts = new AlertsNamespace(this.#
|
|
496
|
-
this.workspaces = new WorkspacesNamespace(this.#
|
|
497
|
-
this.projects = new ProjectsNamespace(this.#
|
|
498
|
-
this.virtualDataplanes = new VirtualDataplanesNamespace(this.#
|
|
518
|
+
this.#clients = createApiClient(options);
|
|
519
|
+
this.alerts = new AlertsNamespace(this.#clients);
|
|
520
|
+
this.workspaces = new WorkspacesNamespace(this.#clients);
|
|
521
|
+
this.projects = new ProjectsNamespace(this.#clients);
|
|
522
|
+
this.virtualDataplanes = new VirtualDataplanesNamespace(this.#clients);
|
|
499
523
|
}
|
|
500
524
|
}
|
package/src/generated/types.ts
CHANGED
|
@@ -244,12 +244,11 @@ export interface paths {
|
|
|
244
244
|
* A cluster admits an organization only if your control plane administrator configured it to,
|
|
245
245
|
* so a `cluster_id` you can read from a sibling virtual data plane is not necessarily one you
|
|
246
246
|
* may place a new virtual data plane on. A cluster that does not admit this organization
|
|
247
|
-
* returns a
|
|
248
|
-
*
|
|
249
|
-
* to place the virtual data plane on another cluster.
|
|
247
|
+
* returns a 404. When this endpoint inferred the cluster, send an explicit `cluster_id` to
|
|
248
|
+
* place the virtual data plane on another cluster.
|
|
250
249
|
*
|
|
251
250
|
* Deployments differ in who places virtual data planes. Where HoneyHive assigns them to
|
|
252
|
-
* organizations automatically, this endpoint returns a
|
|
251
|
+
* organizations automatically, this endpoint returns a 404 for every request and the
|
|
253
252
|
* placement is not yours to make. Deployments whose administrators own the scope tree are
|
|
254
253
|
* the ones this endpoint serves.
|
|
255
254
|
*
|
|
@@ -308,7 +307,7 @@ export interface paths {
|
|
|
308
307
|
* `name`, or sends the current one, changes nothing.
|
|
309
308
|
*
|
|
310
309
|
* This endpoint is unavailable where HoneyHive assigns virtual data planes automatically,
|
|
311
|
-
* and returns a
|
|
310
|
+
* and returns a 404 there.
|
|
312
311
|
*/
|
|
313
312
|
put: operations['updateVirtualDataplane'];
|
|
314
313
|
post?: never;
|
|
@@ -329,7 +328,7 @@ export interface paths {
|
|
|
329
328
|
* archived, so read that first if you need the list.
|
|
330
329
|
*
|
|
331
330
|
* This endpoint is unavailable where HoneyHive assigns virtual data planes automatically,
|
|
332
|
-
* and returns a
|
|
331
|
+
* and returns a 404 there.
|
|
333
332
|
*/
|
|
334
333
|
delete: operations['deleteVirtualDataplane'];
|
|
335
334
|
options?: never;
|
|
@@ -560,6 +559,8 @@ export interface components {
|
|
|
560
559
|
PostVirtualDataplaneRequest: {
|
|
561
560
|
/** @description Virtual dataplane display name. Allowed characters are letters, digits, space, underscore, hyphen, apostrophe and ampersand. The name must contain at least one letter or digit, and must not start with a space. */
|
|
562
561
|
name: string;
|
|
562
|
+
/** @description Globally unique identifier for the virtual dataplane, letters, digits and underscores only. Omit it and the server derives one from the name with a random suffix appended. A slug already in use returns 409. */
|
|
563
|
+
slug?: string;
|
|
563
564
|
/** @description Physical cluster to host this virtual dataplane. Omit to place it alongside the existing virtual dataplanes in this org; required when the org has none yet, or when its virtual dataplanes span more than one cluster. */
|
|
564
565
|
cluster_id?: string;
|
|
565
566
|
/**
|
|
@@ -607,6 +608,8 @@ export interface components {
|
|
|
607
608
|
PostWorkspaceRequest: {
|
|
608
609
|
/** @description Workspace display name. Allowed characters are letters, digits, space, underscore, hyphen, apostrophe and ampersand. The name must contain at least one letter or digit, and must not start with a space. */
|
|
609
610
|
name: string;
|
|
611
|
+
/** @description Globally unique identifier for the workspace, letters, digits and underscores only. Omit it and the server derives one from the name with a random suffix appended. Supply it when the identifier has to match a value maintained outside HoneyHive, such as an identity provider group that grants access to this workspace. A slug already in use returns 409. */
|
|
612
|
+
slug?: string;
|
|
610
613
|
/** @description Workspace description */
|
|
611
614
|
description?: string;
|
|
612
615
|
/**
|
|
@@ -899,6 +902,13 @@ export interface operations {
|
|
|
899
902
|
};
|
|
900
903
|
content?: never;
|
|
901
904
|
};
|
|
905
|
+
/** @description The `slug` is already taken by another scope */
|
|
906
|
+
409: {
|
|
907
|
+
headers: {
|
|
908
|
+
[name: string]: unknown;
|
|
909
|
+
};
|
|
910
|
+
content?: never;
|
|
911
|
+
};
|
|
902
912
|
};
|
|
903
913
|
};
|
|
904
914
|
createProject: {
|
|
@@ -1196,15 +1206,15 @@ export interface operations {
|
|
|
1196
1206
|
};
|
|
1197
1207
|
content?: never;
|
|
1198
1208
|
};
|
|
1199
|
-
/** @description
|
|
1200
|
-
|
|
1209
|
+
/** @description Organization or cluster not found, or the caller may not create a virtual data plane here. The response does not say which. */
|
|
1210
|
+
404: {
|
|
1201
1211
|
headers: {
|
|
1202
1212
|
[name: string]: unknown;
|
|
1203
1213
|
};
|
|
1204
1214
|
content?: never;
|
|
1205
1215
|
};
|
|
1206
|
-
/** @description
|
|
1207
|
-
|
|
1216
|
+
/** @description The `slug` is already taken by another scope */
|
|
1217
|
+
409: {
|
|
1208
1218
|
headers: {
|
|
1209
1219
|
[name: string]: unknown;
|
|
1210
1220
|
};
|
|
@@ -1274,14 +1284,7 @@ export interface operations {
|
|
|
1274
1284
|
};
|
|
1275
1285
|
content?: never;
|
|
1276
1286
|
};
|
|
1277
|
-
/** @description
|
|
1278
|
-
403: {
|
|
1279
|
-
headers: {
|
|
1280
|
-
[name: string]: unknown;
|
|
1281
|
-
};
|
|
1282
|
-
content?: never;
|
|
1283
|
-
};
|
|
1284
|
-
/** @description Virtual data plane not found */
|
|
1287
|
+
/** @description Virtual data plane not found, or the caller may not update it, or this deployment assigns virtual data planes automatically. The response does not say which. */
|
|
1285
1288
|
404: {
|
|
1286
1289
|
headers: {
|
|
1287
1290
|
[name: string]: unknown;
|
|
@@ -1325,14 +1328,7 @@ export interface operations {
|
|
|
1325
1328
|
};
|
|
1326
1329
|
content?: never;
|
|
1327
1330
|
};
|
|
1328
|
-
/** @description
|
|
1329
|
-
403: {
|
|
1330
|
-
headers: {
|
|
1331
|
-
[name: string]: unknown;
|
|
1332
|
-
};
|
|
1333
|
-
content?: never;
|
|
1334
|
-
};
|
|
1335
|
-
/** @description Virtual data plane not found */
|
|
1331
|
+
/** @description Virtual data plane not found, or the caller may not delete it, or this deployment assigns virtual data planes automatically. The response does not say which. */
|
|
1336
1332
|
404: {
|
|
1337
1333
|
headers: {
|
|
1338
1334
|
[name: string]: unknown;
|
package/src/generated/version.ts
CHANGED
package/src/util.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
2
|
import createClient, { type ClientOptions, type Middleware } from 'openapi-fetch';
|
|
3
3
|
|
|
4
|
+
import { checkControlPlaneApiKey, maskApiKey } from './apiKeys.js';
|
|
5
|
+
import { type ApiClients } from './generated/client.js';
|
|
6
|
+
import { type paths } from './generated/types.js';
|
|
4
7
|
import { SDK_VERSION } from './generated/version.js';
|
|
5
8
|
|
|
6
9
|
// The control plane's public, API-key entrypoint. This is deliberately not the
|
|
@@ -36,68 +39,6 @@ function getEnv(key: string, defaultValue?: string): string | undefined {
|
|
|
36
39
|
return defaultValue;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
/**
|
|
40
|
-
* The prefix of a fine-grained control-plane API key, whose values have the
|
|
41
|
-
* shape `hh_fgcp_<key id>_<key secret>`. In practice this is the only credential
|
|
42
|
-
* the control plane's API accepts, but the SDK does not enforce that — the
|
|
43
|
-
* prefix's job here is masking: it identifies the values whose key id can be
|
|
44
|
-
* shown, and everything else is redacted wholesale.
|
|
45
|
-
*/
|
|
46
|
-
const FGCP_KEY_PREFIX = 'hh_fgcp_';
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* The shape of the key id segment of a fine-grained key value: exactly 24
|
|
50
|
-
* alphanumeric characters, with `_` and `-` excluded so that an id can never
|
|
51
|
-
* read as two segments.
|
|
52
|
-
*
|
|
53
|
-
* The length and the alphabet are fixed properties of the key format, so a value
|
|
54
|
-
* whose id segment doesn't match this either wasn't issued by HoneyHive or has
|
|
55
|
-
* been altered in transit — either way it is redacted rather than rendered.
|
|
56
|
-
*/
|
|
57
|
-
const FGCP_KEY_ID_PATTERN = /^[A-Za-z0-9]{24}$/;
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Returns a display-safe rendering of an API key for verbose logging.
|
|
61
|
-
*
|
|
62
|
-
* Renders `hh_fgcp_<key id>_******` — the key's id and none of its secret. This
|
|
63
|
-
* is character-for-character the masked form HoneyHive displays for that key, so
|
|
64
|
-
* a verbose log line can be matched directly against a key in your account.
|
|
65
|
-
* Masking from the id rather than from the secret is what makes it unique per
|
|
66
|
-
* key and free of secret material.
|
|
67
|
-
*
|
|
68
|
-
* The id is `_`-free by construction, so it is everything up to the first `_`
|
|
69
|
-
* after the prefix.
|
|
70
|
-
*
|
|
71
|
-
* Anything else collapses to 8 fixed-width asterisks, revealing neither its
|
|
72
|
-
* length nor its content. That covers both a value that isn't a fine-grained key
|
|
73
|
-
* at all — the SDK forwards whatever it is given, so this function must assume
|
|
74
|
-
* it may be handed a coarse-grained HoneyHive key or a credential belonging to
|
|
75
|
-
* some other system entirely — and a fine-grained value whose id segment is
|
|
76
|
-
* truncated or mangled, where the characters after the prefix could be secret
|
|
77
|
-
* material rather than an id.
|
|
78
|
-
*
|
|
79
|
-
* Both guards are load-bearing, and the prefix guard especially: without it the
|
|
80
|
-
* unconditional slice below would chop 8 characters off an arbitrary token and
|
|
81
|
-
* any value whose next 24 characters happened to be alphanumerics followed by
|
|
82
|
-
* `_` would render as `hh_fgcp_<24 chars of that token>_******`, echoing part of
|
|
83
|
-
* a foreign credential under our own prefix. So the output is always either
|
|
84
|
-
* exactly the server's mask or fully redacted, never a partial echo.
|
|
85
|
-
*/
|
|
86
|
-
function maskApiKey(apiKey: string): string {
|
|
87
|
-
if (!apiKey.startsWith(FGCP_KEY_PREFIX)) {
|
|
88
|
-
return '********';
|
|
89
|
-
}
|
|
90
|
-
const rest = apiKey.slice(FGCP_KEY_PREFIX.length);
|
|
91
|
-
const separator = rest.indexOf('_');
|
|
92
|
-
// An empty id never matches the pattern, so a value with no separator at all
|
|
93
|
-
// takes the redacted path without a second branch.
|
|
94
|
-
const keyId = separator === -1 ? '' : rest.slice(0, separator);
|
|
95
|
-
if (!FGCP_KEY_ID_PATTERN.test(keyId)) {
|
|
96
|
-
return '********';
|
|
97
|
-
}
|
|
98
|
-
return `${FGCP_KEY_PREFIX}${keyId}_******`;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
42
|
/**
|
|
102
43
|
* Configuration options for the HoneyHive Control Plane client. They extend the
|
|
103
44
|
* options from openapi-fetch, but replace 'baseUrl' with 'controlPlaneUrl' so
|
|
@@ -106,9 +47,10 @@ function maskApiKey(apiKey: string): string {
|
|
|
106
47
|
export interface ClientConfig extends Omit<ClientOptions, 'baseUrl' | 'headers'> {
|
|
107
48
|
/**
|
|
108
49
|
* A fine-grained control-plane API key (`hh_fgcp_…`), the only credential the
|
|
109
|
-
* control plane's API accepts
|
|
110
|
-
*
|
|
111
|
-
*
|
|
50
|
+
* control plane's API accepts. Defaults to the `HH_CONTROL_PLANE_API_KEY`
|
|
51
|
+
* environment variable. The value is trimmed, and one that is not a
|
|
52
|
+
* well-formed fine-grained key throws at construction, naming the option or
|
|
53
|
+
* variable it came from. An empty value counts as no key.
|
|
112
54
|
*/
|
|
113
55
|
apiKey?: string;
|
|
114
56
|
controlPlaneUrl?: string;
|
|
@@ -154,13 +96,18 @@ function querySerializer(queryParams: Record<string, unknown>): string {
|
|
|
154
96
|
return uri.startsWith('?') ? uri.slice(1) : uri;
|
|
155
97
|
}
|
|
156
98
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
99
|
+
/**
|
|
100
|
+
* Resolves the client's credential and returns the openapi-fetch client that
|
|
101
|
+
* carries it, keyed by the security scheme the spec defines. Every generated
|
|
102
|
+
* method indexes the result by its operation's scheme.
|
|
103
|
+
*/
|
|
104
|
+
export function createApiClient(options: ClientConfig): ApiClients {
|
|
161
105
|
const { apiKey, controlPlaneUrl, middleware, verbose, _internal_provenance, ...clientOptions } =
|
|
162
106
|
options;
|
|
163
|
-
|
|
107
|
+
// Option > env var. The source travels with the value so the shape check
|
|
108
|
+
// below can name where a bad value came from.
|
|
109
|
+
const [rawApiKey, apiKeySource] =
|
|
110
|
+
apiKey !== undefined ? [apiKey, 'apiKey'] : [getEnv('HH_CONTROL_PLANE_API_KEY'), 'HH_CONTROL_PLANE_API_KEY']; // prettier-ignore
|
|
164
111
|
|
|
165
112
|
// Resolution order: option > env var > default. For the option, any
|
|
166
113
|
// non-undefined value wins (so explicit undefined falls back). For the env
|
|
@@ -177,14 +124,19 @@ export function createApiClient<Paths extends {}>(
|
|
|
177
124
|
version: SDK_VERSION,
|
|
178
125
|
};
|
|
179
126
|
|
|
180
|
-
// Log before
|
|
181
|
-
// resolve when construction is about to
|
|
127
|
+
// Log before either check that can throw (a malformed key, a missing key) so
|
|
128
|
+
// verbose users can see what *did* resolve when construction is about to
|
|
129
|
+
// fail. The mask redacts a malformed key wholesale.
|
|
182
130
|
if (resolvedVerbose) {
|
|
183
131
|
console.error(`Control plane URL: ${resolvedControlPlaneUrl}`);
|
|
184
|
-
console.error(`API key: ${
|
|
132
|
+
console.error(`API key: ${rawApiKey ? maskApiKey(rawApiKey) : '(none)'}`);
|
|
185
133
|
console.error(`Package: ${provenance.package} v${provenance.version}`);
|
|
186
134
|
}
|
|
187
135
|
|
|
136
|
+
// A present key is checked for shape here, at construction, whether or not
|
|
137
|
+
// middleware is supplied. An empty key is no key (below), not a bad one.
|
|
138
|
+
const resolvedApiKey = rawApiKey ? checkControlPlaneApiKey(rawApiKey, apiKeySource) : rawApiKey;
|
|
139
|
+
|
|
188
140
|
// When middleware is supplied, it is assumed to handle authentication itself
|
|
189
141
|
// (for example by attaching a short-lived token per request), so no key is
|
|
190
142
|
// required. The URL always resolves (option > env > default), so only the key
|
|
@@ -204,7 +156,7 @@ export function createApiClient<Paths extends {}>(
|
|
|
204
156
|
headers.Authorization = `Bearer ${resolvedApiKey}`;
|
|
205
157
|
}
|
|
206
158
|
|
|
207
|
-
const client = createClient<
|
|
159
|
+
const client = createClient<paths>({
|
|
208
160
|
...clientOptions,
|
|
209
161
|
querySerializer,
|
|
210
162
|
// Always set (option > env > default). Middleware, when supplied, may still
|
|
@@ -221,7 +173,12 @@ export function createApiClient<Paths extends {}>(
|
|
|
221
173
|
client.use(...middleware);
|
|
222
174
|
}
|
|
223
175
|
|
|
224
|
-
|
|
176
|
+
// The control plane takes one credential kind, the fine-grained control
|
|
177
|
+
// plane key, so every scheme maps to the one client. Keyed by the schemes
|
|
178
|
+
// the spec defines, so a scheme added to or removed from the spec fails to
|
|
179
|
+
// compile here until this table says which client serves it.
|
|
180
|
+
const clients: ApiClients = { ControlPlaneApiKey: client };
|
|
181
|
+
return clients;
|
|
225
182
|
}
|
|
226
183
|
|
|
227
184
|
/**
|