@miosa/sdk 0.3.0 → 1.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/dist/index.d.ts +1209 -18
- package/dist/index.js +1698 -252
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +44 -0
- package/src/index.ts +100 -0
- package/src/resources/api-keys.ts +5 -1
- package/src/resources/computer.ts +16 -0
- package/src/resources/cron-jobs.ts +7 -0
- package/src/resources/custom_domains.ts +7 -0
- package/src/resources/deployments.ts +13 -2
- package/src/resources/egress.test.ts +318 -0
- package/src/resources/egressAudit.ts +245 -0
- package/src/resources/egressNetwork.ts +450 -0
- package/src/resources/egressSecrets.ts +577 -0
- package/src/resources/flat-custom-domains.ts +7 -0
- package/src/resources/functions.ts +7 -0
- package/src/resources/org-invites.ts +189 -0
- package/src/resources/phase1.test.ts +187 -0
- package/src/resources/quotas.ts +77 -0
- package/src/resources/sandbox-processes.ts +112 -0
- package/src/resources/sandbox-shares.ts +83 -0
- package/src/resources/sandboxes.ts +239 -10
- package/src/resources/storage.ts +7 -0
- package/src/resources/tenant-events.ts +32 -0
- package/src/resources/tenant.ts +82 -3
- package/src/resources/volumes.ts +7 -0
- package/src/resources/webhooks.ts +55 -0
- package/src/resources/workspace-invites.ts +188 -0
- package/src/resources/workspace-members.test.ts +121 -0
- package/src/resources/workspace-members.ts +143 -0
- package/src/resources/workspaces.ts +285 -0
- package/src/types.ts +7 -0
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Egress secrets — encrypted API key + OAuth credential vault.
|
|
3
|
+
*
|
|
4
|
+
* Backed by:
|
|
5
|
+
* POST /api/v1/egress/secrets
|
|
6
|
+
* GET /api/v1/egress/secrets
|
|
7
|
+
* GET /api/v1/egress/secrets/:id
|
|
8
|
+
* PATCH /api/v1/egress/secrets/:id (rotate)
|
|
9
|
+
* DELETE /api/v1/egress/secrets/:id
|
|
10
|
+
*
|
|
11
|
+
* POST /api/v1/egress/bindings
|
|
12
|
+
* GET /api/v1/egress/bindings
|
|
13
|
+
* DELETE /api/v1/egress/bindings/:id
|
|
14
|
+
*
|
|
15
|
+
* GET /api/v1/egress/oauth/providers
|
|
16
|
+
* POST /api/v1/egress/oauth/start
|
|
17
|
+
* GET /api/v1/egress/oauth/status?state=...
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import type { HttpClient } from "../http.js";
|
|
21
|
+
|
|
22
|
+
// ── Resource shapes ──────────────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
export type EgressSecretType =
|
|
25
|
+
| "api_key"
|
|
26
|
+
| "oauth_token"
|
|
27
|
+
| "bearer"
|
|
28
|
+
| "basic"
|
|
29
|
+
| "generic";
|
|
30
|
+
|
|
31
|
+
export type EgressSecretScope =
|
|
32
|
+
| "user"
|
|
33
|
+
| "workspace"
|
|
34
|
+
| "tenant"
|
|
35
|
+
| "external_user"
|
|
36
|
+
| "external_workspace";
|
|
37
|
+
|
|
38
|
+
export interface EgressSecretData {
|
|
39
|
+
id: string;
|
|
40
|
+
name?: string;
|
|
41
|
+
type?: EgressSecretType | string;
|
|
42
|
+
scope?: EgressSecretScope | string;
|
|
43
|
+
workspace_id?: string | null;
|
|
44
|
+
owner_user_id?: string | null;
|
|
45
|
+
external_user_id?: string | null;
|
|
46
|
+
external_workspace_id?: string | null;
|
|
47
|
+
resource_id?: string | null;
|
|
48
|
+
resource_type?: string | null;
|
|
49
|
+
masked_value?: string | null;
|
|
50
|
+
expires_at?: string | null;
|
|
51
|
+
metadata?: Record<string, unknown>;
|
|
52
|
+
created_at?: string;
|
|
53
|
+
updated_at?: string;
|
|
54
|
+
[key: string]: unknown;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface EgressBindingData {
|
|
58
|
+
id: string;
|
|
59
|
+
secret_id: string;
|
|
60
|
+
resource_id: string;
|
|
61
|
+
resource_type: string;
|
|
62
|
+
expose_as_env: string;
|
|
63
|
+
created_at?: string;
|
|
64
|
+
[key: string]: unknown;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface OauthProvider {
|
|
68
|
+
name: string;
|
|
69
|
+
display_name?: string;
|
|
70
|
+
scopes?: string[];
|
|
71
|
+
[key: string]: unknown;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ── Request payloads ─────────────────────────────────────────────────────────
|
|
75
|
+
|
|
76
|
+
export interface SecretSetParams {
|
|
77
|
+
name: string;
|
|
78
|
+
value: string;
|
|
79
|
+
type?: EgressSecretType | string;
|
|
80
|
+
scope?: EgressSecretScope | string;
|
|
81
|
+
exposeAsEnv?: string;
|
|
82
|
+
expose_as_env?: string;
|
|
83
|
+
workspaceId?: string;
|
|
84
|
+
workspace_id?: string;
|
|
85
|
+
ownerUserId?: string;
|
|
86
|
+
owner_user_id?: string;
|
|
87
|
+
externalUserId?: string;
|
|
88
|
+
external_user_id?: string;
|
|
89
|
+
externalWorkspaceId?: string;
|
|
90
|
+
external_workspace_id?: string;
|
|
91
|
+
resourceId?: string;
|
|
92
|
+
resource_id?: string;
|
|
93
|
+
resourceType?: string;
|
|
94
|
+
resource_type?: string;
|
|
95
|
+
refreshToken?: string;
|
|
96
|
+
refresh_token?: string;
|
|
97
|
+
expiresAt?: string;
|
|
98
|
+
expires_at?: string;
|
|
99
|
+
metadata?: Record<string, unknown>;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface SecretListParams {
|
|
103
|
+
scope?: string;
|
|
104
|
+
type?: string;
|
|
105
|
+
workspaceId?: string;
|
|
106
|
+
workspace_id?: string;
|
|
107
|
+
ownerUserId?: string;
|
|
108
|
+
owner_user_id?: string;
|
|
109
|
+
externalUserId?: string;
|
|
110
|
+
external_user_id?: string;
|
|
111
|
+
externalWorkspaceId?: string;
|
|
112
|
+
external_workspace_id?: string;
|
|
113
|
+
resourceId?: string;
|
|
114
|
+
resource_id?: string;
|
|
115
|
+
resourceType?: string;
|
|
116
|
+
resource_type?: string;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface SecretRotateParams {
|
|
120
|
+
newValue?: string;
|
|
121
|
+
new_value?: string;
|
|
122
|
+
value?: string;
|
|
123
|
+
refreshToken?: string;
|
|
124
|
+
refresh_token?: string;
|
|
125
|
+
expiresAt?: string;
|
|
126
|
+
expires_at?: string;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface BindingCreateParams {
|
|
130
|
+
secretId?: string;
|
|
131
|
+
secret_id?: string;
|
|
132
|
+
resourceId?: string;
|
|
133
|
+
resource_id?: string;
|
|
134
|
+
resourceType?: string;
|
|
135
|
+
resource_type?: string;
|
|
136
|
+
exposeAsEnv?: string;
|
|
137
|
+
expose_as_env?: string;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export interface BindingListParams {
|
|
141
|
+
resourceId?: string;
|
|
142
|
+
resource_id?: string;
|
|
143
|
+
resourceType?: string;
|
|
144
|
+
resource_type?: string;
|
|
145
|
+
secretId?: string;
|
|
146
|
+
secret_id?: string;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export interface OauthConnectParams {
|
|
150
|
+
provider: string;
|
|
151
|
+
exposeAsEnv?: string;
|
|
152
|
+
expose_as_env?: string;
|
|
153
|
+
scope?: string;
|
|
154
|
+
ownerUserId?: string;
|
|
155
|
+
owner_user_id?: string;
|
|
156
|
+
externalUserId?: string;
|
|
157
|
+
external_user_id?: string;
|
|
158
|
+
externalWorkspaceId?: string;
|
|
159
|
+
external_workspace_id?: string;
|
|
160
|
+
resourceId?: string;
|
|
161
|
+
resource_id?: string;
|
|
162
|
+
resourceType?: string;
|
|
163
|
+
resource_type?: string;
|
|
164
|
+
redirectUri?: string;
|
|
165
|
+
redirect_uri?: string;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export interface OauthStartResult {
|
|
169
|
+
authorize_url: string;
|
|
170
|
+
authorizeUrl?: string;
|
|
171
|
+
state: string;
|
|
172
|
+
provider?: string;
|
|
173
|
+
expires_at?: string;
|
|
174
|
+
[key: string]: unknown;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export interface OauthStatusResult {
|
|
178
|
+
status: string;
|
|
179
|
+
state?: string;
|
|
180
|
+
secret_id?: string;
|
|
181
|
+
error?: string;
|
|
182
|
+
message?: string;
|
|
183
|
+
[key: string]: unknown;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
187
|
+
|
|
188
|
+
interface WireEnvelope<T> {
|
|
189
|
+
data?: T;
|
|
190
|
+
secret?: T;
|
|
191
|
+
binding?: T;
|
|
192
|
+
items?: T;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function unwrap<T>(payload: unknown): T {
|
|
196
|
+
if (payload && typeof payload === "object") {
|
|
197
|
+
const p = payload as Record<string, unknown>;
|
|
198
|
+
for (const k of ["data", "secret", "binding", "items"]) {
|
|
199
|
+
if (k in p) return p[k] as T;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return payload as T;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function unwrapList<T>(payload: unknown): T[] {
|
|
206
|
+
if (Array.isArray(payload)) return payload as T[];
|
|
207
|
+
if (payload && typeof payload === "object") {
|
|
208
|
+
const p = payload as Record<string, unknown>;
|
|
209
|
+
for (const k of ["data", "secrets", "bindings", "providers", "items"]) {
|
|
210
|
+
if (Array.isArray(p[k])) return p[k] as T[];
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return [];
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function stripUndefined(
|
|
217
|
+
input: Record<string, unknown>,
|
|
218
|
+
): Record<string, unknown> {
|
|
219
|
+
return Object.fromEntries(
|
|
220
|
+
Object.entries(input).filter(([, v]) => v !== undefined),
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function pickFirst<T>(...values: Array<T | undefined>): T | undefined {
|
|
225
|
+
for (const v of values) if (v !== undefined) return v;
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function setBody(params: SecretSetParams): Record<string, unknown> {
|
|
230
|
+
return stripUndefined({
|
|
231
|
+
name: params.name,
|
|
232
|
+
value: params.value,
|
|
233
|
+
type: params.type ?? "api_key",
|
|
234
|
+
scope: params.scope ?? "user",
|
|
235
|
+
expose_as_env: pickFirst(params.exposeAsEnv, params.expose_as_env),
|
|
236
|
+
workspace_id: pickFirst(params.workspaceId, params.workspace_id),
|
|
237
|
+
owner_user_id: pickFirst(params.ownerUserId, params.owner_user_id),
|
|
238
|
+
external_user_id: pickFirst(params.externalUserId, params.external_user_id),
|
|
239
|
+
external_workspace_id: pickFirst(
|
|
240
|
+
params.externalWorkspaceId,
|
|
241
|
+
params.external_workspace_id,
|
|
242
|
+
),
|
|
243
|
+
resource_id: pickFirst(params.resourceId, params.resource_id),
|
|
244
|
+
resource_type: pickFirst(params.resourceType, params.resource_type),
|
|
245
|
+
refresh_token: pickFirst(params.refreshToken, params.refresh_token),
|
|
246
|
+
expires_at: pickFirst(params.expiresAt, params.expires_at),
|
|
247
|
+
metadata: params.metadata,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function listQuery(
|
|
252
|
+
params: SecretListParams,
|
|
253
|
+
): Record<string, string | number | boolean | undefined> {
|
|
254
|
+
return stripUndefined({
|
|
255
|
+
scope: params.scope,
|
|
256
|
+
type: params.type,
|
|
257
|
+
workspace_id: pickFirst(params.workspaceId, params.workspace_id),
|
|
258
|
+
owner_user_id: pickFirst(params.ownerUserId, params.owner_user_id),
|
|
259
|
+
external_user_id: pickFirst(params.externalUserId, params.external_user_id),
|
|
260
|
+
external_workspace_id: pickFirst(
|
|
261
|
+
params.externalWorkspaceId,
|
|
262
|
+
params.external_workspace_id,
|
|
263
|
+
),
|
|
264
|
+
resource_id: pickFirst(params.resourceId, params.resource_id),
|
|
265
|
+
resource_type: pickFirst(params.resourceType, params.resource_type),
|
|
266
|
+
}) as Record<string, string | number | boolean | undefined>;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function rotateBody(params: SecretRotateParams): Record<string, unknown> {
|
|
270
|
+
return stripUndefined({
|
|
271
|
+
value: pickFirst(params.newValue, params.new_value, params.value),
|
|
272
|
+
refresh_token: pickFirst(params.refreshToken, params.refresh_token),
|
|
273
|
+
expires_at: pickFirst(params.expiresAt, params.expires_at),
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function bindingBody(params: BindingCreateParams): Record<string, unknown> {
|
|
278
|
+
return stripUndefined({
|
|
279
|
+
secret_id: pickFirst(params.secretId, params.secret_id),
|
|
280
|
+
resource_id: pickFirst(params.resourceId, params.resource_id),
|
|
281
|
+
resource_type: pickFirst(params.resourceType, params.resource_type),
|
|
282
|
+
expose_as_env: pickFirst(params.exposeAsEnv, params.expose_as_env),
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function bindingQuery(
|
|
287
|
+
params: BindingListParams,
|
|
288
|
+
): Record<string, string | number | boolean | undefined> {
|
|
289
|
+
return stripUndefined({
|
|
290
|
+
resource_id: pickFirst(params.resourceId, params.resource_id),
|
|
291
|
+
resource_type: pickFirst(params.resourceType, params.resource_type),
|
|
292
|
+
secret_id: pickFirst(params.secretId, params.secret_id),
|
|
293
|
+
}) as Record<string, string | number | boolean | undefined>;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function oauthBody(params: OauthConnectParams): Record<string, unknown> {
|
|
297
|
+
return stripUndefined({
|
|
298
|
+
provider: params.provider,
|
|
299
|
+
expose_as_env: pickFirst(params.exposeAsEnv, params.expose_as_env),
|
|
300
|
+
scope: params.scope,
|
|
301
|
+
owner_user_id: pickFirst(params.ownerUserId, params.owner_user_id),
|
|
302
|
+
external_user_id: pickFirst(params.externalUserId, params.external_user_id),
|
|
303
|
+
external_workspace_id: pickFirst(
|
|
304
|
+
params.externalWorkspaceId,
|
|
305
|
+
params.external_workspace_id,
|
|
306
|
+
),
|
|
307
|
+
resource_id: pickFirst(params.resourceId, params.resource_id),
|
|
308
|
+
resource_type: pickFirst(params.resourceType, params.resource_type),
|
|
309
|
+
redirect_uri: pickFirst(params.redirectUri, params.redirect_uri),
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function sleep(ms: number): Promise<void> {
|
|
314
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// ── OAuth flow handle ────────────────────────────────────────────────────────
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* A pending OAuth flow.
|
|
321
|
+
*
|
|
322
|
+
* The SDK does NOT auto-open a browser — the caller is responsible for
|
|
323
|
+
* surfacing `authorizeUrl` to the end user. Once the user grants
|
|
324
|
+
* consent, call `waitForCompletion()` to poll the upstream provider
|
|
325
|
+
* status.
|
|
326
|
+
*/
|
|
327
|
+
export class OAuthFlow {
|
|
328
|
+
readonly authorizeUrl: string;
|
|
329
|
+
readonly state: string;
|
|
330
|
+
readonly provider?: string;
|
|
331
|
+
readonly data: OauthStartResult;
|
|
332
|
+
private readonly http: HttpClient;
|
|
333
|
+
|
|
334
|
+
constructor(http: HttpClient, payload: OauthStartResult, provider?: string) {
|
|
335
|
+
this.http = http;
|
|
336
|
+
this.authorizeUrl = payload.authorize_url ?? payload.authorizeUrl ?? "";
|
|
337
|
+
this.state = payload.state ?? "";
|
|
338
|
+
if (provider !== undefined) {
|
|
339
|
+
this.provider = provider;
|
|
340
|
+
}
|
|
341
|
+
this.data = payload;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Poll `GET /egress/oauth/status?state=...` until the flow completes.
|
|
346
|
+
*
|
|
347
|
+
* Returns the status payload once the upstream provider issues
|
|
348
|
+
* tokens. Rejects with a `TimeoutError`-style Error if the flow does
|
|
349
|
+
* not complete within `timeoutSec` seconds, or if the upstream
|
|
350
|
+
* returns a failed status.
|
|
351
|
+
*/
|
|
352
|
+
async waitForCompletion(
|
|
353
|
+
options: { timeoutSec?: number; pollIntervalMs?: number } = {},
|
|
354
|
+
): Promise<OauthStatusResult> {
|
|
355
|
+
const timeoutSec = options.timeoutSec ?? 300;
|
|
356
|
+
const pollMs = options.pollIntervalMs ?? 2000;
|
|
357
|
+
const deadline = Date.now() + timeoutSec * 1000;
|
|
358
|
+
while (Date.now() < deadline) {
|
|
359
|
+
const data = await this.http.get<unknown>("/egress/oauth/status", {
|
|
360
|
+
state: this.state,
|
|
361
|
+
});
|
|
362
|
+
const payload = unwrap<OauthStatusResult>(data) ?? {};
|
|
363
|
+
const status = (payload as OauthStatusResult).status;
|
|
364
|
+
if (
|
|
365
|
+
status === "completed" ||
|
|
366
|
+
status === "ready" ||
|
|
367
|
+
status === "succeeded"
|
|
368
|
+
) {
|
|
369
|
+
return payload as OauthStatusResult;
|
|
370
|
+
}
|
|
371
|
+
if (status === "failed" || status === "error" || status === "denied") {
|
|
372
|
+
throw new Error(
|
|
373
|
+
`OAuth flow ${this.state} ended in status=${status}: ${
|
|
374
|
+
payload.error ?? payload.message ?? "no detail"
|
|
375
|
+
}`,
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
await sleep(pollMs);
|
|
379
|
+
}
|
|
380
|
+
throw new Error(
|
|
381
|
+
`OAuth flow ${this.state} did not complete within ${timeoutSec}s`,
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// ── Main resource ─────────────────────────────────────────────────────────────
|
|
387
|
+
|
|
388
|
+
export class EgressSecrets {
|
|
389
|
+
constructor(protected readonly http: HttpClient) {}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Create a secret. When `exposeAsEnv` is provided together with
|
|
393
|
+
* `resourceId` the backend also creates a binding so the value is
|
|
394
|
+
* injected as an env-var on that resource.
|
|
395
|
+
*/
|
|
396
|
+
async set(params: SecretSetParams): Promise<EgressSecretData> {
|
|
397
|
+
const data = await this.http.post<WireEnvelope<EgressSecretData>>(
|
|
398
|
+
"/egress/secrets",
|
|
399
|
+
setBody(params),
|
|
400
|
+
);
|
|
401
|
+
return unwrap<EgressSecretData>(data);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/** List secrets. */
|
|
405
|
+
async list(params: SecretListParams = {}): Promise<EgressSecretData[]> {
|
|
406
|
+
const data = await this.http.get<unknown>(
|
|
407
|
+
"/egress/secrets",
|
|
408
|
+
listQuery(params),
|
|
409
|
+
);
|
|
410
|
+
return unwrapList<EgressSecretData>(data);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/** Get a single secret by id. */
|
|
414
|
+
async get(id: string): Promise<EgressSecretData> {
|
|
415
|
+
const data = await this.http.get<WireEnvelope<EgressSecretData>>(
|
|
416
|
+
`/egress/secrets/${id}`,
|
|
417
|
+
);
|
|
418
|
+
return unwrap<EgressSecretData>(data);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/** Rotate the secret's value. */
|
|
422
|
+
async rotate(
|
|
423
|
+
id: string,
|
|
424
|
+
params: SecretRotateParams | string,
|
|
425
|
+
): Promise<EgressSecretData> {
|
|
426
|
+
const body =
|
|
427
|
+
typeof params === "string"
|
|
428
|
+
? rotateBody({ newValue: params })
|
|
429
|
+
: rotateBody(params);
|
|
430
|
+
const data = await this.http.patch<WireEnvelope<EgressSecretData>>(
|
|
431
|
+
`/egress/secrets/${id}`,
|
|
432
|
+
body,
|
|
433
|
+
);
|
|
434
|
+
return unwrap<EgressSecretData>(data);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/** Delete a secret. */
|
|
438
|
+
async delete(id: string): Promise<void> {
|
|
439
|
+
await this.http.delete<unknown>(`/egress/secrets/${id}`);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// ── bindings ───────────────────────────────────────────────────────────────
|
|
443
|
+
|
|
444
|
+
/** Bind a secret to a resource as an env var. */
|
|
445
|
+
async createBinding(params: BindingCreateParams): Promise<EgressBindingData> {
|
|
446
|
+
const data = await this.http.post<WireEnvelope<EgressBindingData>>(
|
|
447
|
+
"/egress/bindings",
|
|
448
|
+
bindingBody(params),
|
|
449
|
+
);
|
|
450
|
+
return unwrap<EgressBindingData>(data);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/** List secret bindings. */
|
|
454
|
+
async listBindings(
|
|
455
|
+
params: BindingListParams = {},
|
|
456
|
+
): Promise<EgressBindingData[]> {
|
|
457
|
+
const data = await this.http.get<unknown>(
|
|
458
|
+
"/egress/bindings",
|
|
459
|
+
bindingQuery(params),
|
|
460
|
+
);
|
|
461
|
+
return unwrapList<EgressBindingData>(data);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/** Delete a binding. */
|
|
465
|
+
async deleteBinding(id: string): Promise<void> {
|
|
466
|
+
await this.http.delete<unknown>(`/egress/bindings/${id}`);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// ── OAuth Connect ──────────────────────────────────────────────────────────
|
|
470
|
+
|
|
471
|
+
/** List OAuth providers visible to the current tenant. */
|
|
472
|
+
async providers(): Promise<OauthProvider[]> {
|
|
473
|
+
const data = await this.http.get<unknown>("/egress/oauth/providers");
|
|
474
|
+
return unwrapList<OauthProvider>(data);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Start an OAuth Connect flow.
|
|
479
|
+
*
|
|
480
|
+
* Returns an {@link OAuthFlow} — the caller must surface
|
|
481
|
+
* `flow.authorizeUrl` to the end user (the SDK does NOT open the
|
|
482
|
+
* browser) and then call `flow.waitForCompletion()` to receive the
|
|
483
|
+
* resulting secret id.
|
|
484
|
+
*/
|
|
485
|
+
async connect(params: OauthConnectParams): Promise<OAuthFlow> {
|
|
486
|
+
const data = await this.http.post<WireEnvelope<OauthStartResult>>(
|
|
487
|
+
"/egress/oauth/start",
|
|
488
|
+
oauthBody(params),
|
|
489
|
+
);
|
|
490
|
+
const payload = unwrap<OauthStartResult>(data) ?? ({} as OauthStartResult);
|
|
491
|
+
return new OAuthFlow(this.http, payload, params.provider);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// ── Resource-scoped wrappers ─────────────────────────────────────────────────
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Sandbox-bound view of {@link EgressSecrets}. Pre-scopes
|
|
499
|
+
* `resource_id` + `resource_type="sandbox"` on every call.
|
|
500
|
+
*/
|
|
501
|
+
export class SandboxSecrets {
|
|
502
|
+
protected readonly resourceType: string = "sandbox";
|
|
503
|
+
private readonly delegate: EgressSecrets;
|
|
504
|
+
|
|
505
|
+
constructor(
|
|
506
|
+
http: HttpClient,
|
|
507
|
+
protected readonly resourceId: string,
|
|
508
|
+
) {
|
|
509
|
+
this.delegate = new EgressSecrets(http);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
private resolvedResourceId(params: {
|
|
513
|
+
resourceId?: string;
|
|
514
|
+
resource_id?: string;
|
|
515
|
+
}): string {
|
|
516
|
+
return params.resourceId ?? params.resource_id ?? this.resourceId;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
private resolvedResourceType(params: {
|
|
520
|
+
resourceType?: string;
|
|
521
|
+
resource_type?: string;
|
|
522
|
+
}): string {
|
|
523
|
+
return params.resourceType ?? params.resource_type ?? this.resourceType;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
set(params: SecretSetParams): Promise<EgressSecretData> {
|
|
527
|
+
return this.delegate.set({
|
|
528
|
+
...params,
|
|
529
|
+
resource_id: this.resolvedResourceId(params),
|
|
530
|
+
resource_type: this.resolvedResourceType(params),
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
list(params: SecretListParams = {}): Promise<EgressSecretData[]> {
|
|
535
|
+
return this.delegate.list({
|
|
536
|
+
...params,
|
|
537
|
+
resource_id: this.resolvedResourceId(params),
|
|
538
|
+
resource_type: this.resolvedResourceType(params),
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
get(id: string): Promise<EgressSecretData> {
|
|
543
|
+
return this.delegate.get(id);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
rotate(
|
|
547
|
+
id: string,
|
|
548
|
+
params: SecretRotateParams | string,
|
|
549
|
+
): Promise<EgressSecretData> {
|
|
550
|
+
return this.delegate.rotate(id, params);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
delete(id: string): Promise<void> {
|
|
554
|
+
return this.delegate.delete(id);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
connect(params: OauthConnectParams): Promise<OAuthFlow> {
|
|
558
|
+
return this.delegate.connect({
|
|
559
|
+
...params,
|
|
560
|
+
resource_id: this.resolvedResourceId(params),
|
|
561
|
+
resource_type: this.resolvedResourceType(params),
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
listBindings(params: BindingListParams = {}): Promise<EgressBindingData[]> {
|
|
566
|
+
return this.delegate.listBindings({
|
|
567
|
+
...params,
|
|
568
|
+
resource_id: this.resolvedResourceId(params),
|
|
569
|
+
resource_type: this.resolvedResourceType(params),
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/** Computer-bound secrets — same shape, `resource_type="computer"`. */
|
|
575
|
+
export class ComputerSecrets extends SandboxSecrets {
|
|
576
|
+
protected readonly resourceType: string = "computer";
|
|
577
|
+
}
|
|
@@ -47,6 +47,13 @@ export interface CustomDomainCreateParams {
|
|
|
47
47
|
redirect_policy?: "none" | "www_to_apex" | "apex_to_www";
|
|
48
48
|
redirectPolicy?: "none" | "www_to_apex" | "apex_to_www";
|
|
49
49
|
idempotencyKey?: string;
|
|
50
|
+
// White-label attribution
|
|
51
|
+
externalWorkspaceId?: string;
|
|
52
|
+
external_workspace_id?: string;
|
|
53
|
+
externalUserId?: string;
|
|
54
|
+
external_user_id?: string;
|
|
55
|
+
externalProjectId?: string;
|
|
56
|
+
external_project_id?: string;
|
|
50
57
|
[key: string]: unknown;
|
|
51
58
|
}
|
|
52
59
|
|
|
@@ -46,6 +46,13 @@ export interface FunctionCreateParams {
|
|
|
46
46
|
timeoutSec?: number;
|
|
47
47
|
env?: Record<string, string>;
|
|
48
48
|
idempotencyKey?: string;
|
|
49
|
+
// White-label attribution
|
|
50
|
+
externalWorkspaceId?: string;
|
|
51
|
+
external_workspace_id?: string;
|
|
52
|
+
externalUserId?: string;
|
|
53
|
+
external_user_id?: string;
|
|
54
|
+
externalProjectId?: string;
|
|
55
|
+
external_project_id?: string;
|
|
49
56
|
[key: string]: unknown;
|
|
50
57
|
}
|
|
51
58
|
|