@datalayer/core 1.0.19 → 1.0.21
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 +27 -0
- package/lib/api/DatalayerApi.d.ts +5 -1
- package/lib/api/DatalayerApi.js +55 -8
- package/lib/api/iam/oauth2.d.ts +3 -3
- package/lib/api/iam/oauth2.js +2 -2
- package/lib/api/iam/profile.d.ts +9 -1
- package/lib/api/iam/profile.js +15 -0
- package/lib/api/runtimes/checkpoints.js +1 -1
- package/lib/api/runtimes/snapshots.d.ts +7 -7
- package/lib/api/runtimes/snapshots.js +9 -9
- package/lib/client/auth/storage.js +103 -12
- package/lib/client/index.d.ts +7 -7
- package/lib/client/index.js +1 -1
- package/lib/client/mixins/RuntimesMixin.d.ts +6 -6
- package/lib/client/mixins/RuntimesMixin.js +5 -5
- package/lib/client/mixins/SpacerMixin.js +22 -1
- package/lib/collaboration/DatalayerCollaborationProvider.d.ts +4 -3
- package/lib/components/avatars/DLAvatar.d.ts +24 -0
- package/lib/components/avatars/DLAvatar.js +26 -0
- package/lib/components/avatars/UserProfileAvatar.js +4 -4
- package/lib/components/avatars/index.d.ts +1 -0
- package/lib/components/avatars/index.js +1 -0
- package/lib/components/checkout/StripeCheckout.d.ts +24 -3
- package/lib/components/checkout/StripeCheckout.js +1116 -55
- package/lib/components/display/DatalayerBox.js +6 -1
- package/lib/components/runtimes/RuntimeLauncherDialog.d.ts +2 -2
- package/lib/components/snapshots/{RuntimeSnapshotMenu.d.ts → SandboxSnapshotMenu.d.ts} +4 -4
- package/lib/components/snapshots/{RuntimeSnapshotMenu.js → SandboxSnapshotMenu.js} +33 -33
- package/lib/components/snapshots/index.d.ts +1 -1
- package/lib/components/snapshots/index.js +1 -1
- package/lib/components/storage/ContentsBrowser.js +2 -2
- package/lib/components/tokens/SpaceVariantToken.d.ts +1 -1
- package/lib/components/tokens/SpaceVariantToken.js +7 -4
- package/lib/components/users/PeerIndicator.js +5 -4
- package/lib/hooks/useCache.d.ts +125 -18
- package/lib/hooks/useCache.js +893 -120
- package/lib/hooks/useDatalayer.js +31 -3
- package/lib/hooks/useIAM.js +1 -8
- package/lib/hooks/useProjects.d.ts +44 -0
- package/lib/hooks/useProjects.js +26 -2
- package/lib/index.d.ts +2 -2
- package/lib/index.js +1 -1
- package/lib/mocks/components/FlashMock.js +8 -2
- package/lib/models/{RuntimeSnapshot.d.ts → CodeSandboxSnapshot.d.ts} +5 -5
- package/lib/models/{RuntimeSnapshot.js → CodeSandboxSnapshot.js} +1 -1
- package/lib/models/{RuntimeSnapshotDTO.d.ts → CodeSandboxSnapshotDTO.d.ts} +30 -30
- package/lib/models/{RuntimeSnapshotDTO.js → CodeSandboxSnapshotDTO.js} +6 -6
- package/lib/models/Environment.d.ts +4 -0
- package/lib/models/IAM.d.ts +66 -0
- package/lib/models/Organization.d.ts +1 -0
- package/lib/models/Organization.js +1 -0
- package/lib/models/Page.d.ts +2 -2
- package/lib/models/Page.js +2 -2
- package/lib/models/Profile.d.ts +1 -1
- package/lib/models/RuntimeDTO.d.ts +2 -2
- package/lib/models/Space.d.ts +1 -0
- package/lib/models/Space.js +29 -5
- package/lib/models/SpaceDTO.d.ts +4 -0
- package/lib/models/SpaceDTO.js +5 -0
- package/lib/models/Usage.d.ts +15 -0
- package/lib/models/Usage.js +9 -0
- package/lib/models/User.d.ts +21 -0
- package/lib/models/User.js +6 -2
- package/lib/models/index.d.ts +2 -2
- package/lib/models/index.js +2 -2
- package/lib/otel/auth.js +0 -4
- package/lib/services/index.d.ts +1 -1
- package/lib/services/index.js +1 -1
- package/lib/state/substates/IAMState.js +0 -7
- package/lib/state/substates/RuntimesState.d.ts +9 -9
- package/lib/state/substates/RuntimesState.js +3 -3
- package/lib/stateful/runtimes/actions.d.ts +17 -17
- package/lib/stateful/runtimes/actions.js +35 -55
- package/lib/stateful/runtimes/apis.d.ts +3 -3
- package/lib/stateful/runtimes/snapshots.d.ts +2 -2
- package/lib/stateful/runtimes/snapshots.js +7 -7
- package/lib/utils/Format.d.ts +6 -0
- package/lib/utils/Format.js +17 -0
- package/lib/utils/Snapshot.d.ts +1 -1
- package/lib/utils/Snapshot.js +1 -1
- package/lib/views/datasources/DatasourceDetail.d.ts +7 -1
- package/lib/views/datasources/DatasourceDetail.js +61 -23
- package/lib/views/datasources/DatasourceNew.d.ts +8 -1
- package/lib/views/datasources/DatasourceNew.js +23 -10
- package/lib/views/datasources/Datasources.d.ts +5 -1
- package/lib/views/datasources/Datasources.js +38 -30
- package/lib/views/iam/SignInSimple.d.ts +1 -1
- package/lib/views/iam/SignInSimple.js +52 -28
- package/lib/views/iam-tokens/IAMTokenNew.d.ts +3 -1
- package/lib/views/iam-tokens/IAMTokenNew.js +2 -2
- package/lib/views/iam-tokens/IAMTokens.d.ts +3 -1
- package/lib/views/iam-tokens/IAMTokens.js +2 -2
- package/lib/views/otel/OtelHeader.d.ts +5 -0
- package/lib/views/otel/OtelHeader.js +3 -3
- package/lib/views/profile/UserBadge.d.ts +21 -0
- package/lib/views/profile/UserBadge.js +100 -8
- package/lib/views/secrets/Secrets.js +21 -21
- package/package.json +8 -7
package/README.md
CHANGED
|
@@ -124,6 +124,33 @@ datalayer runtime exec my-script.py --runtime <runtime-id>
|
|
|
124
124
|
datalayer snapshots create <pod-name> my-snapshot 'AI work!' False
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
+
### 4. Subscription and Credits CLI
|
|
128
|
+
|
|
129
|
+
Use these commands to inspect billing and manage credits distribution.
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# End-user billing view
|
|
133
|
+
datalayer subscriptions show
|
|
134
|
+
datalayer subscriptions available
|
|
135
|
+
datalayer subscriptions move
|
|
136
|
+
datalayer subscriptions topups
|
|
137
|
+
datalayer subscriptions dry-run
|
|
138
|
+
|
|
139
|
+
# Organization and team credits visibility
|
|
140
|
+
datalayer usage org-overview --organization-uid <org_uid>
|
|
141
|
+
datalayer usage team-overview --team-uid <team_uid>
|
|
142
|
+
|
|
143
|
+
# Monitoring-driven credit management
|
|
144
|
+
datalayer usage org-monitor --organization-uid <org_uid> --window-hours 24
|
|
145
|
+
datalayer usage team-monitor --team-uid <team_uid> --window-hours 24
|
|
146
|
+
|
|
147
|
+
# Credits transfer operations (owners/admins)
|
|
148
|
+
datalayer usage org-allocate-team --organization-uid <org_uid> --team-uid <team_uid> --amount 50
|
|
149
|
+
datalayer usage org-revoke-team --organization-uid <org_uid> --team-uid <team_uid> --amount 20
|
|
150
|
+
datalayer usage team-allocate-member --team-uid <team_uid> --member-uid <member_uid> --amount 15
|
|
151
|
+
datalayer usage team-revoke-member --team-uid <team_uid> --member-uid <member_uid> --amount 5
|
|
152
|
+
```
|
|
153
|
+
|
|
127
154
|
## Examples
|
|
128
155
|
|
|
129
156
|
### Python Examples
|
|
@@ -14,7 +14,7 @@ export declare class RunResponseError extends Error {
|
|
|
14
14
|
/**
|
|
15
15
|
* Create a new response error.
|
|
16
16
|
*/
|
|
17
|
-
constructor(response: Response, message?: string, warnings?: undefined, errors?: undefined, exceptionMessage?: undefined, traceback?: string);
|
|
17
|
+
constructor(response: Response, message?: string, warnings?: undefined, errors?: undefined, exceptionMessage?: undefined, traceback?: string, detail?: unknown);
|
|
18
18
|
/**
|
|
19
19
|
* Warnings listed in the response.
|
|
20
20
|
*/
|
|
@@ -35,6 +35,10 @@ export declare class RunResponseError extends Error {
|
|
|
35
35
|
* The traceback associated with the error.
|
|
36
36
|
*/
|
|
37
37
|
readonly traceback: string;
|
|
38
|
+
/**
|
|
39
|
+
* Optional structured backend detail payload.
|
|
40
|
+
*/
|
|
41
|
+
readonly detail: unknown;
|
|
38
42
|
private static _defaultMessage;
|
|
39
43
|
}
|
|
40
44
|
/**
|
package/lib/api/DatalayerApi.js
CHANGED
|
@@ -11,6 +11,24 @@
|
|
|
11
11
|
import { URLExt } from '@jupyterlab/coreutils';
|
|
12
12
|
import axios from 'axios';
|
|
13
13
|
import { sleep } from '../utils/Sleep.js';
|
|
14
|
+
function isFormDataBody(body) {
|
|
15
|
+
if (!body || typeof body !== 'object') {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
// `instanceof FormData` is not reliable across realms (e.g. jsdom/undici).
|
|
19
|
+
if (typeof FormData !== 'undefined' && body instanceof FormData) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
const formDataTag = Object.prototype.toString.call(body);
|
|
23
|
+
if (formDataTag === '[object FormData]') {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
const candidate = body;
|
|
27
|
+
return (typeof candidate.append === 'function' &&
|
|
28
|
+
typeof candidate.get === 'function' &&
|
|
29
|
+
typeof candidate.has === 'function' &&
|
|
30
|
+
typeof candidate.entries === 'function');
|
|
31
|
+
}
|
|
14
32
|
/**
|
|
15
33
|
* Error wrapper for failed HTTP responses.
|
|
16
34
|
* Includes response details, warnings, errors, and tracebacks.
|
|
@@ -26,11 +44,17 @@ export class RunResponseError extends Error {
|
|
|
26
44
|
static async create(response) {
|
|
27
45
|
try {
|
|
28
46
|
const data = await response.json();
|
|
29
|
-
const { message, errors, warnings, traceback, exception } = data;
|
|
47
|
+
const { message, errors, warnings, traceback, exception, detail } = data;
|
|
48
|
+
const resolvedMessage = message ??
|
|
49
|
+
(typeof detail === 'string'
|
|
50
|
+
? detail
|
|
51
|
+
: detail && typeof detail === 'object' && 'message' in detail
|
|
52
|
+
? String(detail.message)
|
|
53
|
+
: undefined);
|
|
30
54
|
if (traceback) {
|
|
31
55
|
console.error(traceback);
|
|
32
56
|
}
|
|
33
|
-
const responseError = new RunResponseError(response,
|
|
57
|
+
const responseError = new RunResponseError(response, resolvedMessage ?? RunResponseError._defaultMessage(response), warnings, errors, exception, traceback ?? '', detail);
|
|
34
58
|
return responseError;
|
|
35
59
|
}
|
|
36
60
|
catch (e) {
|
|
@@ -41,7 +65,7 @@ export class RunResponseError extends Error {
|
|
|
41
65
|
/**
|
|
42
66
|
* Create a new response error.
|
|
43
67
|
*/
|
|
44
|
-
constructor(response, message = RunResponseError._defaultMessage(response), warnings = undefined, errors = undefined, exceptionMessage = undefined, traceback = '') {
|
|
68
|
+
constructor(response, message = RunResponseError._defaultMessage(response), warnings = undefined, errors = undefined, exceptionMessage = undefined, traceback = '', detail = undefined) {
|
|
45
69
|
super(message);
|
|
46
70
|
this.name = 'RunResponseError';
|
|
47
71
|
this.warnings = warnings ?? [];
|
|
@@ -49,6 +73,7 @@ export class RunResponseError extends Error {
|
|
|
49
73
|
this.response = response;
|
|
50
74
|
this.exceptionMessage = exceptionMessage;
|
|
51
75
|
this.traceback = traceback;
|
|
76
|
+
this.detail = detail;
|
|
52
77
|
}
|
|
53
78
|
/**
|
|
54
79
|
* Warnings listed in the response.
|
|
@@ -70,6 +95,10 @@ export class RunResponseError extends Error {
|
|
|
70
95
|
* The traceback associated with the error.
|
|
71
96
|
*/
|
|
72
97
|
traceback;
|
|
98
|
+
/**
|
|
99
|
+
* Optional structured backend detail payload.
|
|
100
|
+
*/
|
|
101
|
+
detail;
|
|
73
102
|
static _defaultMessage(response) {
|
|
74
103
|
return `Invalid response: ${response.status} ${response.statusText}`;
|
|
75
104
|
}
|
|
@@ -110,7 +139,7 @@ export class NetworkError extends TypeError {
|
|
|
110
139
|
*/
|
|
111
140
|
export async function requestDatalayerAPI({ url, method, body, token, signal, headers = {}, }) {
|
|
112
141
|
// Handle FormData differently from JSON
|
|
113
|
-
const isFormData = body
|
|
142
|
+
const isFormData = isFormDataBody(body);
|
|
114
143
|
// Prepare axios config
|
|
115
144
|
const axiosConfig = {
|
|
116
145
|
url,
|
|
@@ -198,10 +227,28 @@ export async function requestDatalayerAPI({ url, method, body, token, signal, he
|
|
|
198
227
|
async function handleAxiosRedirection(response, originalConfig) {
|
|
199
228
|
let redirect = response.headers.location;
|
|
200
229
|
if (redirect) {
|
|
201
|
-
const
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
230
|
+
const baseUrl = originalConfig.url ?? '';
|
|
231
|
+
const normalizedRedirect = String(redirect).replace(/^([a-z][a-z0-9+.-]*):\/(?!\/)/i, '$1://');
|
|
232
|
+
try {
|
|
233
|
+
const resolved = new URL(normalizedRedirect, baseUrl);
|
|
234
|
+
const base = new URL(baseUrl, typeof window !== 'undefined' ? window.location.origin : undefined);
|
|
235
|
+
// If a proxy emits an http Location for the same host while the
|
|
236
|
+
// original request is https, force https to avoid mixed-content errors
|
|
237
|
+
// that browsers often report as CORS/network failures.
|
|
238
|
+
if (base.protocol === 'https:' &&
|
|
239
|
+
resolved.protocol === 'http:' &&
|
|
240
|
+
resolved.hostname === base.hostname) {
|
|
241
|
+
resolved.protocol = 'https:';
|
|
242
|
+
if (resolved.port === '80') {
|
|
243
|
+
resolved.port = '';
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
redirect = resolved.toString();
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
const parsedURL = URLExt.parse(baseUrl);
|
|
250
|
+
const fallbackBase = parsedURL.protocol + '//' + parsedURL.hostname;
|
|
251
|
+
redirect = URLExt.join(fallbackBase, normalizedRedirect);
|
|
205
252
|
}
|
|
206
253
|
}
|
|
207
254
|
let sleepTimeout = 1000;
|
package/lib/api/iam/oauth2.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* OAuth2 provider types supported by the platform
|
|
3
3
|
*/
|
|
4
|
-
export type OAuth2Provider = 'github' | 'linkedin' | 'okta';
|
|
4
|
+
export type OAuth2Provider = 'github' | 'google' | 'linkedin' | 'okta';
|
|
5
5
|
/**
|
|
6
6
|
* Response from the OAuth2 authorization URL endpoint
|
|
7
7
|
*/
|
|
@@ -26,7 +26,7 @@ export interface OAuth2CallbackParams {
|
|
|
26
26
|
export type OAuth2CallbackResponse = string;
|
|
27
27
|
/**
|
|
28
28
|
* Get the OAuth2 authorization URL for a specific provider
|
|
29
|
-
* @param provider - OAuth2 provider (
|
|
29
|
+
* @param provider - OAuth2 provider (github, google, linkedin, okta)
|
|
30
30
|
* @param callbackUri - Server endpoint to call with the authz token
|
|
31
31
|
* @param nonce - Optional nonce for security
|
|
32
32
|
* @param baseUrl - Base URL for the API (defaults to production IAM URL)
|
|
@@ -45,7 +45,7 @@ export type OAuth2CallbackResponse = string;
|
|
|
45
45
|
export declare const getOAuth2AuthzUrl: (provider: OAuth2Provider, callbackUri: string, nonce?: string, baseUrl?: string) => Promise<OAuth2AuthzUrlResponse>;
|
|
46
46
|
/**
|
|
47
47
|
* Get the OAuth2 authorization URL for linking a provider to an existing account
|
|
48
|
-
* @param provider - OAuth2 provider (
|
|
48
|
+
* @param provider - OAuth2 provider (github, google, linkedin, okta)
|
|
49
49
|
* @param callbackUri - Server endpoint to call with the authz token
|
|
50
50
|
* @param baseUrl - Base URL for the API (defaults to production IAM URL)
|
|
51
51
|
* @returns OAuth2 authorization URL response
|
package/lib/api/iam/oauth2.js
CHANGED
|
@@ -13,7 +13,7 @@ import { requestDatalayerAPI } from '../DatalayerApi.js';
|
|
|
13
13
|
import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../constants.js';
|
|
14
14
|
/**
|
|
15
15
|
* Get the OAuth2 authorization URL for a specific provider
|
|
16
|
-
* @param provider - OAuth2 provider (
|
|
16
|
+
* @param provider - OAuth2 provider (github, google, linkedin, okta)
|
|
17
17
|
* @param callbackUri - Server endpoint to call with the authz token
|
|
18
18
|
* @param nonce - Optional nonce for security
|
|
19
19
|
* @param baseUrl - Base URL for the API (defaults to production IAM URL)
|
|
@@ -71,7 +71,7 @@ export const getOAuth2AuthzUrl = async (provider, callbackUri, nonce, baseUrl =
|
|
|
71
71
|
};
|
|
72
72
|
/**
|
|
73
73
|
* Get the OAuth2 authorization URL for linking a provider to an existing account
|
|
74
|
-
* @param provider - OAuth2 provider (
|
|
74
|
+
* @param provider - OAuth2 provider (github, google, linkedin, okta)
|
|
75
75
|
* @param callbackUri - Server endpoint to call with the authz token
|
|
76
76
|
* @param baseUrl - Base URL for the API (defaults to production IAM URL)
|
|
77
77
|
* @returns OAuth2 authorization URL response
|
package/lib/api/iam/profile.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MembershipsResponse, UserMeResponse, WhoAmIResponse } from '../../models/IAM';
|
|
1
|
+
import { MembershipsResponse, ShareablePrincipalsResponse, UserMeResponse, WhoAmIResponse } from '../../models/IAM';
|
|
2
2
|
/**
|
|
3
3
|
* Get current authenticated user profile
|
|
4
4
|
* @param token - Authentication token (required)
|
|
@@ -20,3 +20,11 @@ export declare const whoami: (token: string, baseUrl?: string) => Promise<WhoAmI
|
|
|
20
20
|
* @returns Current user identity and profile information
|
|
21
21
|
*/
|
|
22
22
|
export declare const memberships: (token: string, baseUrl?: string) => Promise<MembershipsResponse>;
|
|
23
|
+
/**
|
|
24
|
+
* Get the set of principals the authenticated user can share artifacts with
|
|
25
|
+
* (self + member organizations + member teams).
|
|
26
|
+
*
|
|
27
|
+
* @param token - Authentication token (required)
|
|
28
|
+
* @param baseUrl - Base URL for the API (defaults to production IAM URL)
|
|
29
|
+
*/
|
|
30
|
+
export declare const principalsShareable: (token: string, baseUrl?: string) => Promise<ShareablePrincipalsResponse>;
|
package/lib/api/iam/profile.js
CHANGED
|
@@ -54,3 +54,18 @@ export const memberships = async (token, baseUrl = DEFAULT_SERVICE_URLS.IAM) =>
|
|
|
54
54
|
token,
|
|
55
55
|
});
|
|
56
56
|
};
|
|
57
|
+
/**
|
|
58
|
+
* Get the set of principals the authenticated user can share artifacts with
|
|
59
|
+
* (self + member organizations + member teams).
|
|
60
|
+
*
|
|
61
|
+
* @param token - Authentication token (required)
|
|
62
|
+
* @param baseUrl - Base URL for the API (defaults to production IAM URL)
|
|
63
|
+
*/
|
|
64
|
+
export const principalsShareable = async (token, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
|
|
65
|
+
validateToken(token);
|
|
66
|
+
return requestDatalayerAPI({
|
|
67
|
+
url: `${baseUrl}${API_BASE_PATHS.IAM}/principals/shareable`,
|
|
68
|
+
method: 'GET',
|
|
69
|
+
token,
|
|
70
|
+
});
|
|
71
|
+
};
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Runtime checkpoints API functions for the Datalayer platform.
|
|
7
7
|
*
|
|
8
8
|
* Provides functions for managing CRIU full-pod checkpoints.
|
|
9
|
-
* These are distinct from
|
|
9
|
+
* These are distinct from code sandbox snapshots (Jupyter sandbox snapshots).
|
|
10
10
|
*
|
|
11
11
|
* @module api/runtimes/checkpoints
|
|
12
12
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CreateCodeSandboxSnapshotRequest, ListCodeSandboxSnapshotsResponse, GetCodeSandboxSnapshotResponse, CreateCodeSandboxSnapshotResponse } from '../../models/CodeSandboxSnapshotDTO';
|
|
2
2
|
/**
|
|
3
3
|
* Create a snapshot of a runtime instance.
|
|
4
4
|
* @param token - Authentication token
|
|
@@ -7,17 +7,17 @@ import { CreateRuntimeSnapshotRequest, ListRuntimeSnapshotsResponse, GetRuntimeS
|
|
|
7
7
|
* @returns Promise resolving to the created snapshot response
|
|
8
8
|
* @throws {Error} If authentication token is missing or invalid
|
|
9
9
|
*/
|
|
10
|
-
export declare const createSnapshot: (token: string, data:
|
|
10
|
+
export declare const createSnapshot: (token: string, data: CreateCodeSandboxSnapshotRequest, baseUrl?: string) => Promise<CreateCodeSandboxSnapshotResponse>;
|
|
11
11
|
/**
|
|
12
|
-
* List all
|
|
12
|
+
* List all code sandbox snapshots.
|
|
13
13
|
* @param token - Authentication token
|
|
14
14
|
* @param baseUrl - Base URL for the API (defaults to production Runtimes URL)
|
|
15
15
|
* @returns Promise resolving to list of snapshots
|
|
16
16
|
* @throws {Error} If authentication token is missing or invalid
|
|
17
17
|
*/
|
|
18
|
-
export declare const listSnapshots: (token: string, baseUrl?: string) => Promise<
|
|
18
|
+
export declare const listSnapshots: (token: string, baseUrl?: string) => Promise<ListCodeSandboxSnapshotsResponse>;
|
|
19
19
|
/**
|
|
20
|
-
* Get details for a specific
|
|
20
|
+
* Get details for a specific code sandbox snapshot.
|
|
21
21
|
* @param token - Authentication token
|
|
22
22
|
* @param snapshotId - The unique identifier of the snapshot
|
|
23
23
|
* @param baseUrl - Base URL for the API (defaults to production Runtimes URL)
|
|
@@ -25,9 +25,9 @@ export declare const listSnapshots: (token: string, baseUrl?: string) => Promise
|
|
|
25
25
|
* @throws {Error} If authentication token is missing or invalid
|
|
26
26
|
* @throws {Error} If snapshot ID is missing or invalid
|
|
27
27
|
*/
|
|
28
|
-
export declare const getSnapshot: (token: string, snapshotId: string, baseUrl?: string) => Promise<
|
|
28
|
+
export declare const getSnapshot: (token: string, snapshotId: string, baseUrl?: string) => Promise<GetCodeSandboxSnapshotResponse>;
|
|
29
29
|
/**
|
|
30
|
-
* Delete a
|
|
30
|
+
* Delete a code sandbox snapshot.
|
|
31
31
|
* @param token - Authentication token
|
|
32
32
|
* @param snapshotId - The unique identifier of the snapshot to delete
|
|
33
33
|
* @param baseUrl - Base URL for the API (defaults to production Runtimes URL)
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Code Sandbox snapshots API functions for the Datalayer platform.
|
|
7
7
|
*
|
|
8
|
-
* Provides functions for managing
|
|
8
|
+
* Provides functions for managing code sandbox snapshots (saved runtime states).
|
|
9
9
|
*
|
|
10
10
|
* @module api/runtimes/snapshots
|
|
11
11
|
*/
|
|
@@ -23,14 +23,14 @@ import { validateToken, validateRequiredString } from '../utils/validation.js';
|
|
|
23
23
|
export const createSnapshot = async (token, data, baseUrl = DEFAULT_SERVICE_URLS.RUNTIMES) => {
|
|
24
24
|
validateToken(token);
|
|
25
25
|
return requestDatalayerAPI({
|
|
26
|
-
url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/
|
|
26
|
+
url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/sandbox-snapshots`,
|
|
27
27
|
method: 'POST',
|
|
28
28
|
token,
|
|
29
29
|
body: data,
|
|
30
30
|
});
|
|
31
31
|
};
|
|
32
32
|
/**
|
|
33
|
-
* List all
|
|
33
|
+
* List all code sandbox snapshots.
|
|
34
34
|
* @param token - Authentication token
|
|
35
35
|
* @param baseUrl - Base URL for the API (defaults to production Runtimes URL)
|
|
36
36
|
* @returns Promise resolving to list of snapshots
|
|
@@ -39,13 +39,13 @@ export const createSnapshot = async (token, data, baseUrl = DEFAULT_SERVICE_URLS
|
|
|
39
39
|
export const listSnapshots = async (token, baseUrl = DEFAULT_SERVICE_URLS.RUNTIMES) => {
|
|
40
40
|
validateToken(token);
|
|
41
41
|
return requestDatalayerAPI({
|
|
42
|
-
url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/
|
|
42
|
+
url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/sandbox-snapshots`,
|
|
43
43
|
method: 'GET',
|
|
44
44
|
token,
|
|
45
45
|
});
|
|
46
46
|
};
|
|
47
47
|
/**
|
|
48
|
-
* Get details for a specific
|
|
48
|
+
* Get details for a specific code sandbox snapshot.
|
|
49
49
|
* @param token - Authentication token
|
|
50
50
|
* @param snapshotId - The unique identifier of the snapshot
|
|
51
51
|
* @param baseUrl - Base URL for the API (defaults to production Runtimes URL)
|
|
@@ -57,13 +57,13 @@ export const getSnapshot = async (token, snapshotId, baseUrl = DEFAULT_SERVICE_U
|
|
|
57
57
|
validateToken(token);
|
|
58
58
|
validateRequiredString(snapshotId, 'Snapshot ID');
|
|
59
59
|
return requestDatalayerAPI({
|
|
60
|
-
url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/
|
|
60
|
+
url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/sandbox-snapshots/${snapshotId}`,
|
|
61
61
|
method: 'GET',
|
|
62
62
|
token,
|
|
63
63
|
});
|
|
64
64
|
};
|
|
65
65
|
/**
|
|
66
|
-
* Delete a
|
|
66
|
+
* Delete a code sandbox snapshot.
|
|
67
67
|
* @param token - Authentication token
|
|
68
68
|
* @param snapshotId - The unique identifier of the snapshot to delete
|
|
69
69
|
* @param baseUrl - Base URL for the API (defaults to production Runtimes URL)
|
|
@@ -75,7 +75,7 @@ export const deleteSnapshot = async (token, snapshotId, baseUrl = DEFAULT_SERVIC
|
|
|
75
75
|
validateToken(token);
|
|
76
76
|
validateRequiredString(snapshotId, 'Snapshot ID');
|
|
77
77
|
return requestDatalayerAPI({
|
|
78
|
-
url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/
|
|
78
|
+
url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/sandbox-snapshots/${snapshotId}`,
|
|
79
79
|
method: 'DELETE',
|
|
80
80
|
token,
|
|
81
81
|
});
|
|
@@ -11,6 +11,68 @@
|
|
|
11
11
|
* Token storage backend implementations
|
|
12
12
|
*/
|
|
13
13
|
import { DATALAYER_IAM_TOKEN_KEY, DATALAYER_IAM_USER_KEY, } from '../../state/storage/IAMStorage.js';
|
|
14
|
+
/**
|
|
15
|
+
* Resolve a real Node `require` function that survives bundling.
|
|
16
|
+
*
|
|
17
|
+
* `module.createRequire()` is the documented Node API for obtaining a
|
|
18
|
+
* require function that resolves modules against `node_modules`. Three
|
|
19
|
+
* runtimes need to be supported:
|
|
20
|
+
*
|
|
21
|
+
* 1. **Native Node ESM** (this package is `"type": "module"`). The
|
|
22
|
+
* global `require` is undefined here, so we resolve `module` via
|
|
23
|
+
* `process.getBuiltinModule('module')` (added in Node 22.3 / 20.16).
|
|
24
|
+
* 2. **Native Node CommonJS** and **bundler-injected CJS shims**
|
|
25
|
+
* (e.g. webpack with `target: 'node'`). These expose a working
|
|
26
|
+
* global `require`, and `require('module')` resolves to the real
|
|
27
|
+
* Node builtin even after bundling.
|
|
28
|
+
* 3. **Native browser**. None of the above is available; we return
|
|
29
|
+
* `null`.
|
|
30
|
+
*
|
|
31
|
+
* @returns A real Node `require`, or `null` outside Node, or
|
|
32
|
+
* `undefined` if Node is detected but no `createRequire` source is
|
|
33
|
+
* reachable (extremely old Node, or a hostile sandbox).
|
|
34
|
+
*/
|
|
35
|
+
function resolveNodeRequire() {
|
|
36
|
+
if (typeof process === 'undefined' || !process.versions?.node) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
const fname = typeof __filename !== 'undefined'
|
|
40
|
+
? __filename
|
|
41
|
+
: process.cwd() + '/__datalayer_keytar_loader__.js';
|
|
42
|
+
// 1. ESM-safe path: process.getBuiltinModule (Node 22.3+ / 20.16+).
|
|
43
|
+
// Lets a `"type": "module"` package reach into `module` without a
|
|
44
|
+
// CommonJS-only `require`.
|
|
45
|
+
const nodeProcess = process;
|
|
46
|
+
try {
|
|
47
|
+
const mod = nodeProcess.getBuiltinModule?.('module');
|
|
48
|
+
if (typeof mod?.createRequire === 'function') {
|
|
49
|
+
return mod.createRequire(fname);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Fall through to the CommonJS / bundler path.
|
|
54
|
+
}
|
|
55
|
+
// 2. CommonJS path: `require('module')` is left intact by webpack
|
|
56
|
+
// when target: 'node'. Also covers older Node CJS where
|
|
57
|
+
// getBuiltinModule does not exist.
|
|
58
|
+
try {
|
|
59
|
+
if (typeof require === 'function') {
|
|
60
|
+
const mod = require('module');
|
|
61
|
+
if (typeof mod?.createRequire === 'function') {
|
|
62
|
+
return mod.createRequire(fname);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Fall through to globalThis.require.
|
|
68
|
+
}
|
|
69
|
+
// 3. Last-ditch: a globalThis.require shim from some host environments.
|
|
70
|
+
const g = globalThis;
|
|
71
|
+
if (typeof g.require === 'function') {
|
|
72
|
+
return g.require;
|
|
73
|
+
}
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
14
76
|
/**
|
|
15
77
|
* Browser localStorage-based token storage
|
|
16
78
|
*/
|
|
@@ -136,21 +198,50 @@ export class NodeStorage {
|
|
|
136
198
|
typeof process !== 'undefined' &&
|
|
137
199
|
process.versions?.node) {
|
|
138
200
|
try {
|
|
139
|
-
//
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
201
|
+
// Resolve a real Node `require` even when this module ends up
|
|
202
|
+
// inside a webpack bundle.
|
|
203
|
+
//
|
|
204
|
+
// Why not the previous `string-evaluated require` pattern? Webpack
|
|
205
|
+
// rewrites that pattern to its own loader (`__webpack_require__`),
|
|
206
|
+
// which has no entry for these runtime-only keyring modules
|
|
207
|
+
// (`@github/keytar`, `@vscode/keytar`, or legacy `keytar`)
|
|
208
|
+
// because the require call is hidden behind a string and is
|
|
209
|
+
// therefore invisible to webpack's static analysis — even when
|
|
210
|
+
// consumers declare those package IDs as commonjs/runtime
|
|
211
|
+
// externals. The result was that `this.keytar` silently stayed
|
|
212
|
+
// `null` in any webpacked host (e.g. the VS Code extension), so
|
|
213
|
+
// tokens written via `setAsync()` only landed in the in-memory
|
|
214
|
+
// `Map` and never made it to the OS keyring. They appeared to
|
|
215
|
+
// "save" within a session, but vanished on reload.
|
|
216
|
+
//
|
|
217
|
+
// `module.createRequire(...)` is the documented Node API for
|
|
218
|
+
// obtaining the real require, and webpack/Vite/Rollup all leave
|
|
219
|
+
// it intact when the host targets Node.
|
|
220
|
+
const nodeRequire = resolveNodeRequire();
|
|
221
|
+
if (nodeRequire) {
|
|
222
|
+
// Try variants in order of preference:
|
|
223
|
+
// 1. @github/keytar — actively maintained, ships prebuilt
|
|
224
|
+
// binaries for every platform in the npm tarball, so a
|
|
225
|
+
// single multi-platform VSIX / Electron build can ship
|
|
226
|
+
// it without per-OS rebuilds.
|
|
227
|
+
// 2. @vscode/keytar — historically bundled with VS Code,
|
|
228
|
+
// no longer published to npm but still resolvable in
|
|
229
|
+
// some host environments.
|
|
230
|
+
// 3. keytar — the original, deprecated upstream. Kept as a
|
|
231
|
+
// fallback so existing CLI installs that still depend
|
|
232
|
+
// on it keep working.
|
|
233
|
+
for (const id of ['@github/keytar', '@vscode/keytar', 'keytar']) {
|
|
234
|
+
try {
|
|
235
|
+
this.keytar = nodeRequire(id);
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
// Try next variant.
|
|
240
|
+
}
|
|
150
241
|
}
|
|
151
242
|
}
|
|
152
243
|
}
|
|
153
|
-
catch
|
|
244
|
+
catch {
|
|
154
245
|
// Keyring not available, tokens will not persist across sessions
|
|
155
246
|
console.warn('keytar not available, tokens will not persist');
|
|
156
247
|
}
|
package/lib/client/index.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ import type { UserDTO } from './../models/UserDTO';
|
|
|
19
19
|
import type { CreditsDTO } from '../models/CreditsDTO';
|
|
20
20
|
import type { EnvironmentDTO } from '../models/EnvironmentDTO';
|
|
21
21
|
import type { RuntimeDTO } from '../models/RuntimeDTO';
|
|
22
|
-
import type {
|
|
22
|
+
import type { CodeSandboxSnapshotDTO } from '../models/CodeSandboxSnapshotDTO';
|
|
23
23
|
import type { SpaceDTO } from '../models/SpaceDTO';
|
|
24
24
|
import type { NotebookDTO } from '../models/NotebookDTO';
|
|
25
25
|
import type { LexicalDTO } from '../models/LexicalDTO';
|
|
@@ -65,8 +65,8 @@ export { RuntimeDTO as Runtime } from '../models/RuntimeDTO';
|
|
|
65
65
|
export type { RuntimeJSON, RuntimeData, CreateRuntimeRequest, CreateRuntimeResponse, ListRuntimesResponse, } from '../models/RuntimeDTO';
|
|
66
66
|
export { EnvironmentDTO as Environment } from '../models/EnvironmentDTO';
|
|
67
67
|
export type { EnvironmentJSON, EnvironmentData, ListEnvironmentsResponse, } from '../models/EnvironmentDTO';
|
|
68
|
-
export {
|
|
69
|
-
export type {
|
|
68
|
+
export { CodeSandboxSnapshotDTO as Snapshot } from '../models/CodeSandboxSnapshotDTO';
|
|
69
|
+
export type { CodeSandboxSnapshotJSON, CodeSandboxSnapshotData, CreateCodeSandboxSnapshotRequest, CreateCodeSandboxSnapshotResponse, GetCodeSandboxSnapshotResponse, ListCodeSandboxSnapshotsResponse, } from '../models/CodeSandboxSnapshotDTO';
|
|
70
70
|
export { SpaceDTO as Space } from '../models/SpaceDTO';
|
|
71
71
|
export type { SpaceJSON, SpaceData, SpaceItem, CreateSpaceRequest, CreateSpaceResponse, SpacesForUserResponse, CollaborationSessionResponse, DeleteSpaceItemResponse, GetSpaceItemResponse, GetSpaceItemsResponse, CreateNotebookRequest, CreateNotebookResponse, GetNotebookResponse, UpdateNotebookRequest, UpdateNotebookResponse, UpdateSpaceRequest, GetSpaceResponse, UpdateSpaceResponse, DeleteSpaceResponse, GetSpaceDefaultItemsResponse, GetSpacesByTypeResponse, } from '../models/SpaceDTO';
|
|
72
72
|
export { ProjectDTO as Project } from '../models/ProjectDTO';
|
|
@@ -97,7 +97,7 @@ export type { ISpace, IBaseSpace, IAnySpace, ISpaceVariant, } from '../models/Sp
|
|
|
97
97
|
export type { IBaseTeam, IAnyTeam } from '../models/Team';
|
|
98
98
|
export type { IOrganization, IAnyOrganization, IBaseOrganization, } from '../models/Organization';
|
|
99
99
|
export type { IRuntimeModel, IRuntimePod, IRuntimeType, IRuntimeLocation, IRuntimeCapabilities, } from '../models/Runtime';
|
|
100
|
-
export type {
|
|
100
|
+
export type { ICodeSandboxSnapshot } from '../models/CodeSandboxSnapshot';
|
|
101
101
|
export type { IDatalayerEnvironment, IResources, ISnippet, } from '../models/Environment';
|
|
102
102
|
export type { IRole } from '../models/Role';
|
|
103
103
|
export type { IAssignment } from '../models/Assignment';
|
|
@@ -170,9 +170,9 @@ export interface DatalayerClient {
|
|
|
170
170
|
getRuntime(podName: string): Promise<RuntimeDTO>;
|
|
171
171
|
deleteRuntime(podName: string): Promise<void>;
|
|
172
172
|
terminateAllRuntimes(): Promise<PromiseSettledResult<void>[]>;
|
|
173
|
-
createSnapshot(podName: string, name: string, description: string, stop?: boolean): Promise<
|
|
174
|
-
listSnapshots(): Promise<
|
|
175
|
-
getSnapshot(id: string): Promise<
|
|
173
|
+
createSnapshot(podName: string, name: string, description: string, stop?: boolean): Promise<CodeSandboxSnapshotDTO>;
|
|
174
|
+
listSnapshots(): Promise<CodeSandboxSnapshotDTO[]>;
|
|
175
|
+
getSnapshot(id: string): Promise<CodeSandboxSnapshotDTO>;
|
|
176
176
|
deleteSnapshot(id: string): Promise<void>;
|
|
177
177
|
checkRuntimesHealth(): Promise<HealthCheck>;
|
|
178
178
|
getMySpaces(): Promise<SpaceDTO[]>;
|
package/lib/client/index.js
CHANGED
|
@@ -68,7 +68,7 @@ export { DatalayerClientBase };
|
|
|
68
68
|
export { UserDTO as User } from './../models/UserDTO.js';
|
|
69
69
|
export { RuntimeDTO as Runtime } from '../models/RuntimeDTO.js';
|
|
70
70
|
export { EnvironmentDTO as Environment } from '../models/EnvironmentDTO.js';
|
|
71
|
-
export {
|
|
71
|
+
export { CodeSandboxSnapshotDTO as Snapshot } from '../models/CodeSandboxSnapshotDTO.js';
|
|
72
72
|
export { SpaceDTO as Space } from '../models/SpaceDTO.js';
|
|
73
73
|
export { ProjectDTO as Project } from '../models/ProjectDTO.js';
|
|
74
74
|
export { NotebookDTO as Notebook } from '../models/NotebookDTO.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Constructor } from '../utils/mixins';
|
|
2
2
|
import { EnvironmentDTO } from '../../models/EnvironmentDTO';
|
|
3
3
|
import { RuntimeDTO } from '../../models/RuntimeDTO';
|
|
4
|
-
import {
|
|
4
|
+
import { CodeSandboxSnapshotDTO } from '../../models/CodeSandboxSnapshotDTO';
|
|
5
5
|
import { HealthCheck } from '../../models/HealthCheck';
|
|
6
6
|
/** Options for ensuring a runtime is available. */
|
|
7
7
|
export interface EnsureRuntimeOptions {
|
|
@@ -22,7 +22,7 @@ export interface EnsureRuntimeOptions {
|
|
|
22
22
|
export declare function RuntimesMixin<TBase extends Constructor>(Base: TBase): {
|
|
23
23
|
new (...args: any[]): {
|
|
24
24
|
_extractRuntimePodName(runtimePodNameOrInstance: string | RuntimeDTO): string;
|
|
25
|
-
_extractSnapshotId(snapshotIdOrInstance: string |
|
|
25
|
+
_extractSnapshotId(snapshotIdOrInstance: string | CodeSandboxSnapshotDTO): string;
|
|
26
26
|
/**
|
|
27
27
|
* List all available computational environments.
|
|
28
28
|
* @returns Array of Environment model instances
|
|
@@ -67,18 +67,18 @@ export declare function RuntimesMixin<TBase extends Constructor>(Base: TBase): {
|
|
|
67
67
|
* @param stop - Whether to stop the runtime after creating snapshot (defaults to false)
|
|
68
68
|
* @returns Created snapshot
|
|
69
69
|
*/
|
|
70
|
-
createSnapshot(podName: string, name: string, description: string, stop?: boolean): Promise<
|
|
70
|
+
createSnapshot(podName: string, name: string, description: string, stop?: boolean): Promise<CodeSandboxSnapshotDTO>;
|
|
71
71
|
/**
|
|
72
|
-
* List all
|
|
72
|
+
* List all code sandbox snapshots.
|
|
73
73
|
* @returns Array of snapshots
|
|
74
74
|
*/
|
|
75
|
-
listSnapshots(): Promise<
|
|
75
|
+
listSnapshots(): Promise<CodeSandboxSnapshotDTO[]>;
|
|
76
76
|
/**
|
|
77
77
|
* Get details for a specific snapshot by ID.
|
|
78
78
|
* @param id - Snapshot ID
|
|
79
79
|
* @returns Snapshot details
|
|
80
80
|
*/
|
|
81
|
-
getSnapshot(id: string): Promise<
|
|
81
|
+
getSnapshot(id: string): Promise<CodeSandboxSnapshotDTO>;
|
|
82
82
|
/**
|
|
83
83
|
* Delete a snapshot permanently.
|
|
84
84
|
* @param id - Snapshot ID
|
|
@@ -11,7 +11,7 @@ import * as runtimes from '../../api/runtimes/runtimes.js';
|
|
|
11
11
|
import * as snapshots from '../../api/runtimes/snapshots.js';
|
|
12
12
|
import { EnvironmentDTO } from '../../models/EnvironmentDTO.js';
|
|
13
13
|
import { RuntimeDTO } from '../../models/RuntimeDTO.js';
|
|
14
|
-
import {
|
|
14
|
+
import { CodeSandboxSnapshotDTO } from '../../models/CodeSandboxSnapshotDTO.js';
|
|
15
15
|
import { HealthCheck } from '../../models/HealthCheck.js';
|
|
16
16
|
/** Runtimes mixin providing computational environment and runtime management. */
|
|
17
17
|
export function RuntimesMixin(Base) {
|
|
@@ -148,17 +148,17 @@ export function RuntimesMixin(Base) {
|
|
|
148
148
|
stop,
|
|
149
149
|
};
|
|
150
150
|
const response = await snapshots.createSnapshot(token, data, runtimesRunUrl);
|
|
151
|
-
return new
|
|
151
|
+
return new CodeSandboxSnapshotDTO(response.snapshot, this);
|
|
152
152
|
}
|
|
153
153
|
/**
|
|
154
|
-
* List all
|
|
154
|
+
* List all code sandbox snapshots.
|
|
155
155
|
* @returns Array of snapshots
|
|
156
156
|
*/
|
|
157
157
|
async listSnapshots() {
|
|
158
158
|
const token = this.getToken();
|
|
159
159
|
const runtimesRunUrl = this.getRuntimesRunUrl();
|
|
160
160
|
const response = await snapshots.listSnapshots(token, runtimesRunUrl);
|
|
161
|
-
return response.snapshots.map(s => new
|
|
161
|
+
return response.snapshots.map(s => new CodeSandboxSnapshotDTO(s, this));
|
|
162
162
|
}
|
|
163
163
|
/**
|
|
164
164
|
* Get details for a specific snapshot by ID.
|
|
@@ -169,7 +169,7 @@ export function RuntimesMixin(Base) {
|
|
|
169
169
|
const token = this.getToken();
|
|
170
170
|
const runtimesRunUrl = this.getRuntimesRunUrl();
|
|
171
171
|
const response = await snapshots.getSnapshot(token, id, runtimesRunUrl);
|
|
172
|
-
return new
|
|
172
|
+
return new CodeSandboxSnapshotDTO(response.snapshot, this);
|
|
173
173
|
}
|
|
174
174
|
/**
|
|
175
175
|
* Delete a snapshot permanently.
|