@blaxel/core 0.2.86-preview.165 → 0.2.87-dev.173
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -2
- package/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/authentication/credentials.js +11 -1
- package/dist/cjs/authentication/index.js +3 -1
- package/dist/cjs/client/sdk.gen.js +63 -12
- package/dist/cjs/common/credentials.test.js +71 -0
- package/dist/cjs/common/errors.js +15 -0
- package/dist/cjs/common/h2fetch.js +101 -50
- package/dist/cjs/common/h2pool.js +9 -0
- package/dist/cjs/common/pagination.js +87 -0
- package/dist/cjs/common/pagination.test.js +62 -0
- package/dist/cjs/common/settings.js +41 -3
- package/dist/cjs/common/settings.test.js +12 -3
- package/dist/cjs/drive/index.js +39 -3
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/jobs/jobs.js +42 -9
- package/dist/cjs/sandbox/client/sdk.gen.js +1 -1
- package/dist/cjs/sandbox/preview.js +8 -3
- package/dist/cjs/sandbox/sandbox.js +41 -4
- package/dist/cjs/types/authentication/credentials.d.ts +9 -0
- package/dist/cjs/types/client/sdk.gen.d.ts +34 -19
- package/dist/cjs/types/client/types.gen.d.ts +704 -22
- package/dist/cjs/types/common/credentials.test.d.ts +1 -0
- package/dist/cjs/types/common/errors.d.ts +10 -0
- package/dist/cjs/types/common/h2fetch.d.ts +9 -4
- package/dist/cjs/types/common/pagination.d.ts +35 -0
- package/dist/cjs/types/common/pagination.test.d.ts +1 -0
- package/dist/cjs/types/common/settings.d.ts +9 -0
- package/dist/cjs/types/drive/index.d.ts +35 -4
- package/dist/cjs/types/index.d.ts +1 -0
- package/dist/cjs/types/jobs/jobs.d.ts +33 -3
- package/dist/cjs/types/sandbox/client/sdk.gen.d.ts +1 -1
- package/dist/cjs/types/sandbox/client/types.gen.d.ts +24 -0
- package/dist/cjs/types/sandbox/preview.d.ts +2 -2
- package/dist/cjs/types/sandbox/sandbox.d.ts +36 -2
- package/dist/cjs/types/volume/index.d.ts +37 -4
- package/dist/cjs/volume/index.js +41 -3
- package/dist/cjs-browser/.tsbuildinfo +1 -1
- package/dist/cjs-browser/authentication/credentials.js +11 -1
- package/dist/cjs-browser/authentication/index.js +3 -1
- package/dist/cjs-browser/client/sdk.gen.js +63 -12
- package/dist/cjs-browser/common/credentials.test.js +71 -0
- package/dist/cjs-browser/common/errors.js +15 -0
- package/dist/cjs-browser/common/pagination.js +87 -0
- package/dist/cjs-browser/common/pagination.test.js +62 -0
- package/dist/cjs-browser/common/settings.js +41 -3
- package/dist/cjs-browser/common/settings.test.js +12 -3
- package/dist/cjs-browser/drive/index.js +39 -3
- package/dist/cjs-browser/index.js +1 -0
- package/dist/cjs-browser/jobs/jobs.js +42 -9
- package/dist/cjs-browser/sandbox/client/sdk.gen.js +1 -1
- package/dist/cjs-browser/sandbox/preview.js +8 -3
- package/dist/cjs-browser/sandbox/sandbox.js +41 -4
- package/dist/cjs-browser/types/authentication/credentials.d.ts +9 -0
- package/dist/cjs-browser/types/client/sdk.gen.d.ts +34 -19
- package/dist/cjs-browser/types/client/types.gen.d.ts +704 -22
- package/dist/cjs-browser/types/common/credentials.test.d.ts +1 -0
- package/dist/cjs-browser/types/common/errors.d.ts +10 -0
- package/dist/cjs-browser/types/common/h2fetch.d.ts +9 -4
- package/dist/cjs-browser/types/common/pagination.d.ts +35 -0
- package/dist/cjs-browser/types/common/pagination.test.d.ts +1 -0
- package/dist/cjs-browser/types/common/settings.d.ts +9 -0
- package/dist/cjs-browser/types/drive/index.d.ts +35 -4
- package/dist/cjs-browser/types/index.d.ts +1 -0
- package/dist/cjs-browser/types/jobs/jobs.d.ts +33 -3
- package/dist/cjs-browser/types/sandbox/client/sdk.gen.d.ts +1 -1
- package/dist/cjs-browser/types/sandbox/client/types.gen.d.ts +24 -0
- package/dist/cjs-browser/types/sandbox/preview.d.ts +2 -2
- package/dist/cjs-browser/types/sandbox/sandbox.d.ts +36 -2
- package/dist/cjs-browser/types/volume/index.d.ts +37 -4
- package/dist/cjs-browser/volume/index.js +41 -3
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/authentication/credentials.js +9 -0
- package/dist/esm/authentication/index.js +4 -2
- package/dist/esm/client/sdk.gen.js +57 -9
- package/dist/esm/common/credentials.test.js +69 -0
- package/dist/esm/common/errors.js +13 -0
- package/dist/esm/common/h2fetch.js +101 -50
- package/dist/esm/common/h2pool.js +9 -0
- package/dist/esm/common/pagination.js +83 -0
- package/dist/esm/common/pagination.test.js +60 -0
- package/dist/esm/common/settings.js +41 -3
- package/dist/esm/common/settings.test.js +12 -3
- package/dist/esm/drive/index.js +39 -3
- package/dist/esm/index.js +1 -0
- package/dist/esm/jobs/jobs.js +42 -9
- package/dist/esm/sandbox/client/sdk.gen.js +1 -1
- package/dist/esm/sandbox/preview.js +8 -3
- package/dist/esm/sandbox/sandbox.js +41 -4
- package/dist/esm/volume/index.js +41 -3
- package/dist/esm-browser/.tsbuildinfo +1 -1
- package/dist/esm-browser/authentication/credentials.js +9 -0
- package/dist/esm-browser/authentication/index.js +4 -2
- package/dist/esm-browser/client/sdk.gen.js +57 -9
- package/dist/esm-browser/common/credentials.test.js +69 -0
- package/dist/esm-browser/common/errors.js +13 -0
- package/dist/esm-browser/common/pagination.js +83 -0
- package/dist/esm-browser/common/pagination.test.js +60 -0
- package/dist/esm-browser/common/settings.js +41 -3
- package/dist/esm-browser/common/settings.test.js +12 -3
- package/dist/esm-browser/drive/index.js +39 -3
- package/dist/esm-browser/index.js +1 -0
- package/dist/esm-browser/jobs/jobs.js +42 -9
- package/dist/esm-browser/sandbox/client/sdk.gen.js +1 -1
- package/dist/esm-browser/sandbox/preview.js +8 -3
- package/dist/esm-browser/sandbox/sandbox.js +41 -4
- package/dist/esm-browser/volume/index.js +41 -3
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Credentials = void 0;
|
|
3
|
+
exports.MissingCredentials = exports.Credentials = void 0;
|
|
4
4
|
const env_js_1 = require("../common/env.js");
|
|
5
5
|
class Credentials {
|
|
6
6
|
async authenticate() { }
|
|
@@ -15,3 +15,13 @@ class Credentials {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
exports.Credentials = Credentials;
|
|
18
|
+
/**
|
|
19
|
+
* Marker returned by `authentication()` when no usable Blaxel credentials were
|
|
20
|
+
* resolved (no env vars, no matching config workspace). Construction is
|
|
21
|
+
* side-effect free so importing `@blaxel/core` never fails; the actionable
|
|
22
|
+
* error is raised when an authenticated request is actually attempted
|
|
23
|
+
* (see `Settings.assertCredentials`).
|
|
24
|
+
*/
|
|
25
|
+
class MissingCredentials extends Credentials {
|
|
26
|
+
}
|
|
27
|
+
exports.MissingCredentials = MissingCredentials;
|
|
@@ -51,7 +51,9 @@ function getCredentials() {
|
|
|
51
51
|
function authentication() {
|
|
52
52
|
const credentials = getCredentials();
|
|
53
53
|
if (!credentials) {
|
|
54
|
-
|
|
54
|
+
// Never silently fall back to empty headers: a marker that triggers a
|
|
55
|
+
// clear CredentialsError when an authenticated request is attempted.
|
|
56
|
+
return new credentials_js_1.MissingCredentials();
|
|
55
57
|
}
|
|
56
58
|
if (credentials.apiKey) {
|
|
57
59
|
return new apikey_js_1.ApiKey(credentials);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// This file is auto-generated by @hey-api/openapi-ts
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.
|
|
5
|
-
exports.
|
|
6
|
-
exports.checkWorkspaceAvailability = exports.leaveWorkspace = exports.acceptWorkspaceInvitation = exports.declineWorkspaceInvitation = exports.updateWorkspace = exports.getWorkspace = exports.deleteWorkspace = exports.createWorkspace = exports.listWorkspaces = exports.getEgressIp = exports.deleteEgressIp = exports.createEgressIp = exports.listEgressIps = exports.getEgressGateway = exports.deleteEgressGateway = exports.createEgressGateway = exports.listEgressGateways = exports.getVpc = exports.deleteVpc = exports.createVpc = exports.listVpcs = exports.updateVolume = exports.getVolume = exports.deleteVolume = exports.createVolume = exports.listVolumes = exports.deleteVolumeTemplateVersion = exports.updateVolumeTemplate = exports.getVolumeTemplate = exports.deleteVolumeTemplate = exports.createVolumeTemplate = exports.listVolumeTemplates = exports.updateWorkspaceUserRole = exports.removeWorkspaceUser = void 0;
|
|
4
|
+
exports.listJobs = exports.getIntegrationConnectionModel = exports.listIntegrationConnectionModels = exports.getIntegrationConnectionModelEndpointConfigurations = exports.updateIntegrationConnection = exports.getIntegrationConnection = exports.deleteIntegrationConnection = exports.createIntegrationConnection = exports.listIntegrationConnections = exports.getIntegration = exports.deleteImageTag = exports.unshareImage = exports.shareImage = exports.listImageShares = exports.getImage = exports.deleteImage = exports.createImage = exports.listImages = exports.cleanupImages = exports.listFunctionRevisions = exports.updateFunction = exports.getFunction = exports.deleteFunction = exports.createFunction = exports.listFunctions = exports.testFeatureFlag = exports.getWorkspaceFeatures = exports.listAllEgressIps = exports.getEgressGatewayUsage = exports.listAllEgressGateways = exports.getDriveJwks = exports.createDriveAccessToken = exports.updateDrive = exports.getDrive = exports.deleteDrive = exports.createDrive = exports.listDrives = exports.verifyCustomDomain = exports.updateCustomDomain = exports.getCustomDomain = exports.deleteCustomDomain = exports.createCustomDomain = exports.listCustomDomains = exports.getConfiguration = exports.listAgentRevisions = exports.updateAgent = exports.getAgent = exports.deleteAgent = exports.createAgent = exports.listAgents = void 0;
|
|
5
|
+
exports.listTemplates = exports.deleteApiKeyForServiceAccount = exports.createApiKeyForServiceAccount = exports.listApiKeysForServiceAccount = exports.updateWorkspaceServiceAccount = exports.deleteWorkspaceServiceAccount = exports.createWorkspaceServiceAccount = exports.getWorkspaceServiceAccounts = exports.deleteSandboxPreviewToken = exports.createSandboxPreviewToken = exports.listSandboxPreviewTokens = exports.updateSandboxPreview = exports.getSandboxPreview = exports.deleteSandboxPreview = exports.createSandboxPreview = exports.listSandboxPreviews = exports.updateSandbox = exports.getSandbox = exports.deleteSandbox = exports.createSandbox = exports.listSandboxes = exports.listSandboxHubDefinitions = exports.listPublicIps = exports.getPolicyUsages = exports.updatePolicy = exports.getPolicy = exports.deletePolicy = exports.createPolicy = exports.listPolicies = exports.declineImageShare = exports.acceptImageShare = exports.listPendingImageShares = exports.listModelRevisions = exports.updateModel = exports.getModel = exports.deleteModel = exports.createModel = exports.listModels = exports.listMcpHubDefinitions = exports.listLocations = exports.listJobRevisions = exports.listJobExecutionTasks = exports.getJobExecution = exports.deleteJobExecution = exports.createJobExecution = exports.listJobExecutions = exports.updateJob = exports.getJob = exports.deleteJob = exports.createJob = void 0;
|
|
6
|
+
exports.checkWorkspaceAvailability = exports.leaveWorkspace = exports.acceptWorkspaceInvitation = exports.declineWorkspaceInvitation = exports.updateWorkspace = exports.getWorkspace = exports.deleteWorkspace = exports.createWorkspace = exports.listWorkspaces = exports.getEgressIp = exports.deleteEgressIp = exports.createEgressIp = exports.listEgressIps = exports.getEgressGateway = exports.deleteEgressGateway = exports.createEgressGateway = exports.listEgressGateways = exports.getVpc = exports.deleteVpc = exports.createVpc = exports.listVpcs = exports.updateVolume = exports.getVolume = exports.deleteVolume = exports.createVolume = exports.listVolumes = exports.deleteVolumeTemplateVersion = exports.updateVolumeTemplate = exports.getVolumeTemplate = exports.deleteVolumeTemplate = exports.createVolumeTemplate = exports.listVolumeTemplates = exports.updateWorkspaceUserRole = exports.removeWorkspaceUser = exports.inviteWorkspaceUser = exports.listWorkspaceUsers = exports.getTemplate = void 0;
|
|
7
7
|
const client_gen_1 = require("./client.gen");
|
|
8
8
|
/**
|
|
9
9
|
* List all agents
|
|
10
|
-
* Returns
|
|
10
|
+
* Returns AI agents deployed in the workspace. Each agent includes its deployment status, runtime configuration, and global inference endpoint URL. Starting with API version 2026-04-28 the response is wrapped in `{data, meta}` and supports cursor pagination via the `cursor` and `limit` query parameters; older versions keep returning a bare array with all agents.
|
|
11
11
|
*/
|
|
12
12
|
const listAgents = (options) => {
|
|
13
13
|
return (options?.client ?? client_gen_1.client).get({
|
|
@@ -239,7 +239,7 @@ const verifyCustomDomain = (options) => {
|
|
|
239
239
|
exports.verifyCustomDomain = verifyCustomDomain;
|
|
240
240
|
/**
|
|
241
241
|
* List drives
|
|
242
|
-
* Returns all drives in the workspace. Drives provide persistent storage that can be attached to agents, functions, and sandboxes.
|
|
242
|
+
* Returns all drives in the workspace. Drives provide persistent storage that can be attached to agents, functions, and sandboxes. Starting with API version 2026-04-28, the response wraps items in `{data, meta}` and supports cursor pagination via the `cursor` and `limit` query parameters; older versions keep returning a bare array with all drives.
|
|
243
243
|
*/
|
|
244
244
|
const listDrives = (options) => {
|
|
245
245
|
return (options?.client ?? client_gen_1.client).get({
|
|
@@ -374,6 +374,23 @@ const listAllEgressGateways = (options) => {
|
|
|
374
374
|
});
|
|
375
375
|
};
|
|
376
376
|
exports.listAllEgressGateways = listAllEgressGateways;
|
|
377
|
+
/**
|
|
378
|
+
* Egress gateway sandbox attachments
|
|
379
|
+
* Returns the inverse map (gateway → sandbox names) for the workspace. Used by the egress-IPs UI to render attachment counts without fetching the sandboxes listing full client-side.
|
|
380
|
+
*/
|
|
381
|
+
const getEgressGatewayUsage = (options) => {
|
|
382
|
+
return (options?.client ?? client_gen_1.client).get({
|
|
383
|
+
security: [
|
|
384
|
+
{
|
|
385
|
+
scheme: 'bearer',
|
|
386
|
+
type: 'http'
|
|
387
|
+
}
|
|
388
|
+
],
|
|
389
|
+
url: '/egressgateways/usage',
|
|
390
|
+
...options
|
|
391
|
+
});
|
|
392
|
+
};
|
|
393
|
+
exports.getEgressGatewayUsage = getEgressGatewayUsage;
|
|
377
394
|
/**
|
|
378
395
|
* List all egress IPs across all VPCs and gateways in the workspace
|
|
379
396
|
*/
|
|
@@ -426,7 +443,7 @@ const testFeatureFlag = (options) => {
|
|
|
426
443
|
exports.testFeatureFlag = testFeatureFlag;
|
|
427
444
|
/**
|
|
428
445
|
* List all MCP servers
|
|
429
|
-
* Returns
|
|
446
|
+
* Returns MCP server functions deployed in the workspace. Each function includes its deployment status, transport protocol (websocket or http-stream), and endpoint URL. Starting with API version 2026-04-28 the response is wrapped in `{data, meta}` and supports cursor pagination via the `cursor` and `limit` query parameters; older versions keep returning a bare array with all functions.
|
|
430
447
|
*/
|
|
431
448
|
const listFunctions = (options) => {
|
|
432
449
|
return (options?.client ?? client_gen_1.client).get({
|
|
@@ -858,7 +875,7 @@ const getIntegrationConnectionModel = (options) => {
|
|
|
858
875
|
exports.getIntegrationConnectionModel = getIntegrationConnectionModel;
|
|
859
876
|
/**
|
|
860
877
|
* List batch jobs
|
|
861
|
-
* Returns
|
|
878
|
+
* Returns batch job definitions in the workspace. Each job can be triggered to run multiple parallel tasks with configurable concurrency and retry settings. Starting with API version 2026-04-28 the response is wrapped in `{data, meta}` and supports cursor pagination via the `cursor` and `limit` query parameters; older versions keep returning a bare array with all jobs.
|
|
862
879
|
*/
|
|
863
880
|
const listJobs = (options) => {
|
|
864
881
|
return (options?.client ?? client_gen_1.client).get({
|
|
@@ -951,7 +968,7 @@ const updateJob = (options) => {
|
|
|
951
968
|
exports.updateJob = updateJob;
|
|
952
969
|
/**
|
|
953
970
|
* List job executions
|
|
954
|
-
* Returns
|
|
971
|
+
* Returns executions for a batch job. Starting with API version 2026-04-28 the response is wrapped in `{data, meta}` and supports cursor pagination via the `cursor` and `limit` query parameters; older versions keep the legacy offset/limit contract and return a bare array.
|
|
955
972
|
*/
|
|
956
973
|
const listJobExecutions = (options) => {
|
|
957
974
|
return (options.client ?? client_gen_1.client).get({
|
|
@@ -1021,6 +1038,23 @@ const getJobExecution = (options) => {
|
|
|
1021
1038
|
});
|
|
1022
1039
|
};
|
|
1023
1040
|
exports.getJobExecution = getJobExecution;
|
|
1041
|
+
/**
|
|
1042
|
+
* List execution tasks
|
|
1043
|
+
* Returns one cursor-paginated page of an execution's tasks. Tasks are derived from event history each request; only the in-memory slicing is paginated, the events scan still fetches the whole event log behind the scenes. Available starting with API version 2026-04-28.
|
|
1044
|
+
*/
|
|
1045
|
+
const listJobExecutionTasks = (options) => {
|
|
1046
|
+
return (options.client ?? client_gen_1.client).get({
|
|
1047
|
+
security: [
|
|
1048
|
+
{
|
|
1049
|
+
scheme: 'bearer',
|
|
1050
|
+
type: 'http'
|
|
1051
|
+
}
|
|
1052
|
+
],
|
|
1053
|
+
url: '/jobs/{jobId}/executions/{executionId}/tasks',
|
|
1054
|
+
...options
|
|
1055
|
+
});
|
|
1056
|
+
};
|
|
1057
|
+
exports.listJobExecutionTasks = listJobExecutionTasks;
|
|
1024
1058
|
/**
|
|
1025
1059
|
* List job revisions
|
|
1026
1060
|
* Returns revisions for a job by name.
|
|
@@ -1074,7 +1108,7 @@ const listMcpHubDefinitions = (options) => {
|
|
|
1074
1108
|
exports.listMcpHubDefinitions = listMcpHubDefinitions;
|
|
1075
1109
|
/**
|
|
1076
1110
|
* List model endpoints
|
|
1077
|
-
* Returns
|
|
1111
|
+
* Returns model gateway endpoints configured in the workspace. Each model represents a proxy to an external LLM provider (OpenAI, Anthropic, etc.) with unified access control. Starting with API version 2026-04-28 the response is wrapped in `{data, meta}` and supports cursor pagination via the `cursor` and `limit` query parameters; older versions keep returning a bare array with all models.
|
|
1078
1112
|
*/
|
|
1079
1113
|
const listModels = (options) => {
|
|
1080
1114
|
return (options?.client ?? client_gen_1.client).get({
|
|
@@ -1235,7 +1269,7 @@ const declineImageShare = (options) => {
|
|
|
1235
1269
|
exports.declineImageShare = declineImageShare;
|
|
1236
1270
|
/**
|
|
1237
1271
|
* List governance policies
|
|
1238
|
-
* Returns
|
|
1272
|
+
* Returns governance policies in the workspace. Policies control deployment locations, hardware flavors, and token limits for agents, functions, and models. Starting with API version 2026-04-28 the response is wrapped in `{data, meta}` and supports cursor pagination via the `cursor` and `limit` query parameters; older versions keep returning a bare array with all policies.
|
|
1239
1273
|
*/
|
|
1240
1274
|
const listPolicies = (options) => {
|
|
1241
1275
|
return (options?.client ?? client_gen_1.client).get({
|
|
@@ -1326,6 +1360,23 @@ const updatePolicy = (options) => {
|
|
|
1326
1360
|
});
|
|
1327
1361
|
};
|
|
1328
1362
|
exports.updatePolicy = updatePolicy;
|
|
1363
|
+
/**
|
|
1364
|
+
* List resources using a policy
|
|
1365
|
+
* Returns the names of every resource (agent, function, model, sandbox, job) currently referencing the given policy. Replaces the client-side fan-out the policies UI used to do over the listings.
|
|
1366
|
+
*/
|
|
1367
|
+
const getPolicyUsages = (options) => {
|
|
1368
|
+
return (options.client ?? client_gen_1.client).get({
|
|
1369
|
+
security: [
|
|
1370
|
+
{
|
|
1371
|
+
scheme: 'bearer',
|
|
1372
|
+
type: 'http'
|
|
1373
|
+
}
|
|
1374
|
+
],
|
|
1375
|
+
url: '/policies/{policyName}/usages',
|
|
1376
|
+
...options
|
|
1377
|
+
});
|
|
1378
|
+
};
|
|
1379
|
+
exports.getPolicyUsages = getPolicyUsages;
|
|
1329
1380
|
/**
|
|
1330
1381
|
* List public ips
|
|
1331
1382
|
* Returns a list of all public ips used in Blaxel..
|
|
@@ -1362,7 +1413,7 @@ const listSandboxHubDefinitions = (options) => {
|
|
|
1362
1413
|
exports.listSandboxHubDefinitions = listSandboxHubDefinitions;
|
|
1363
1414
|
/**
|
|
1364
1415
|
* List sandboxes
|
|
1365
|
-
* Returns
|
|
1416
|
+
* Returns sandboxes in the workspace. Each sandbox includes its configuration, status, and endpoint URL. Terminated sandboxes are hidden by default; pass `showTerminated=true` to include them. Starting with API version 2026-04-28 the response is wrapped in `{data, meta}` and supports cursor pagination via the `cursor` and `limit` query parameters; older versions keep returning a bare array of all sandboxes.
|
|
1366
1417
|
*/
|
|
1367
1418
|
const listSandboxes = (options) => {
|
|
1368
1419
|
return (options?.client ?? client_gen_1.client).get({
|
|
@@ -1954,7 +2005,7 @@ const deleteVolumeTemplateVersion = (options) => {
|
|
|
1954
2005
|
exports.deleteVolumeTemplateVersion = deleteVolumeTemplateVersion;
|
|
1955
2006
|
/**
|
|
1956
2007
|
* List persistent volumes
|
|
1957
|
-
* Returns
|
|
2008
|
+
* Returns persistent storage volumes in the workspace. Volumes can be attached to sandboxes for durable file storage that persists across sessions and sandbox deletions. Starting with API version 2026-04-28 the response is wrapped in `{data, meta}` and supports cursor pagination via the `cursor` and `limit` query parameters; older versions keep returning a bare array of volumes.
|
|
1958
2009
|
*/
|
|
1959
2010
|
const listVolumes = (options) => {
|
|
1960
2011
|
return (options?.client ?? client_gen_1.client).get({
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const apikey_js_1 = require("../authentication/apikey.js");
|
|
5
|
+
const credentials_js_1 = require("../authentication/credentials.js");
|
|
6
|
+
const index_js_1 = require("../authentication/index.js");
|
|
7
|
+
const errors_js_1 = require("./errors.js");
|
|
8
|
+
const settings_js_1 = require("./settings.js");
|
|
9
|
+
/**
|
|
10
|
+
* ENG-2698: missing / partial BL_WORKSPACE / BL_API_KEY must fail fast with a
|
|
11
|
+
* clear, actionable error instead of silently sending empty headers and
|
|
12
|
+
* surfacing the server's misleading "workspace is required".
|
|
13
|
+
*
|
|
14
|
+
* `env` reads through to `process.env`, so env state is controlled there.
|
|
15
|
+
*/
|
|
16
|
+
(0, vitest_1.describe)('credential validation', () => {
|
|
17
|
+
const AUTH_ENV = ['BL_API_KEY', 'BL_WORKSPACE', 'BL_CLIENT_CREDENTIALS'];
|
|
18
|
+
let savedEnv;
|
|
19
|
+
let savedCredentials;
|
|
20
|
+
let savedConfig;
|
|
21
|
+
(0, vitest_1.beforeEach)(() => {
|
|
22
|
+
savedEnv = {};
|
|
23
|
+
for (const key of AUTH_ENV) {
|
|
24
|
+
savedEnv[key] = process.env[key];
|
|
25
|
+
delete process.env[key];
|
|
26
|
+
}
|
|
27
|
+
savedCredentials = settings_js_1.settings.credentials;
|
|
28
|
+
savedConfig = settings_js_1.settings.config;
|
|
29
|
+
settings_js_1.settings.config = { proxy: '', apikey: '', workspace: '' };
|
|
30
|
+
});
|
|
31
|
+
(0, vitest_1.afterEach)(() => {
|
|
32
|
+
for (const key of AUTH_ENV) {
|
|
33
|
+
if (savedEnv[key] === undefined)
|
|
34
|
+
delete process.env[key];
|
|
35
|
+
else
|
|
36
|
+
process.env[key] = savedEnv[key];
|
|
37
|
+
}
|
|
38
|
+
settings_js_1.settings.credentials = savedCredentials;
|
|
39
|
+
settings_js_1.settings.config = savedConfig;
|
|
40
|
+
});
|
|
41
|
+
(0, vitest_1.it)('API key without workspace throws a clear BL_WORKSPACE error from headers', () => {
|
|
42
|
+
settings_js_1.settings.credentials = new apikey_js_1.ApiKey({ apiKey: 'test-key' });
|
|
43
|
+
(0, vitest_1.expect)(() => settings_js_1.settings.headers).toThrow(errors_js_1.CredentialsError);
|
|
44
|
+
(0, vitest_1.expect)(() => settings_js_1.settings.headers).toThrow(/BL_WORKSPACE/);
|
|
45
|
+
});
|
|
46
|
+
(0, vitest_1.it)('API key without workspace rejects from authenticate()', async () => {
|
|
47
|
+
settings_js_1.settings.credentials = new apikey_js_1.ApiKey({ apiKey: 'test-key' });
|
|
48
|
+
await (0, vitest_1.expect)(settings_js_1.settings.authenticate()).rejects.toThrow(/BL_WORKSPACE/);
|
|
49
|
+
});
|
|
50
|
+
(0, vitest_1.it)('workspace set but no API key names the missing API key', () => {
|
|
51
|
+
process.env.BL_WORKSPACE = 'my-workspace';
|
|
52
|
+
settings_js_1.settings.credentials = new credentials_js_1.MissingCredentials();
|
|
53
|
+
(0, vitest_1.expect)(() => settings_js_1.settings.headers).toThrow(/API key is missing/);
|
|
54
|
+
});
|
|
55
|
+
(0, vitest_1.it)('no credentials at all names both env vars', () => {
|
|
56
|
+
settings_js_1.settings.credentials = new credentials_js_1.MissingCredentials();
|
|
57
|
+
(0, vitest_1.expect)(() => settings_js_1.settings.headers).toThrow(errors_js_1.CredentialsError);
|
|
58
|
+
(0, vitest_1.expect)(() => settings_js_1.settings.headers).toThrow(/BL_API_KEY and BL_WORKSPACE/);
|
|
59
|
+
});
|
|
60
|
+
(0, vitest_1.it)('api key + workspace builds clean headers with no empty values', () => {
|
|
61
|
+
settings_js_1.settings.credentials = new apikey_js_1.ApiKey({ apiKey: 'test-key', workspace: 'my-workspace' });
|
|
62
|
+
const headers = settings_js_1.settings.headers;
|
|
63
|
+
(0, vitest_1.expect)(headers['x-blaxel-workspace']).toBe('my-workspace');
|
|
64
|
+
(0, vitest_1.expect)(headers['x-blaxel-authorization']).toBe('Bearer test-key');
|
|
65
|
+
(0, vitest_1.expect)(Object.values(headers)).not.toContain('');
|
|
66
|
+
});
|
|
67
|
+
(0, vitest_1.it)('authentication() returns a real ApiKey when BL_API_KEY is set', () => {
|
|
68
|
+
process.env.BL_API_KEY = 'test-key';
|
|
69
|
+
(0, vitest_1.expect)((0, index_js_1.authentication)()).toBeInstanceOf(apikey_js_1.ApiKey);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CredentialsError = void 0;
|
|
3
4
|
exports.handleDynamicImportError = handleDynamicImportError;
|
|
5
|
+
/**
|
|
6
|
+
* Thrown when Blaxel credentials are missing or incomplete.
|
|
7
|
+
*
|
|
8
|
+
* Surfaced eagerly with an actionable message (which env var / login step is
|
|
9
|
+
* missing) instead of silently sending empty workspace/authorization headers
|
|
10
|
+
* and letting the user hit a misleading server-side "workspace is required".
|
|
11
|
+
*/
|
|
12
|
+
class CredentialsError extends Error {
|
|
13
|
+
constructor(message) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = "CredentialsError";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.CredentialsError = CredentialsError;
|
|
4
19
|
function handleDynamicImportError(err) {
|
|
5
20
|
if (err instanceof Error) {
|
|
6
21
|
// We check if it's module import error and retrieve package name from the error message with a regex
|
|
@@ -17,14 +17,21 @@ const sessionsWithListenerBudget = new WeakSet();
|
|
|
17
17
|
* When `settings.maxConcurrentH2Requests` is `0`/unset the gate is a no-op
|
|
18
18
|
* (current default behavior: unlimited concurrency).
|
|
19
19
|
*/
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
|
|
20
|
+
// Last-resort leak guard for a held slot. The slot is now released on the real
|
|
21
|
+
// stream terminal (end / error / abort / cancel / pre-response reject), which
|
|
22
|
+
// always fires, so this timer is a pure backstop for the one residual case: a
|
|
23
|
+
// request that never opens a stream AND never settles (no response, no error,
|
|
24
|
+
// no abort) — it must not pin a slot forever and starve the per-domain queue.
|
|
25
|
+
//
|
|
26
|
+
// When it fires it ONLY frees the queue slot. It NEVER aborts or cancels the
|
|
27
|
+
// underlying request or its response stream: `release` does not touch `req` or
|
|
28
|
+
// the body stream, so a long-lived streaming response keeps flowing. Raised
|
|
29
|
+
// well beyond any legitimate stream lifetime so it cannot interfere with a
|
|
30
|
+
// healthy long-open stream (process.streamLogs / execWithStreaming / port
|
|
31
|
+
// proxy). RESIDUAL: a stream that outlives this backstop would have its slot
|
|
32
|
+
// freed early (the queue could then admit one extra stream); acceptable as a
|
|
33
|
+
// pure backstop, since the slot is otherwise tied to the true stream terminal.
|
|
34
|
+
const H2_SLOT_TIMEOUT_MS = 1_800_000; // 30 minutes
|
|
28
35
|
const h2GatesByDomain = new Map();
|
|
29
36
|
function getH2Gate(domain) {
|
|
30
37
|
let gate = h2GatesByDomain.get(domain);
|
|
@@ -35,10 +42,14 @@ function getH2Gate(domain) {
|
|
|
35
42
|
return gate;
|
|
36
43
|
}
|
|
37
44
|
/**
|
|
38
|
-
* Acquire an
|
|
39
|
-
* that is idempotent and FIFO-fair: releasing wakes the longest-waiting
|
|
40
|
-
*
|
|
41
|
-
*
|
|
45
|
+
* Acquire an OPEN-STREAM slot for `domain`. Resolves with a release function
|
|
46
|
+
* that is idempotent and FIFO-fair: releasing wakes the longest-waiting queued
|
|
47
|
+
* caller for the same domain. The slot is held for the lifetime of an OPEN H2
|
|
48
|
+
* stream — the send path releases it on the stream terminal — so the gate
|
|
49
|
+
* bounds true concurrent streams on the one shared session, not merely requests
|
|
50
|
+
* awaiting headers (ENG-2678). A backstop timer releases the slot if a request
|
|
51
|
+
* neither opens a stream nor ever settles, preventing per-domain starvation;
|
|
52
|
+
* it never aborts the underlying request (see `H2_SLOT_TIMEOUT_MS`).
|
|
42
53
|
*/
|
|
43
54
|
async function acquireH2Slot(domain) {
|
|
44
55
|
const max = settings_js_1.settings.maxConcurrentH2Requests; // 0/undefined = unlimited
|
|
@@ -92,66 +103,89 @@ function createH2Fetch(session) {
|
|
|
92
103
|
};
|
|
93
104
|
}
|
|
94
105
|
/**
|
|
95
|
-
*
|
|
106
|
+
* The single HTTP/2 request gateway (ENG-2679).
|
|
96
107
|
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
108
|
+
* Every pool-backed request funnels through here, no matter which entry point
|
|
109
|
+
* it came from: the generated client's fetch (`createPoolBackedH2Fetch`),
|
|
110
|
+
* `SandboxAction.h2Fetch`, and the interpreter's direct path (both via
|
|
111
|
+
* `h2RequestDirectFromPool`). It owns the shared request lifecycle in one place:
|
|
112
|
+
* 1. take a per-domain open-stream slot,
|
|
113
|
+
* 2. get a live session from the pool,
|
|
114
|
+
* 3. send the request on it,
|
|
115
|
+
* 4. evict the session if the send fails after a stream was opened,
|
|
116
|
+
* 5. fall back to globalThis.fetch when the pool has no usable session.
|
|
117
|
+
*
|
|
118
|
+
* This is the chokepoint where reliability behavior that must protect EVERY
|
|
119
|
+
* consumer belongs: the open-stream concurrency limit today, and retry,
|
|
120
|
+
* timeouts, typed errors, and observability in later phases. Adding it once here
|
|
121
|
+
* (instead of re-implementing it per entry point) is what stops the recurring
|
|
122
|
+
* "fixed on one path, still broken on another" regressions.
|
|
123
|
+
*
|
|
124
|
+
* `send` performs the actual wire send on a live session; the caller supplies it
|
|
125
|
+
* so the gateway stays agnostic to the `Request` vs `(url, init)` call shapes,
|
|
126
|
+
* and it receives the slot-release and request-created hooks. `fallback` runs
|
|
127
|
+
* only when the pool has no usable session (a fresh connection, no shared
|
|
128
|
+
* stream is opened).
|
|
100
129
|
*/
|
|
101
|
-
function
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
try {
|
|
109
|
-
return await _h2Request(session, input, {
|
|
110
|
-
onH2RequestCreated: () => {
|
|
111
|
-
h2RequestCreated = true;
|
|
112
|
-
},
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
catch (err) {
|
|
116
|
-
if (h2RequestCreated) {
|
|
117
|
-
pool.evictSession(domain, session);
|
|
118
|
-
}
|
|
119
|
-
throw err;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return await globalThis.fetch(input);
|
|
123
|
-
}
|
|
124
|
-
finally {
|
|
125
|
-
rel();
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
async function h2RequestDirectFromPool(pool, domain, url, init) {
|
|
130
|
+
async function h2GatewayRequest(pool, domain, send, fallback) {
|
|
131
|
+
// Take the slot here, but hand its release to the send path: it is held for
|
|
132
|
+
// the OPEN-STREAM lifetime and freed on the stream terminal (ENG-2678). A
|
|
133
|
+
// request that never opens a stream on the shared session (the fallback goes
|
|
134
|
+
// over a different connection) releases it immediately so it does not count
|
|
135
|
+
// against the open-stream budget. `rel` is idempotent, so releasing here when
|
|
136
|
+
// the send path may also release is safe.
|
|
130
137
|
const rel = await acquireH2Slot(domain);
|
|
131
138
|
try {
|
|
132
139
|
const session = await pool.get(domain);
|
|
133
140
|
if (session) {
|
|
134
141
|
let h2RequestCreated = false;
|
|
135
142
|
try {
|
|
136
|
-
return await
|
|
143
|
+
return await send(session, {
|
|
137
144
|
onH2RequestCreated: () => {
|
|
138
145
|
h2RequestCreated = true;
|
|
139
146
|
},
|
|
147
|
+
releaseSlot: rel,
|
|
140
148
|
});
|
|
141
149
|
}
|
|
142
150
|
catch (err) {
|
|
151
|
+
// A failure AFTER a stream opened means the session is suspect: drop it
|
|
152
|
+
// so the next caller gets a fresh one.
|
|
143
153
|
if (h2RequestCreated) {
|
|
144
154
|
pool.evictSession(domain, session);
|
|
145
155
|
}
|
|
146
156
|
throw err;
|
|
147
157
|
}
|
|
148
158
|
}
|
|
149
|
-
|
|
159
|
+
// No usable session: free the slot before falling back over a different
|
|
160
|
+
// connection (no stream opens on the shared session).
|
|
161
|
+
rel();
|
|
162
|
+
return await fallback();
|
|
150
163
|
}
|
|
151
|
-
|
|
164
|
+
catch (err) {
|
|
165
|
+
// Pre-send throw (pool.get(), Request body read, or the fallback itself):
|
|
166
|
+
// release the slot so a failed request never pins it. Idempotent.
|
|
152
167
|
rel();
|
|
168
|
+
throw err;
|
|
153
169
|
}
|
|
154
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Creates a fetch()-compatible function backed by the H2 session pool, routed
|
|
173
|
+
* through the single gateway. Used as the generated client's `fetch`.
|
|
174
|
+
*
|
|
175
|
+
* If no usable H2 session is available, the request falls back to regular fetch
|
|
176
|
+
* before any H2 frames are sent.
|
|
177
|
+
*/
|
|
178
|
+
function createPoolBackedH2Fetch(pool, domain) {
|
|
179
|
+
return (input) => h2GatewayRequest(pool, domain, (session, options) => _h2Request(session, input, options), () => globalThis.fetch(input));
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Pool-backed H2 request taking raw url + init (skips Request allocation),
|
|
183
|
+
* routed through the same single gateway. Used by `SandboxAction.h2Fetch` and
|
|
184
|
+
* the code interpreter.
|
|
185
|
+
*/
|
|
186
|
+
function h2RequestDirectFromPool(pool, domain, url, init) {
|
|
187
|
+
return h2GatewayRequest(pool, domain, (session, options) => h2RequestDirectInternal(session, url, init, options), () => globalThis.fetch(url, init));
|
|
188
|
+
}
|
|
155
189
|
/**
|
|
156
190
|
* Low-level H2 request that takes raw URL + init, skipping Request construction.
|
|
157
191
|
* Used by SandboxAction.h2Fetch() for direct calls from subsystems.
|
|
@@ -161,6 +195,9 @@ function h2RequestDirect(session, url, init) {
|
|
|
161
195
|
}
|
|
162
196
|
function h2RequestDirectInternal(session, url, init, options) {
|
|
163
197
|
if (session.closed || session.destroyed) {
|
|
198
|
+
// Pre-flight fallback (session unusable): no stream opens on the shared
|
|
199
|
+
// session, so free any held slot before going over globalThis.fetch.
|
|
200
|
+
options?.releaseSlot?.();
|
|
164
201
|
return globalThis.fetch(url, init);
|
|
165
202
|
}
|
|
166
203
|
const parsed = new URL(url);
|
|
@@ -200,7 +237,9 @@ function h2RequestDirectInternal(session, url, init, options) {
|
|
|
200
237
|
else {
|
|
201
238
|
// FormData, ReadableStream, Blob, etc. can't be serialized to Buffer
|
|
202
239
|
// for manual H2 framing — fall back to regular fetch (pre-flight,
|
|
203
|
-
// nothing has been sent on the wire yet).
|
|
240
|
+
// nothing has been sent on the wire yet). No stream opens on the shared
|
|
241
|
+
// session, so free any held slot before falling back.
|
|
242
|
+
options?.releaseSlot?.();
|
|
204
243
|
return globalThis.fetch(url, init);
|
|
205
244
|
}
|
|
206
245
|
if (!h2Headers["content-length"]) {
|
|
@@ -244,13 +283,19 @@ function _h2Send(session, h2Headers, body, signal, fallbackUrl, fallbackInit, op
|
|
|
244
283
|
let streamClosed = false;
|
|
245
284
|
let req = null;
|
|
246
285
|
let releaseSessionRef = () => { };
|
|
286
|
+
// The per-domain open-stream slot (idempotent; no-op for the non-pool
|
|
287
|
+
// transports). Held for the OPEN-STREAM lifetime and released alongside the
|
|
288
|
+
// session ref from cleanupActiveRequest() on every terminal path.
|
|
289
|
+
const releaseSlot = options?.releaseSlot ?? (() => { });
|
|
247
290
|
let abort = null;
|
|
248
291
|
try {
|
|
249
292
|
req = session.request(h2Headers);
|
|
250
293
|
}
|
|
251
294
|
catch {
|
|
252
295
|
// Pre-flight fallback: session.request() threw synchronously, so no
|
|
253
|
-
// H2 frames were sent.
|
|
296
|
+
// H2 frames were sent. No stream opened on the shared session, so free
|
|
297
|
+
// the slot before retrying over globalThis.fetch.
|
|
298
|
+
releaseSlot();
|
|
254
299
|
globalThis.fetch(fallbackUrl, fallbackInit).then(resolve, reject);
|
|
255
300
|
return;
|
|
256
301
|
}
|
|
@@ -265,7 +310,13 @@ function _h2Send(session, h2Headers, body, signal, fallbackUrl, fallbackInit, op
|
|
|
265
310
|
const cleanupActiveRequest = () => {
|
|
266
311
|
if (abort)
|
|
267
312
|
signal?.removeEventListener("abort", abort);
|
|
313
|
+
// Slot and session-ref share the OPEN-STREAM lifetime but stay
|
|
314
|
+
// independent and each idempotent (PM-2160). Every terminal path funnels
|
|
315
|
+
// through here exactly once: pre-response reject (close/goaway/error),
|
|
316
|
+
// abort-before-response, abort-during-stream, stream end, stream error,
|
|
317
|
+
// and ReadableStream cancel — so the slot is freed once on each.
|
|
268
318
|
releaseSessionRef();
|
|
319
|
+
releaseSlot();
|
|
269
320
|
};
|
|
270
321
|
const rejectBeforeResponse = (err) => {
|
|
271
322
|
if (settled)
|
|
@@ -153,6 +153,15 @@ class H2Pool {
|
|
|
153
153
|
return session;
|
|
154
154
|
}
|
|
155
155
|
if (await this.ping(session)) {
|
|
156
|
+
// ENG-2676 generation/identity pin: `await this.ping` yields, and during
|
|
157
|
+
// that await an eviction listener (goaway/error/close ->
|
|
158
|
+
// attachEvictionListeners, see above) may have deleted or replaced this
|
|
159
|
+
// entry. `entry` is the exact object held in the map, so if it is no
|
|
160
|
+
// longer the cached generation, refuse the now-stale session instead of
|
|
161
|
+
// handing back a zombie — the ENG-2422 failure re-entering through the
|
|
162
|
+
// validate race. The caller falls through to establish a fresh session.
|
|
163
|
+
if (this.sessions.get(domain) !== entry)
|
|
164
|
+
return null;
|
|
156
165
|
this.markUsed(domain, session);
|
|
157
166
|
return session;
|
|
158
167
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.unwrapListData = unwrapListData;
|
|
4
|
+
exports.createPaginatedList = createPaginatedList;
|
|
5
|
+
function unwrapListData(response) {
|
|
6
|
+
if (!response) {
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
if (Array.isArray(response)) {
|
|
10
|
+
return response;
|
|
11
|
+
}
|
|
12
|
+
return response.data ?? [];
|
|
13
|
+
}
|
|
14
|
+
function unwrapListMeta(response) {
|
|
15
|
+
if (!response || Array.isArray(response)) {
|
|
16
|
+
return { hasMore: false };
|
|
17
|
+
}
|
|
18
|
+
return response.meta ?? { hasMore: false };
|
|
19
|
+
}
|
|
20
|
+
async function createPaginatedList({ response, fetchPage, mapItem, query, seenCursors, }) {
|
|
21
|
+
const meta = unwrapListMeta(response);
|
|
22
|
+
const data = await Promise.all(unwrapListData(response).map(mapItem));
|
|
23
|
+
const cursors = new Set(seenCursors);
|
|
24
|
+
if (query?.cursor) {
|
|
25
|
+
cursors.add(query.cursor);
|
|
26
|
+
}
|
|
27
|
+
const list = {
|
|
28
|
+
data,
|
|
29
|
+
meta,
|
|
30
|
+
get hasMore() {
|
|
31
|
+
return Boolean(meta.hasMore);
|
|
32
|
+
},
|
|
33
|
+
get nextCursor() {
|
|
34
|
+
return meta.nextCursor || undefined;
|
|
35
|
+
},
|
|
36
|
+
async nextPage() {
|
|
37
|
+
const cursor = list.nextCursor;
|
|
38
|
+
if (!cursor) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
if (cursors.has(cursor)) {
|
|
42
|
+
throw new Error("Pagination returned a repeated cursor");
|
|
43
|
+
}
|
|
44
|
+
const nextQuery = { ...(query ?? {}), cursor };
|
|
45
|
+
const nextSeenCursors = new Set(cursors);
|
|
46
|
+
nextSeenCursors.add(cursor);
|
|
47
|
+
return createPaginatedList({
|
|
48
|
+
response: await fetchPage(nextQuery),
|
|
49
|
+
fetchPage,
|
|
50
|
+
mapItem,
|
|
51
|
+
query: nextQuery,
|
|
52
|
+
seenCursors: nextSeenCursors,
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
async autoPagingEach(onItem) {
|
|
56
|
+
for await (const item of list) {
|
|
57
|
+
const shouldContinue = await onItem(item);
|
|
58
|
+
if (shouldContinue === false) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
async autoPagingToArray(options) {
|
|
64
|
+
if (!options || !Number.isFinite(options.limit) || options.limit <= 0) {
|
|
65
|
+
throw new Error("autoPagingToArray requires a positive limit");
|
|
66
|
+
}
|
|
67
|
+
const items = [];
|
|
68
|
+
for await (const item of list) {
|
|
69
|
+
items.push(item);
|
|
70
|
+
if (items.length >= options.limit) {
|
|
71
|
+
return items;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return items;
|
|
75
|
+
},
|
|
76
|
+
async *[Symbol.asyncIterator]() {
|
|
77
|
+
let page = list;
|
|
78
|
+
while (page) {
|
|
79
|
+
for (const item of page.data) {
|
|
80
|
+
yield item;
|
|
81
|
+
}
|
|
82
|
+
page = await page.nextPage();
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
return list;
|
|
87
|
+
}
|