@onkernel/sdk 0.49.0 → 0.52.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 +86 -0
- package/client.d.mts +5 -2
- package/client.d.mts.map +1 -1
- package/client.d.ts +5 -2
- package/client.d.ts.map +1 -1
- package/client.js +26 -2
- package/client.js.map +1 -1
- package/client.mjs +26 -2
- package/client.mjs.map +1 -1
- package/index.d.mts +2 -0
- package/index.d.mts.map +1 -1
- package/index.d.ts +2 -0
- package/index.d.ts.map +1 -1
- package/index.js +3 -1
- package/index.js.map +1 -1
- package/index.mjs +1 -0
- package/index.mjs.map +1 -1
- package/internal/types.d.mts +6 -6
- package/internal/types.d.mts.map +1 -1
- package/internal/types.d.ts +6 -6
- package/internal/types.d.ts.map +1 -1
- package/lib/browser-fetch.d.mts +7 -0
- package/lib/browser-fetch.d.mts.map +1 -0
- package/lib/browser-fetch.d.ts +7 -0
- package/lib/browser-fetch.d.ts.map +1 -0
- package/lib/browser-fetch.js +128 -0
- package/lib/browser-fetch.js.map +1 -0
- package/lib/browser-fetch.mjs +125 -0
- package/lib/browser-fetch.mjs.map +1 -0
- package/lib/browser-routing.d.mts +20 -0
- package/lib/browser-routing.d.mts.map +1 -0
- package/lib/browser-routing.d.ts +20 -0
- package/lib/browser-routing.d.ts.map +1 -0
- package/lib/browser-routing.js +246 -0
- package/lib/browser-routing.js.map +1 -0
- package/lib/browser-routing.mjs +240 -0
- package/lib/browser-routing.mjs.map +1 -0
- package/lib/join-url.d.mts +2 -0
- package/lib/join-url.d.mts.map +1 -0
- package/lib/join-url.d.ts +2 -0
- package/lib/join-url.d.ts.map +1 -0
- package/lib/join-url.js +7 -0
- package/lib/join-url.js.map +1 -0
- package/lib/join-url.mjs +4 -0
- package/lib/join-url.mjs.map +1 -0
- package/package.json +11 -1
- package/resources/auth/connections.d.mts +31 -2
- package/resources/auth/connections.d.mts.map +1 -1
- package/resources/auth/connections.d.ts +31 -2
- package/resources/auth/connections.d.ts.map +1 -1
- package/resources/browsers/browsers.d.mts +72 -1
- package/resources/browsers/browsers.d.mts.map +1 -1
- package/resources/browsers/browsers.d.ts +72 -1
- package/resources/browsers/browsers.d.ts.map +1 -1
- package/resources/browsers/browsers.js +23 -0
- package/resources/browsers/browsers.js.map +1 -1
- package/resources/browsers/browsers.mjs +23 -0
- package/resources/browsers/browsers.mjs.map +1 -1
- package/resources/browsers/index.d.mts +1 -1
- package/resources/browsers/index.d.mts.map +1 -1
- package/resources/browsers/index.d.ts +1 -1
- package/resources/browsers/index.d.ts.map +1 -1
- package/resources/browsers/index.js.map +1 -1
- package/resources/browsers/index.mjs.map +1 -1
- package/resources/index.d.mts +1 -1
- package/resources/index.d.mts.map +1 -1
- package/resources/index.d.ts +1 -1
- package/resources/index.d.ts.map +1 -1
- package/resources/index.js.map +1 -1
- package/resources/index.mjs.map +1 -1
- package/resources/profiles.d.mts +1 -2
- package/resources/profiles.d.mts.map +1 -1
- package/resources/profiles.d.ts +1 -2
- package/resources/profiles.d.ts.map +1 -1
- package/resources/profiles.js +1 -2
- package/resources/profiles.js.map +1 -1
- package/resources/profiles.mjs +1 -2
- package/resources/profiles.mjs.map +1 -1
- package/resources/projects/projects.d.mts +2 -2
- package/resources/projects/projects.d.ts +2 -2
- package/resources/projects/projects.js +2 -2
- package/resources/projects/projects.mjs +2 -2
- package/src/client.ts +37 -2
- package/src/index.ts +2 -0
- package/src/internal/types.ts +6 -8
- package/src/lib/browser-fetch.ts +180 -0
- package/src/lib/browser-routing.ts +329 -0
- package/src/lib/join-url.ts +3 -0
- package/src/resources/auth/connections.ts +35 -2
- package/src/resources/browsers/browsers.ts +85 -0
- package/src/resources/browsers/index.ts +2 -0
- package/src/resources/index.ts +2 -0
- package/src/resources/profiles.ts +1 -2
- package/src/resources/projects/projects.ts +2 -2
- package/src/version.ts +1 -1
- package/version.d.mts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.mjs +1 -1
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import type { Fetch, RequestInfo, RequestInit } from '../internal/builtin-types';
|
|
2
|
+
import { joinURL } from './join-url';
|
|
3
|
+
|
|
4
|
+
export type BrowserRoute = {
|
|
5
|
+
sessionId: string;
|
|
6
|
+
baseURL: string;
|
|
7
|
+
jwt: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export class BrowserRouteCache {
|
|
11
|
+
private entries = new Map<string, BrowserRoute>();
|
|
12
|
+
|
|
13
|
+
get(sessionId: string): BrowserRoute | undefined {
|
|
14
|
+
return this.entries.get(sessionId);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
set(route: BrowserRoute): void {
|
|
18
|
+
this.entries.set(route.sessionId, route);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
delete(sessionId: string): void {
|
|
22
|
+
this.entries.delete(sessionId);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
clear(): void {
|
|
26
|
+
this.entries.clear();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const BROWSER_ROUTING_SUBRESOURCES_ENV = 'KERNEL_BROWSER_ROUTING_SUBRESOURCES';
|
|
31
|
+
const DEFAULT_BROWSER_ROUTING_SUBRESOURCES = ['curl'];
|
|
32
|
+
const BROWSER_ROUTE_CACHEABLE_PATH = /^\/(?:v\d+\/)?browsers(?:\/[^/]+)?\/?$/;
|
|
33
|
+
const BROWSER_POOL_ACQUIRE_PATH = /^\/(?:v\d+\/)?browser_pools\/[^/]+\/acquire\/?$/;
|
|
34
|
+
const BROWSER_DELETE_BY_ID_PATH = /^\/(?:v\d+\/)?browsers\/([^/]+)\/?$/;
|
|
35
|
+
const BROWSER_POOL_RELEASE_PATH = /^\/(?:v\d+\/)?browser_pools\/[^/]+\/release\/?$/;
|
|
36
|
+
|
|
37
|
+
export function browserRoutingSubresourcesFromEnv(): string[] {
|
|
38
|
+
const raw = readBrowserRoutingSubresourcesEnv();
|
|
39
|
+
if (raw === undefined) {
|
|
40
|
+
return [...DEFAULT_BROWSER_ROUTING_SUBRESOURCES];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (raw.trim() === '') {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return raw
|
|
48
|
+
.split(',')
|
|
49
|
+
.map((value) => value.trim())
|
|
50
|
+
.filter(Boolean);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function createRoutingFetch(
|
|
54
|
+
innerFetch: Fetch,
|
|
55
|
+
{
|
|
56
|
+
apiBaseURL,
|
|
57
|
+
subresources,
|
|
58
|
+
cache,
|
|
59
|
+
}: {
|
|
60
|
+
apiBaseURL: string;
|
|
61
|
+
subresources: Iterable<string>;
|
|
62
|
+
cache: BrowserRouteCache;
|
|
63
|
+
},
|
|
64
|
+
): Fetch {
|
|
65
|
+
const allowed = new Set([...subresources].map((value) => value.trim()).filter(Boolean));
|
|
66
|
+
const apiOrigin = new URL(apiBaseURL).origin;
|
|
67
|
+
|
|
68
|
+
return async (input, init) => {
|
|
69
|
+
const request = new Request(input, init);
|
|
70
|
+
const shouldSniff = shouldSniffAndPopulateCache(request, apiOrigin);
|
|
71
|
+
const response = await routeRequest(innerFetch, { input, init, request }, apiOrigin, allowed, cache);
|
|
72
|
+
if (shouldSniff) {
|
|
73
|
+
await sniffAndPopulateCache(response, cache);
|
|
74
|
+
}
|
|
75
|
+
await maybeEvictBrowserRoute(request, response, apiOrigin, cache);
|
|
76
|
+
return response;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function shouldSniffAndPopulateCache(request: Request, apiOrigin: string): boolean {
|
|
81
|
+
const url = new URL(request.url);
|
|
82
|
+
return (
|
|
83
|
+
url.origin === apiOrigin &&
|
|
84
|
+
(BROWSER_ROUTE_CACHEABLE_PATH.test(url.pathname) || BROWSER_POOL_ACQUIRE_PATH.test(url.pathname))
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function maybeEvictBrowserRoute(
|
|
89
|
+
request: Request,
|
|
90
|
+
response: Response,
|
|
91
|
+
apiOrigin: string,
|
|
92
|
+
cache: BrowserRouteCache,
|
|
93
|
+
): Promise<void> {
|
|
94
|
+
if (!response.ok) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const url = new URL(request.url);
|
|
99
|
+
if (url.origin !== apiOrigin) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const sessionId =
|
|
104
|
+
deletedSessionIdFromPath(request, url.pathname) ??
|
|
105
|
+
(await releasedSessionIdFromRequest(request, url.pathname));
|
|
106
|
+
if (sessionId) {
|
|
107
|
+
cache.delete(sessionId);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function deletedSessionIdFromPath(request: Request, pathname: string): string | undefined {
|
|
112
|
+
if (request.method.toUpperCase() !== 'DELETE') {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const match = pathname.match(BROWSER_DELETE_BY_ID_PATH);
|
|
117
|
+
if (!match) {
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const sessionId = decodeURIComponent(match[1] ?? '');
|
|
122
|
+
return sessionId || undefined;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async function releasedSessionIdFromRequest(request: Request, pathname: string): Promise<string | undefined> {
|
|
126
|
+
if (request.method.toUpperCase() !== 'POST' || !BROWSER_POOL_RELEASE_PATH.test(pathname)) {
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const body = await request.clone().json();
|
|
132
|
+
if (!body || typeof body !== 'object') {
|
|
133
|
+
return undefined;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const sessionId = (body as Record<string, unknown>)['session_id'];
|
|
137
|
+
return typeof sessionId === 'string' && sessionId.trim() ? sessionId.trim() : undefined;
|
|
138
|
+
} catch {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function browserRouteFromValue(value: unknown): BrowserRoute | undefined {
|
|
144
|
+
if (!value || typeof value !== 'object') {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const record = value as Record<string, unknown>;
|
|
149
|
+
const sessionId = typeof record['session_id'] === 'string' ? record['session_id'].trim() : '';
|
|
150
|
+
const baseURL = typeof record['base_url'] === 'string' ? record['base_url'].trim() : '';
|
|
151
|
+
if (!sessionId || !baseURL) {
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const explicitJWT = typeof record['jwt'] === 'string' ? record['jwt'].trim() : '';
|
|
156
|
+
const cdpWsURL = typeof record['cdp_ws_url'] === 'string' ? record['cdp_ws_url'] : undefined;
|
|
157
|
+
const jwt = explicitJWT || parseJwtFromCdpWsUrl(cdpWsURL) || '';
|
|
158
|
+
if (!jwt) {
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
sessionId,
|
|
163
|
+
baseURL,
|
|
164
|
+
jwt,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async function sniffAndPopulateCache(response: Response, cache: BrowserRouteCache): Promise<void> {
|
|
169
|
+
const contentType = response.headers.get('content-type')?.toLowerCase() ?? '';
|
|
170
|
+
if (!contentType.includes('application/json')) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
populateCache(await response.clone().json(), cache);
|
|
176
|
+
} catch {
|
|
177
|
+
// Ignore malformed JSON in routing cache population.
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function populateCache(value: unknown, cache: BrowserRouteCache): void {
|
|
182
|
+
const route = browserRouteFromValue(value);
|
|
183
|
+
if (route) {
|
|
184
|
+
cache.set(route);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (Array.isArray(value)) {
|
|
188
|
+
for (const item of value) {
|
|
189
|
+
populateCache(item, cache);
|
|
190
|
+
}
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (!value || typeof value !== 'object') {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
for (const child of Object.values(value as Record<string, unknown>)) {
|
|
199
|
+
if (typeof child === 'object' && child !== null) {
|
|
200
|
+
populateCache(child, cache);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async function routeRequest(
|
|
206
|
+
innerFetch: Fetch,
|
|
207
|
+
{
|
|
208
|
+
input,
|
|
209
|
+
init,
|
|
210
|
+
request,
|
|
211
|
+
}: {
|
|
212
|
+
input: RequestInfo;
|
|
213
|
+
init: RequestInit | undefined;
|
|
214
|
+
request: Request;
|
|
215
|
+
},
|
|
216
|
+
apiOrigin: string,
|
|
217
|
+
allowed: ReadonlySet<string>,
|
|
218
|
+
cache: BrowserRouteCache,
|
|
219
|
+
): Promise<Response> {
|
|
220
|
+
const url = new URL(request.url);
|
|
221
|
+
if (url.origin !== apiOrigin) {
|
|
222
|
+
return innerFetch(input, init);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const match = url.pathname.match(/^\/(?:v\d+\/)?browsers\/([^/]+)\/([^/]+)(\/.*)?$/);
|
|
226
|
+
if (!match) {
|
|
227
|
+
return innerFetch(input, init);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const sessionId = decodeURIComponent(match[1] ?? '');
|
|
231
|
+
const subresource = match[2] ?? '';
|
|
232
|
+
if (!sessionId || !allowed.has(subresource)) {
|
|
233
|
+
return innerFetch(input, init);
|
|
234
|
+
}
|
|
235
|
+
const route = cache.get(sessionId);
|
|
236
|
+
if (route === undefined) {
|
|
237
|
+
return innerFetch(input, init);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const target = new URL(joinURL(route.baseURL, `/${subresource}${match[3] ?? ''}`));
|
|
241
|
+
url.searchParams.forEach((value, key) => {
|
|
242
|
+
if (key !== 'jwt') {
|
|
243
|
+
target.searchParams.append(key, value);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
if (!target.searchParams.get('jwt')) {
|
|
247
|
+
target.searchParams.set('jwt', route.jwt);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const headers = new Headers(request.headers);
|
|
251
|
+
headers.delete('authorization');
|
|
252
|
+
return innerFetch(target.toString(), buildRoutedInit(request, init, headers));
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function buildRoutedInit(
|
|
256
|
+
request: Request,
|
|
257
|
+
originalInit: RequestInit | undefined,
|
|
258
|
+
headers: Headers,
|
|
259
|
+
): RequestInit {
|
|
260
|
+
const method = request.method.toUpperCase();
|
|
261
|
+
const routedInit = {
|
|
262
|
+
...((originalInit ?? {}) as Record<string, unknown>),
|
|
263
|
+
method,
|
|
264
|
+
headers,
|
|
265
|
+
redirect: request.redirect,
|
|
266
|
+
signal: request.signal,
|
|
267
|
+
} as RequestInit & Record<string, unknown>;
|
|
268
|
+
|
|
269
|
+
delete routedInit['body'];
|
|
270
|
+
delete routedInit['duplex'];
|
|
271
|
+
|
|
272
|
+
if (method !== 'GET' && method !== 'HEAD') {
|
|
273
|
+
const body = requestBodyForFetch(request, originalInit);
|
|
274
|
+
if (body !== undefined) {
|
|
275
|
+
routedInit.body = body;
|
|
276
|
+
}
|
|
277
|
+
if (originalInit?.duplex !== undefined) {
|
|
278
|
+
routedInit.duplex = originalInit.duplex;
|
|
279
|
+
} else if (requiresHalfDuplex(body)) {
|
|
280
|
+
routedInit.duplex = 'half';
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return routedInit;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function requestBodyForFetch(
|
|
288
|
+
request: Request,
|
|
289
|
+
originalInit: RequestInit | undefined,
|
|
290
|
+
): RequestInit['body'] | undefined {
|
|
291
|
+
if (originalInit?.body !== undefined && originalInit.body !== null) {
|
|
292
|
+
return originalInit.body;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return request.body ?? undefined;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function requiresHalfDuplex(body: RequestInit['body'] | undefined): boolean {
|
|
299
|
+
return (
|
|
300
|
+
((globalThis as any).ReadableStream && body instanceof (globalThis as any).ReadableStream) ||
|
|
301
|
+
(typeof body === 'object' && body !== null && Symbol.asyncIterator in body)
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function parseJwtFromCdpWsUrl(cdpWsUrl: string | undefined): string | undefined {
|
|
306
|
+
if (!cdpWsUrl) {
|
|
307
|
+
return undefined;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
return new URL(cdpWsUrl).searchParams.get('jwt') ?? undefined;
|
|
312
|
+
} catch {
|
|
313
|
+
return undefined;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function readBrowserRoutingSubresourcesEnv(): string | undefined {
|
|
318
|
+
if (typeof (globalThis as any).process !== 'undefined') {
|
|
319
|
+
const value = (globalThis as any).process.env?.[BROWSER_ROUTING_SUBRESOURCES_ENV];
|
|
320
|
+
return typeof value === 'string' ? value : undefined;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (typeof (globalThis as any).Deno !== 'undefined') {
|
|
324
|
+
const value = (globalThis as any).Deno.env?.get?.(BROWSER_ROUTING_SUBRESOURCES_ENV);
|
|
325
|
+
return typeof value === 'string' ? value : undefined;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return undefined;
|
|
329
|
+
}
|
|
@@ -244,6 +244,13 @@ export interface ManagedAuth {
|
|
|
244
244
|
*/
|
|
245
245
|
allowed_domains?: Array<string>;
|
|
246
246
|
|
|
247
|
+
/**
|
|
248
|
+
* ID of the underlying browser session driving the current flow (present when flow
|
|
249
|
+
* in progress). Use this to inspect or terminate the browser session via the
|
|
250
|
+
* `/browsers` API.
|
|
251
|
+
*/
|
|
252
|
+
browser_session_id?: string | null;
|
|
253
|
+
|
|
247
254
|
/**
|
|
248
255
|
* Whether automatic re-authentication is possible (has credential, selectors, and
|
|
249
256
|
* login_url)
|
|
@@ -286,7 +293,10 @@ export interface ManagedAuth {
|
|
|
286
293
|
external_action_message?: string | null;
|
|
287
294
|
|
|
288
295
|
/**
|
|
289
|
-
* When the current flow expires (null when no flow in progress)
|
|
296
|
+
* When the current flow expires (null when no flow in progress). A flow past this
|
|
297
|
+
* timestamp is no longer valid and its `flow_status` will be `EXPIRED`. Clients
|
|
298
|
+
* may start a new login to supersede a stale `IN_PROGRESS` flow past this
|
|
299
|
+
* timestamp.
|
|
290
300
|
*/
|
|
291
301
|
flow_expires_at?: string | null;
|
|
292
302
|
|
|
@@ -326,10 +336,21 @@ export interface ManagedAuth {
|
|
|
326
336
|
hosted_url?: string | null;
|
|
327
337
|
|
|
328
338
|
/**
|
|
329
|
-
*
|
|
339
|
+
* @deprecated Deprecated alias for `last_auth_check_at`. Despite the name, this is
|
|
340
|
+
* the last health-check timestamp, not the last successful authentication. Use
|
|
341
|
+
* `last_auth_check_at` instead.
|
|
330
342
|
*/
|
|
331
343
|
last_auth_at?: string;
|
|
332
344
|
|
|
345
|
+
/**
|
|
346
|
+
* When the most recent auth health check ran for this connection, regardless of
|
|
347
|
+
* outcome. Updated on every health check and does not by itself indicate that the
|
|
348
|
+
* profile is currently authenticated - use `status` for that. May be newer than
|
|
349
|
+
* `flow_expires_at` when a flow is still in progress because health checks
|
|
350
|
+
* continue to run in parallel.
|
|
351
|
+
*/
|
|
352
|
+
last_auth_check_at?: string;
|
|
353
|
+
|
|
333
354
|
/**
|
|
334
355
|
* Browser live view URL for debugging (present when flow in progress)
|
|
335
356
|
*/
|
|
@@ -433,6 +454,12 @@ export namespace ManagedAuth {
|
|
|
433
454
|
*/
|
|
434
455
|
type: 'text' | 'email' | 'password' | 'tel' | 'number' | 'url' | 'code' | 'totp';
|
|
435
456
|
|
|
457
|
+
/**
|
|
458
|
+
* Contextual help text near the field that tells the user what to enter (e.g.,
|
|
459
|
+
* "Enter the phone ending in (**_) _**-\*\*92")
|
|
460
|
+
*/
|
|
461
|
+
hint?: string;
|
|
462
|
+
|
|
436
463
|
/**
|
|
437
464
|
* If this field is associated with an MFA option, the type of that option (e.g.,
|
|
438
465
|
* password field linked to "Enter password" option)
|
|
@@ -890,6 +917,12 @@ export namespace ConnectionFollowResponse {
|
|
|
890
917
|
*/
|
|
891
918
|
type: 'text' | 'email' | 'password' | 'tel' | 'number' | 'url' | 'code' | 'totp';
|
|
892
919
|
|
|
920
|
+
/**
|
|
921
|
+
* Contextual help text near the field that tells the user what to enter (e.g.,
|
|
922
|
+
* "Enter the phone ending in (**_) _**-\*\*92")
|
|
923
|
+
*/
|
|
924
|
+
hint?: string;
|
|
925
|
+
|
|
893
926
|
/**
|
|
894
927
|
* If this field is associated with an MFA option, the type of that option (e.g.,
|
|
895
928
|
* password field linked to "Enter password" option)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
2
2
|
|
|
3
|
+
import type { RequestInfo } from '../../internal/builtin-types';
|
|
3
4
|
import { APIResource } from '../../core/resource';
|
|
4
5
|
import * as Shared from '../shared';
|
|
5
6
|
import * as ComputerAPI from './computer';
|
|
@@ -75,6 +76,7 @@ import { buildHeaders } from '../../internal/headers';
|
|
|
75
76
|
import { RequestOptions } from '../../internal/request-options';
|
|
76
77
|
import { multipartFormRequestOptions } from '../../internal/uploads';
|
|
77
78
|
import { path } from '../../internal/utils/path';
|
|
79
|
+
import { browserFetch, type BrowserFetchInit } from '../../lib/browser-fetch';
|
|
78
80
|
|
|
79
81
|
/**
|
|
80
82
|
* Create and manage browser sessions.
|
|
@@ -168,6 +170,30 @@ export class Browsers extends APIResource {
|
|
|
168
170
|
});
|
|
169
171
|
}
|
|
170
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Sends an HTTP request through Chrome's HTTP request stack, inheriting the
|
|
175
|
+
* browser's TLS fingerprint, cookies, proxy configuration, and headers. Returns a
|
|
176
|
+
* structured JSON response with status, headers, body, and timing.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```ts
|
|
180
|
+
* const response = await client.browsers.curl('id', {
|
|
181
|
+
* url: 'url',
|
|
182
|
+
* });
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
curl(id: string, body: BrowserCurlParams, options?: RequestOptions): APIPromise<BrowserCurlResponse> {
|
|
186
|
+
return this._client.post(path`/browsers/${id}/curl`, { body, ...options });
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Issues an HTTP request through the browser VM network stack, routing directly
|
|
191
|
+
* to the browser's `base_url` using the shared browser route cache.
|
|
192
|
+
*/
|
|
193
|
+
fetch(id: string, input: RequestInfo | URL, init?: BrowserFetchInit): Promise<Response> {
|
|
194
|
+
return browserFetch(this._client, id, input, init);
|
|
195
|
+
}
|
|
196
|
+
|
|
171
197
|
/**
|
|
172
198
|
* Delete a browser session by ID
|
|
173
199
|
*
|
|
@@ -706,6 +732,31 @@ export interface BrowserListResponse {
|
|
|
706
732
|
viewport?: Shared.BrowserViewport;
|
|
707
733
|
}
|
|
708
734
|
|
|
735
|
+
/**
|
|
736
|
+
* Structured response from the browser curl request.
|
|
737
|
+
*/
|
|
738
|
+
export interface BrowserCurlResponse {
|
|
739
|
+
/**
|
|
740
|
+
* Response body (UTF-8 string or base64 depending on request).
|
|
741
|
+
*/
|
|
742
|
+
body: string;
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Total request duration in milliseconds.
|
|
746
|
+
*/
|
|
747
|
+
duration_ms: number;
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* Response headers (multi-value).
|
|
751
|
+
*/
|
|
752
|
+
headers: { [key: string]: Array<string> };
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* HTTP status code from target.
|
|
756
|
+
*/
|
|
757
|
+
status: number;
|
|
758
|
+
}
|
|
759
|
+
|
|
709
760
|
export interface BrowserCreateParams {
|
|
710
761
|
/**
|
|
711
762
|
* List of browser extensions to load into the session. Provide each by id or name.
|
|
@@ -859,6 +910,38 @@ export interface BrowserDeleteParams {
|
|
|
859
910
|
persistent_id: string;
|
|
860
911
|
}
|
|
861
912
|
|
|
913
|
+
export interface BrowserCurlParams {
|
|
914
|
+
/**
|
|
915
|
+
* Target URL (must be http or https).
|
|
916
|
+
*/
|
|
917
|
+
url: string;
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* Request body (for POST/PUT/PATCH).
|
|
921
|
+
*/
|
|
922
|
+
body?: string;
|
|
923
|
+
|
|
924
|
+
/**
|
|
925
|
+
* Custom headers merged with browser defaults.
|
|
926
|
+
*/
|
|
927
|
+
headers?: { [key: string]: string };
|
|
928
|
+
|
|
929
|
+
/**
|
|
930
|
+
* HTTP method.
|
|
931
|
+
*/
|
|
932
|
+
method?: 'GET' | 'HEAD' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS';
|
|
933
|
+
|
|
934
|
+
/**
|
|
935
|
+
* Encoding for the response body. Use base64 for binary content.
|
|
936
|
+
*/
|
|
937
|
+
response_encoding?: 'utf8' | 'base64';
|
|
938
|
+
|
|
939
|
+
/**
|
|
940
|
+
* Request timeout in milliseconds.
|
|
941
|
+
*/
|
|
942
|
+
timeout_ms?: number;
|
|
943
|
+
}
|
|
944
|
+
|
|
862
945
|
export interface BrowserLoadExtensionsParams {
|
|
863
946
|
/**
|
|
864
947
|
* List of extensions to upload and activate
|
|
@@ -898,12 +981,14 @@ export declare namespace Browsers {
|
|
|
898
981
|
type BrowserRetrieveResponse as BrowserRetrieveResponse,
|
|
899
982
|
type BrowserUpdateResponse as BrowserUpdateResponse,
|
|
900
983
|
type BrowserListResponse as BrowserListResponse,
|
|
984
|
+
type BrowserCurlResponse as BrowserCurlResponse,
|
|
901
985
|
type BrowserListResponsesOffsetPagination as BrowserListResponsesOffsetPagination,
|
|
902
986
|
type BrowserCreateParams as BrowserCreateParams,
|
|
903
987
|
type BrowserRetrieveParams as BrowserRetrieveParams,
|
|
904
988
|
type BrowserUpdateParams as BrowserUpdateParams,
|
|
905
989
|
type BrowserListParams as BrowserListParams,
|
|
906
990
|
type BrowserDeleteParams as BrowserDeleteParams,
|
|
991
|
+
type BrowserCurlParams as BrowserCurlParams,
|
|
907
992
|
type BrowserLoadExtensionsParams as BrowserLoadExtensionsParams,
|
|
908
993
|
};
|
|
909
994
|
|
|
@@ -10,11 +10,13 @@ export {
|
|
|
10
10
|
type BrowserRetrieveResponse,
|
|
11
11
|
type BrowserUpdateResponse,
|
|
12
12
|
type BrowserListResponse,
|
|
13
|
+
type BrowserCurlResponse,
|
|
13
14
|
type BrowserCreateParams,
|
|
14
15
|
type BrowserRetrieveParams,
|
|
15
16
|
type BrowserUpdateParams,
|
|
16
17
|
type BrowserListParams,
|
|
17
18
|
type BrowserDeleteParams,
|
|
19
|
+
type BrowserCurlParams,
|
|
18
20
|
type BrowserLoadExtensionsParams,
|
|
19
21
|
type ProfilesOffsetPagination,
|
|
20
22
|
type BrowserListResponsesOffsetPagination,
|
package/src/resources/index.ts
CHANGED
|
@@ -29,11 +29,13 @@ export {
|
|
|
29
29
|
type BrowserRetrieveResponse,
|
|
30
30
|
type BrowserUpdateResponse,
|
|
31
31
|
type BrowserListResponse,
|
|
32
|
+
type BrowserCurlResponse,
|
|
32
33
|
type BrowserCreateParams,
|
|
33
34
|
type BrowserRetrieveParams,
|
|
34
35
|
type BrowserUpdateParams,
|
|
35
36
|
type BrowserListParams,
|
|
36
37
|
type BrowserDeleteParams,
|
|
38
|
+
type BrowserCurlParams,
|
|
37
39
|
type BrowserLoadExtensionsParams,
|
|
38
40
|
type ProfilesOffsetPagination,
|
|
39
41
|
type BrowserListResponsesOffsetPagination,
|
|
@@ -49,8 +49,7 @@ export class Profiles extends APIResource {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
|
-
*
|
|
53
|
-
* that we save.
|
|
52
|
+
* Returns a zstd-compressed tar file of the full user-data directory.
|
|
54
53
|
*/
|
|
55
54
|
download(idOrName: string, options?: RequestOptions): APIPromise<Response> {
|
|
56
55
|
return this._client.get(path`/profiles/${idOrName}/download`, {
|
|
@@ -16,8 +16,8 @@ export class Projects extends APIResource {
|
|
|
16
16
|
limits: LimitsAPI.Limits = new LimitsAPI.Limits(this._client);
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* Create a new project within the authenticated organization. Requires
|
|
20
|
-
*
|
|
19
|
+
* Create a new project within the authenticated organization. Requires the
|
|
20
|
+
* projects feature flag.
|
|
21
21
|
*
|
|
22
22
|
* @example
|
|
23
23
|
* ```ts
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '0.
|
|
1
|
+
export const VERSION = '0.52.0'; // x-release-please-version
|
package/version.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.52.0";
|
|
2
2
|
//# sourceMappingURL=version.d.mts.map
|
package/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.52.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/version.js
CHANGED
package/version.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = '0.
|
|
1
|
+
export const VERSION = '0.52.0'; // x-release-please-version
|
|
2
2
|
//# sourceMappingURL=version.mjs.map
|