@datalayer/core 1.0.23 → 1.0.25
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 +30 -7
- package/lib/api/constants.d.ts +3 -0
- package/lib/api/constants.js +3 -0
- package/lib/api/index.d.ts +1 -0
- package/lib/api/index.js +1 -0
- package/lib/api/runtimes/checkpoints.d.ts +4 -4
- package/lib/api/runtimes/runtimes.d.ts +3 -3
- package/lib/api/scheduler/index.d.ts +6 -0
- package/lib/api/scheduler/index.js +10 -0
- package/lib/api/scheduler/schedules.d.ts +85 -0
- package/lib/api/scheduler/schedules.js +78 -0
- package/lib/components/checkout/StripeCheckout.js +48 -2
- package/lib/components/display/LiveRelativeTime.d.ts +1 -10
- package/lib/components/display/LiveRelativeTime.js +3 -18
- package/lib/components/index.d.ts +3 -0
- package/lib/components/index.js +3 -0
- package/lib/components/runtimes/RuntimePickerBase.js +18 -16
- package/lib/components/runtimes/RuntimePickerCell.js +1 -1
- package/lib/components/scheduler/ScheduleMenu.d.ts +54 -0
- package/lib/components/scheduler/ScheduleMenu.js +154 -0
- package/lib/components/scheduler/index.d.ts +1 -0
- package/lib/{views/iam-tokens → components/scheduler}/index.js +1 -3
- package/lib/components/time/LiveRelativeTime.d.ts +14 -0
- package/lib/components/time/LiveRelativeTime.js +39 -0
- package/lib/components/time/index.d.ts +1 -0
- package/lib/components/time/index.js +5 -0
- package/lib/components/timeline/Timeline.d.ts +20 -0
- package/lib/components/timeline/Timeline.js +90 -0
- package/lib/components/timeline/index.d.ts +1 -0
- package/lib/components/timeline/index.js +5 -0
- package/lib/hooks/useCache.d.ts +31 -1
- package/lib/hooks/useCache.js +221 -17
- package/lib/hooks/useProjectStore.d.ts +1 -1
- package/lib/hooks/useProjects.d.ts +2 -2
- package/lib/models/IAMToken.d.ts +1 -1
- package/lib/models/Page.d.ts +3 -0
- package/lib/models/ProjectDTO.d.ts +1 -1
- package/lib/models/ProjectDTO.js +1 -1
- package/lib/state/substates/CoreState.js +2 -2
- package/lib/utils/Date.d.ts +7 -0
- package/lib/utils/Date.js +43 -10
- package/lib/utils/Name.d.ts +1 -0
- package/lib/utils/Name.js +8 -0
- package/lib/utils/Snapshot.js +2 -2
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +1 -0
- package/lib/views/api-keys/APIKeyEdit.d.ts +8 -0
- package/lib/views/{iam-tokens/IAMTokenEdit.js → api-keys/APIKeyEdit.js} +31 -31
- package/lib/views/api-keys/APIKeyNew.d.ts +8 -0
- package/lib/views/api-keys/APIKeyNew.js +143 -0
- package/lib/views/api-keys/APIKeys.d.ts +12 -0
- package/lib/views/api-keys/APIKeys.js +119 -0
- package/lib/views/api-keys/APIKeysStandalone.d.ts +2 -0
- package/lib/views/api-keys/APIKeysStandalone.js +117 -0
- package/lib/views/api-keys/index.d.ts +3 -0
- package/lib/views/api-keys/index.js +7 -0
- package/package.json +1 -1
- package/lib/views/iam-tokens/IAMTokenEdit.d.ts +0 -6
- package/lib/views/iam-tokens/IAMTokenNew.d.ts +0 -8
- package/lib/views/iam-tokens/IAMTokenNew.js +0 -118
- package/lib/views/iam-tokens/IAMTokens.d.ts +0 -12
- package/lib/views/iam-tokens/IAMTokens.js +0 -87
- package/lib/views/iam-tokens/Tokens.d.ts +0 -2
- package/lib/views/iam-tokens/Tokens.js +0 -85
- package/lib/views/iam-tokens/index.d.ts +0 -3
- /package/lib/utils/{logger.d.ts → Logger.d.ts} +0 -0
- /package/lib/utils/{logger.js → Logger.js} +0 -0
package/lib/hooks/useCache.js
CHANGED
|
@@ -305,6 +305,20 @@ export const queryKeys = {
|
|
|
305
305
|
growth: {
|
|
306
306
|
kpi: () => ['growth', 'kpi'],
|
|
307
307
|
},
|
|
308
|
+
// Ray (Runtimes)
|
|
309
|
+
ray: {
|
|
310
|
+
all: () => ['ray'],
|
|
311
|
+
clusters: () => [...queryKeys.ray.all(), 'clusters'],
|
|
312
|
+
cluster: (namespace, clusterName) => [...queryKeys.ray.all(), 'cluster', namespace, clusterName],
|
|
313
|
+
jobs: (namespace, clusterName) => [
|
|
314
|
+
...queryKeys.ray.all(),
|
|
315
|
+
'jobs',
|
|
316
|
+
namespace,
|
|
317
|
+
clusterName || 'all',
|
|
318
|
+
],
|
|
319
|
+
job: (namespace, jobName) => [...queryKeys.ray.all(), 'job', namespace, jobName],
|
|
320
|
+
logs: (namespace, jobName) => [...queryKeys.ray.job(namespace, jobName), 'logs'],
|
|
321
|
+
},
|
|
308
322
|
// OAuth2
|
|
309
323
|
oauth2: {
|
|
310
324
|
authorizationUrl: (queryArgs) => ['oauth2', 'authz', 'url', queryArgs],
|
|
@@ -2011,7 +2025,11 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
2011
2025
|
const principalUid = options?.principalUid;
|
|
2012
2026
|
const principalKind = options?.principalKind;
|
|
2013
2027
|
return useQuery({
|
|
2014
|
-
queryKey: [
|
|
2028
|
+
queryKey: [
|
|
2029
|
+
...queryKeys.datasources.all(),
|
|
2030
|
+
principalUid || 'self',
|
|
2031
|
+
principalKind || '',
|
|
2032
|
+
],
|
|
2015
2033
|
queryFn: async () => {
|
|
2016
2034
|
const resp = await requestDatalayer({
|
|
2017
2035
|
url: withAccountUidQuery(`${configuration.iamRunUrl}/api/iam/v1/datasources`, principalUid, principalKind),
|
|
@@ -2072,7 +2090,11 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
2072
2090
|
const principalUid = options?.principalUid;
|
|
2073
2091
|
const principalKind = options?.principalKind;
|
|
2074
2092
|
return useQuery({
|
|
2075
|
-
queryKey: [
|
|
2093
|
+
queryKey: [
|
|
2094
|
+
...queryKeys.secrets.all(),
|
|
2095
|
+
principalUid || 'self',
|
|
2096
|
+
principalKind || '',
|
|
2097
|
+
],
|
|
2076
2098
|
queryFn: async () => {
|
|
2077
2099
|
const resp = await requestDatalayer({
|
|
2078
2100
|
url: withAccountUidQuery(`${configuration.iamRunUrl}/api/iam/v1/secrets`, principalUid, principalKind),
|
|
@@ -2144,11 +2166,12 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
2144
2166
|
queryKey: queryKeys.tokens.all(),
|
|
2145
2167
|
queryFn: async () => {
|
|
2146
2168
|
const resp = await requestDatalayer({
|
|
2147
|
-
url: `${configuration.iamRunUrl}/api/iam/v1/
|
|
2169
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/api-keys`,
|
|
2148
2170
|
method: 'GET',
|
|
2149
2171
|
});
|
|
2150
|
-
|
|
2151
|
-
|
|
2172
|
+
const tokenItems = asArray(resp?.apiKeys ?? resp?.api_keys ?? resp?.tokens);
|
|
2173
|
+
if (resp.success && tokenItems.length > 0) {
|
|
2174
|
+
const tokens = tokenItems
|
|
2152
2175
|
.map((t) => {
|
|
2153
2176
|
const token = toToken(t);
|
|
2154
2177
|
if (token) {
|
|
@@ -2172,7 +2195,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
2172
2195
|
return useMutation({
|
|
2173
2196
|
mutationFn: async (token) => {
|
|
2174
2197
|
const resp = await requestDatalayer({
|
|
2175
|
-
url: `${configuration.iamRunUrl}/api/iam/v1/
|
|
2198
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/api-keys`,
|
|
2176
2199
|
method: 'POST',
|
|
2177
2200
|
body: {
|
|
2178
2201
|
...token,
|
|
@@ -2180,8 +2203,9 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
2180
2203
|
},
|
|
2181
2204
|
});
|
|
2182
2205
|
// Transform the token in the response
|
|
2183
|
-
|
|
2184
|
-
|
|
2206
|
+
const tokenPayload = resp?.apiKey ?? resp?.api_key ?? resp?.token;
|
|
2207
|
+
if (resp.success && tokenPayload) {
|
|
2208
|
+
resp.token = toToken(tokenPayload);
|
|
2185
2209
|
}
|
|
2186
2210
|
return resp;
|
|
2187
2211
|
},
|
|
@@ -2385,7 +2409,11 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
2385
2409
|
const principalUid = options?.principalUid;
|
|
2386
2410
|
const principalKind = options?.principalKind;
|
|
2387
2411
|
return useQuery({
|
|
2388
|
-
queryKey: [
|
|
2412
|
+
queryKey: [
|
|
2413
|
+
...queryKeys.datasources.detail(datasourceId),
|
|
2414
|
+
principalUid || 'self',
|
|
2415
|
+
principalKind || '',
|
|
2416
|
+
],
|
|
2389
2417
|
queryFn: async () => {
|
|
2390
2418
|
const resp = await requestDatalayer({
|
|
2391
2419
|
url: withAccountUidQuery(`${configuration.iamRunUrl}/api/iam/v1/datasources/${datasourceId}`, principalUid, principalKind),
|
|
@@ -2434,7 +2462,11 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
2434
2462
|
const principalUid = options?.principalUid;
|
|
2435
2463
|
const principalKind = options?.principalKind;
|
|
2436
2464
|
return useQuery({
|
|
2437
|
-
queryKey: [
|
|
2465
|
+
queryKey: [
|
|
2466
|
+
...queryKeys.secrets.detail(secretId),
|
|
2467
|
+
principalUid || 'self',
|
|
2468
|
+
principalKind || '',
|
|
2469
|
+
],
|
|
2438
2470
|
queryFn: async () => {
|
|
2439
2471
|
const resp = await requestDatalayer({
|
|
2440
2472
|
url: withAccountUidQuery(`${configuration.iamRunUrl}/api/iam/v1/secrets/${secretId}`, principalUid, principalKind),
|
|
@@ -2485,11 +2517,12 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
2485
2517
|
queryKey: queryKeys.tokens.detail(tokenId),
|
|
2486
2518
|
queryFn: async () => {
|
|
2487
2519
|
const resp = await requestDatalayer({
|
|
2488
|
-
url: `${configuration.iamRunUrl}/api/iam/v1/
|
|
2520
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/api-keys/${tokenId}`,
|
|
2489
2521
|
method: 'GET',
|
|
2490
2522
|
});
|
|
2491
|
-
|
|
2492
|
-
|
|
2523
|
+
const tokenPayload = resp?.apiKey ?? resp?.api_key ?? resp?.token;
|
|
2524
|
+
if (resp.success && tokenPayload) {
|
|
2525
|
+
return toToken(tokenPayload);
|
|
2493
2526
|
}
|
|
2494
2527
|
return null;
|
|
2495
2528
|
},
|
|
@@ -2504,14 +2537,15 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
2504
2537
|
return useMutation({
|
|
2505
2538
|
mutationFn: async (token) => {
|
|
2506
2539
|
return requestDatalayer({
|
|
2507
|
-
url: `${configuration.iamRunUrl}/api/iam/v1/
|
|
2540
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/api-keys/${token.id}`,
|
|
2508
2541
|
method: 'PUT',
|
|
2509
2542
|
body: { ...token },
|
|
2510
2543
|
});
|
|
2511
2544
|
},
|
|
2512
2545
|
onSuccess: resp => {
|
|
2513
|
-
|
|
2514
|
-
|
|
2546
|
+
const tokenPayload = resp?.apiKey ?? resp?.api_key ?? resp?.token;
|
|
2547
|
+
if (resp.success && tokenPayload) {
|
|
2548
|
+
const tok = toToken(tokenPayload);
|
|
2515
2549
|
if (tok) {
|
|
2516
2550
|
queryClient.setQueryData(queryKeys.tokens.detail(tok.id), tok);
|
|
2517
2551
|
}
|
|
@@ -2527,7 +2561,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
2527
2561
|
return useMutation({
|
|
2528
2562
|
mutationFn: async (tokenId) => {
|
|
2529
2563
|
return requestDatalayer({
|
|
2530
|
-
url: `${configuration.iamRunUrl}/api/iam/v1/
|
|
2564
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/api-keys/${tokenId}`,
|
|
2531
2565
|
method: 'DELETE',
|
|
2532
2566
|
});
|
|
2533
2567
|
},
|
|
@@ -6805,6 +6839,167 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
6805
6839
|
});
|
|
6806
6840
|
};
|
|
6807
6841
|
// ============================================================================
|
|
6842
|
+
// Ray (Runtimes) Hooks
|
|
6843
|
+
// ============================================================================
|
|
6844
|
+
const useRayClusters = () => {
|
|
6845
|
+
return useQuery({
|
|
6846
|
+
queryKey: queryKeys.ray.clusters(),
|
|
6847
|
+
queryFn: async () => {
|
|
6848
|
+
const resp = await requestDatalayer({
|
|
6849
|
+
url: `${configuration.runtimesRunUrl}/api/runtimes/v1/ray/clusters`,
|
|
6850
|
+
method: 'GET',
|
|
6851
|
+
});
|
|
6852
|
+
if (!resp.success) {
|
|
6853
|
+
throw new Error(resp.message || 'Failed to fetch Ray clusters');
|
|
6854
|
+
}
|
|
6855
|
+
return {
|
|
6856
|
+
clusters: asArray(resp.clusters),
|
|
6857
|
+
namespaces: asArray(resp.namespaces)
|
|
6858
|
+
.map(value => String(value))
|
|
6859
|
+
.filter(Boolean),
|
|
6860
|
+
};
|
|
6861
|
+
},
|
|
6862
|
+
...DEFAULT_QUERY_OPTIONS,
|
|
6863
|
+
refetchOnMount: true,
|
|
6864
|
+
enabled: Boolean(configuration.runtimesRunUrl),
|
|
6865
|
+
});
|
|
6866
|
+
};
|
|
6867
|
+
const useRayCluster = (namespace = 'default', clusterName = '') => {
|
|
6868
|
+
return useQuery({
|
|
6869
|
+
queryKey: queryKeys.ray.cluster(namespace, clusterName),
|
|
6870
|
+
queryFn: async () => {
|
|
6871
|
+
const resp = await requestDatalayer({
|
|
6872
|
+
url: `${configuration.runtimesRunUrl}/api/runtimes/v1/ray/clusters/${encodeURIComponent(clusterName)}?namespace=${encodeURIComponent(namespace)}`,
|
|
6873
|
+
method: 'GET',
|
|
6874
|
+
});
|
|
6875
|
+
if (!resp.success) {
|
|
6876
|
+
throw new Error(resp.message || 'Failed to fetch Ray cluster');
|
|
6877
|
+
}
|
|
6878
|
+
return resp.cluster || null;
|
|
6879
|
+
},
|
|
6880
|
+
...DEFAULT_QUERY_OPTIONS,
|
|
6881
|
+
enabled: Boolean(configuration.runtimesRunUrl) &&
|
|
6882
|
+
Boolean(namespace) &&
|
|
6883
|
+
Boolean(clusterName),
|
|
6884
|
+
});
|
|
6885
|
+
};
|
|
6886
|
+
const useCreateRayCluster = () => {
|
|
6887
|
+
return useMutation({
|
|
6888
|
+
mutationFn: async (payload) => {
|
|
6889
|
+
const resp = await requestDatalayer({
|
|
6890
|
+
url: `${configuration.runtimesRunUrl}/api/runtimes/v1/ray/clusters`,
|
|
6891
|
+
method: 'POST',
|
|
6892
|
+
body: payload,
|
|
6893
|
+
});
|
|
6894
|
+
if (resp?.success === false) {
|
|
6895
|
+
throw new Error(resp?.message || resp?.reason || 'Failed to create Ray cluster');
|
|
6896
|
+
}
|
|
6897
|
+
return resp;
|
|
6898
|
+
},
|
|
6899
|
+
onSuccess: () => {
|
|
6900
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.ray.all() });
|
|
6901
|
+
},
|
|
6902
|
+
});
|
|
6903
|
+
};
|
|
6904
|
+
const useDeleteRayCluster = (namespace = 'default') => {
|
|
6905
|
+
return useMutation({
|
|
6906
|
+
mutationFn: async (clusterName) => {
|
|
6907
|
+
return requestDatalayer({
|
|
6908
|
+
url: `${configuration.runtimesRunUrl}/api/runtimes/v1/ray/clusters/${encodeURIComponent(clusterName)}?namespace=${encodeURIComponent(namespace)}`,
|
|
6909
|
+
method: 'DELETE',
|
|
6910
|
+
});
|
|
6911
|
+
},
|
|
6912
|
+
onSuccess: () => {
|
|
6913
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.ray.all() });
|
|
6914
|
+
},
|
|
6915
|
+
});
|
|
6916
|
+
};
|
|
6917
|
+
const useRayJobs = (namespace = 'default', clusterName) => {
|
|
6918
|
+
return useQuery({
|
|
6919
|
+
queryKey: queryKeys.ray.jobs(namespace, clusterName),
|
|
6920
|
+
queryFn: async () => {
|
|
6921
|
+
const params = new URLSearchParams();
|
|
6922
|
+
params.set('namespace', namespace);
|
|
6923
|
+
if (clusterName) {
|
|
6924
|
+
params.set('cluster_name', clusterName);
|
|
6925
|
+
}
|
|
6926
|
+
const resp = await requestDatalayer({
|
|
6927
|
+
url: `${configuration.runtimesRunUrl}/api/runtimes/v1/ray/jobs?${params.toString()}`,
|
|
6928
|
+
method: 'GET',
|
|
6929
|
+
});
|
|
6930
|
+
if (!resp.success) {
|
|
6931
|
+
throw new Error(resp.message || 'Failed to fetch Ray jobs');
|
|
6932
|
+
}
|
|
6933
|
+
return asArray(resp.jobs);
|
|
6934
|
+
},
|
|
6935
|
+
...DEFAULT_QUERY_OPTIONS,
|
|
6936
|
+
enabled: Boolean(configuration.runtimesRunUrl),
|
|
6937
|
+
});
|
|
6938
|
+
};
|
|
6939
|
+
const useSubmitRayJob = (clusterName) => {
|
|
6940
|
+
return useMutation({
|
|
6941
|
+
mutationFn: async (payload) => {
|
|
6942
|
+
return requestDatalayer({
|
|
6943
|
+
url: `${configuration.runtimesRunUrl}/api/runtimes/v1/ray/clusters/${encodeURIComponent(clusterName)}/jobs`,
|
|
6944
|
+
method: 'POST',
|
|
6945
|
+
body: payload,
|
|
6946
|
+
});
|
|
6947
|
+
},
|
|
6948
|
+
onSuccess: () => {
|
|
6949
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.ray.all() });
|
|
6950
|
+
},
|
|
6951
|
+
});
|
|
6952
|
+
};
|
|
6953
|
+
const useDeleteRayJob = (namespace = 'default') => {
|
|
6954
|
+
return useMutation({
|
|
6955
|
+
mutationFn: async (jobName) => {
|
|
6956
|
+
return requestDatalayer({
|
|
6957
|
+
url: `${configuration.runtimesRunUrl}/api/runtimes/v1/ray/jobs/${encodeURIComponent(jobName)}?namespace=${encodeURIComponent(namespace)}`,
|
|
6958
|
+
method: 'DELETE',
|
|
6959
|
+
});
|
|
6960
|
+
},
|
|
6961
|
+
onSuccess: () => {
|
|
6962
|
+
queryClient.invalidateQueries({ queryKey: queryKeys.ray.all() });
|
|
6963
|
+
},
|
|
6964
|
+
});
|
|
6965
|
+
};
|
|
6966
|
+
const useRayJobLogs = (jobName, namespace = 'default', tailLines = 200, enabled = true) => {
|
|
6967
|
+
return useQuery({
|
|
6968
|
+
queryKey: queryKeys.ray.logs(namespace, jobName),
|
|
6969
|
+
queryFn: async () => {
|
|
6970
|
+
const params = new URLSearchParams();
|
|
6971
|
+
params.set('namespace', namespace);
|
|
6972
|
+
params.set('tail_lines', String(tailLines));
|
|
6973
|
+
const resp = await requestDatalayer({
|
|
6974
|
+
url: `${configuration.runtimesRunUrl}/api/runtimes/v1/ray/jobs/${encodeURIComponent(jobName)}/logs?${params.toString()}`,
|
|
6975
|
+
method: 'GET',
|
|
6976
|
+
// Logs naturally 404 once a job is deleted; never surface a toast.
|
|
6977
|
+
notifyOnError: false,
|
|
6978
|
+
});
|
|
6979
|
+
if (!resp.success) {
|
|
6980
|
+
throw new Error(resp.message || 'Failed to fetch Ray job logs');
|
|
6981
|
+
}
|
|
6982
|
+
return {
|
|
6983
|
+
logs: String(resp.logs || ''),
|
|
6984
|
+
status: String(resp.status || ''),
|
|
6985
|
+
};
|
|
6986
|
+
},
|
|
6987
|
+
...DEFAULT_QUERY_OPTIONS,
|
|
6988
|
+
enabled: Boolean(configuration.runtimesRunUrl) && Boolean(jobName) && enabled,
|
|
6989
|
+
refetchOnMount: 'always',
|
|
6990
|
+
refetchInterval: query => {
|
|
6991
|
+
const status = String(query.state.data?.status || '').toLowerCase();
|
|
6992
|
+
const terminal = [
|
|
6993
|
+
'succeeded',
|
|
6994
|
+
'failed',
|
|
6995
|
+
'stopped',
|
|
6996
|
+
'completed',
|
|
6997
|
+
].includes(status);
|
|
6998
|
+
return terminal ? false : 3000;
|
|
6999
|
+
},
|
|
7000
|
+
});
|
|
7001
|
+
};
|
|
7002
|
+
// ============================================================================
|
|
6808
7003
|
// Return all methods grouped by category
|
|
6809
7004
|
// ============================================================================
|
|
6810
7005
|
return {
|
|
@@ -7093,6 +7288,15 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
7093
7288
|
useUserSurveys,
|
|
7094
7289
|
useGrowthKPI,
|
|
7095
7290
|
useGrowthContactsKPI,
|
|
7291
|
+
// Ray (Runtimes)
|
|
7292
|
+
useRayClusters,
|
|
7293
|
+
useRayCluster,
|
|
7294
|
+
useCreateRayCluster,
|
|
7295
|
+
useDeleteRayCluster,
|
|
7296
|
+
useRayJobs,
|
|
7297
|
+
useSubmitRayJob,
|
|
7298
|
+
useDeleteRayJob,
|
|
7299
|
+
useRayJobLogs,
|
|
7096
7300
|
// Query keys for manual operations
|
|
7097
7301
|
queryKeys,
|
|
7098
7302
|
// Upload
|
|
@@ -16,7 +16,7 @@ export type ProjectRuntimeEntry = {
|
|
|
16
16
|
agentName?: string;
|
|
17
17
|
/** Agent runtime status (running, starting, terminated, etc.). */
|
|
18
18
|
agentStatus?: string;
|
|
19
|
-
/** The
|
|
19
|
+
/** The agentspec ID used to create the runtime. */
|
|
20
20
|
agentSpecId?: string;
|
|
21
21
|
};
|
|
22
22
|
export type ProjectStoreState = {
|
|
@@ -20,7 +20,7 @@ export type ProjectData = {
|
|
|
20
20
|
isPublic: boolean;
|
|
21
21
|
/** Attached agent (runtime) pod name, if any */
|
|
22
22
|
attachedAgentPodName?: string;
|
|
23
|
-
/** Attached
|
|
23
|
+
/** Attached agentspec ID (e.g. 'data-acquisition'), if any */
|
|
24
24
|
attachedAgentSpecId?: string;
|
|
25
25
|
};
|
|
26
26
|
/**
|
|
@@ -31,7 +31,7 @@ export type CreateProjectRequest = {
|
|
|
31
31
|
name: string;
|
|
32
32
|
/** Project description */
|
|
33
33
|
description?: string;
|
|
34
|
-
/**
|
|
34
|
+
/** Agentspec to attach (creates agent on project creation) */
|
|
35
35
|
agentSpecId?: string;
|
|
36
36
|
};
|
|
37
37
|
/**
|
package/lib/models/IAMToken.d.ts
CHANGED
package/lib/models/Page.d.ts
CHANGED
|
@@ -29,6 +29,9 @@ export type IPage = {
|
|
|
29
29
|
screenCapture?: string;
|
|
30
30
|
creator?: IUser;
|
|
31
31
|
creatorId?: string;
|
|
32
|
+
selectedPrincipalUid?: string;
|
|
33
|
+
selectedPrincipalKind?: 'user' | 'organization' | 'team';
|
|
34
|
+
selectedOrganizationUid?: string;
|
|
32
35
|
kernelSnapshot?: ICodeSandboxSnapshot;
|
|
33
36
|
kernelSnapshotId?: string;
|
|
34
37
|
createdAt?: string;
|
|
@@ -66,7 +66,7 @@ export declare class ProjectDTO {
|
|
|
66
66
|
get createdAt(): Date;
|
|
67
67
|
/** Attached agent runtime pod name, if any. */
|
|
68
68
|
get attachedAgentPodName(): string | undefined;
|
|
69
|
-
/** Attached
|
|
69
|
+
/** Attached agentspec ID (e.g., 'data-acquisition'), if any. */
|
|
70
70
|
get attachedAgentSpecId(): string | undefined;
|
|
71
71
|
/** Human-readable name of the attached agent runtime, if any. */
|
|
72
72
|
get attachedAgentGivenName(): string | undefined;
|
package/lib/models/ProjectDTO.js
CHANGED
|
@@ -69,7 +69,7 @@ export class ProjectDTO {
|
|
|
69
69
|
this._checkDeleted();
|
|
70
70
|
return this._data.attached_agent_pod_name_s || undefined;
|
|
71
71
|
}
|
|
72
|
-
/** Attached
|
|
72
|
+
/** Attached agentspec ID (e.g., 'data-acquisition'), if any. */
|
|
73
73
|
get attachedAgentSpecId() {
|
|
74
74
|
this._checkDeleted();
|
|
75
75
|
return this._data.attached_agent_spec_id_s || undefined;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { createStore } from 'zustand/vanilla';
|
|
6
6
|
import { useStore } from 'zustand';
|
|
7
|
-
import { configLogger } from '../../utils/
|
|
7
|
+
import { configLogger } from '../../utils/Logger.js';
|
|
8
8
|
let loadConfigurationFromServer = true;
|
|
9
9
|
let initialConfiguration = {
|
|
10
10
|
runUrl: 'https://prod1.datalayer.run',
|
|
@@ -40,7 +40,7 @@ let initialConfiguration = {
|
|
|
40
40
|
logoUrl: 'https://assets.datalayer.tech/datalayer-25.svg',
|
|
41
41
|
logoSquareUrl: 'https://assets.datalayer.tech/datalayer-square.png',
|
|
42
42
|
copyright: '© 2025 Datalayer, Inc',
|
|
43
|
-
docsUrl: 'https://
|
|
43
|
+
docsUrl: 'https://datalayer.ai/docs',
|
|
44
44
|
supportUrl: 'https://datalayer.ai/support',
|
|
45
45
|
termsUrl: 'https://datalayer.ai/terms',
|
|
46
46
|
pricingUrl: 'https://datalayer.ai/pricing',
|
package/lib/utils/Date.d.ts
CHANGED
|
@@ -6,6 +6,13 @@ export declare const timeSince: (date: Date) => string;
|
|
|
6
6
|
* Examples: "just now", "15m ago", "3h ago", "2d ago", "4w ago", "1y ago".
|
|
7
7
|
*/
|
|
8
8
|
export declare const formatRelativeTime: (value?: Date | string | number, now?: Date) => string | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Build a detailed datetime string suitable for tooltips.
|
|
11
|
+
*
|
|
12
|
+
* Example:
|
|
13
|
+
* "2026-06-08T16:15:32.531Z • Jun 8, 2026, 6:15:32 PM CEST (Europe/Paris)"
|
|
14
|
+
*/
|
|
15
|
+
export declare const formatDateTimeDetails: (value?: Date | string | number) => string | undefined;
|
|
9
16
|
/**
|
|
10
17
|
* Format a duration in milliseconds into a human-readable string.
|
|
11
18
|
*
|
package/lib/utils/Date.js
CHANGED
|
@@ -76,24 +76,57 @@ export const formatRelativeTime = (value, now = new Date()) => {
|
|
|
76
76
|
if (Number.isNaN(ts)) {
|
|
77
77
|
return typeof value === 'string' ? value : undefined;
|
|
78
78
|
}
|
|
79
|
-
const diffMs =
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
const diffMs = ts - now.getTime();
|
|
80
|
+
const inFuture = diffMs > 0;
|
|
81
|
+
const absSeconds = Math.floor(Math.abs(diffMs) / 1000);
|
|
82
|
+
if (absSeconds < 30)
|
|
83
|
+
return inFuture ? 'in a few seconds' : 'just now';
|
|
84
|
+
const withDirection = (value, unit) => {
|
|
85
|
+
return inFuture ? `in ${value}${unit}` : `${value}${unit} ago`;
|
|
86
|
+
};
|
|
87
|
+
if (absSeconds < 60)
|
|
88
|
+
return withDirection(absSeconds, 's');
|
|
89
|
+
const minutes = Math.floor(absSeconds / 60);
|
|
84
90
|
if (minutes < 60)
|
|
85
|
-
return
|
|
91
|
+
return withDirection(minutes, 'm');
|
|
86
92
|
const hours = Math.floor(minutes / 60);
|
|
87
93
|
if (hours < 24)
|
|
88
|
-
return
|
|
94
|
+
return withDirection(hours, 'h');
|
|
89
95
|
const days = Math.floor(hours / 24);
|
|
90
96
|
if (days < 7)
|
|
91
|
-
return
|
|
97
|
+
return withDirection(days, 'd');
|
|
92
98
|
const weeks = Math.floor(days / 7);
|
|
93
99
|
if (weeks < 52)
|
|
94
|
-
return
|
|
100
|
+
return withDirection(weeks, 'w');
|
|
95
101
|
const years = Math.floor(days / 365);
|
|
96
|
-
return
|
|
102
|
+
return withDirection(years, 'y');
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Build a detailed datetime string suitable for tooltips.
|
|
106
|
+
*
|
|
107
|
+
* Example:
|
|
108
|
+
* "2026-06-08T16:15:32.531Z • Jun 8, 2026, 6:15:32 PM CEST (Europe/Paris)"
|
|
109
|
+
*/
|
|
110
|
+
export const formatDateTimeDetails = (value) => {
|
|
111
|
+
if (value === undefined || value === null) {
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
const date = value instanceof Date
|
|
115
|
+
? value
|
|
116
|
+
: typeof value === 'number'
|
|
117
|
+
? new Date(value)
|
|
118
|
+
: new Date(value);
|
|
119
|
+
const ts = date.getTime();
|
|
120
|
+
if (Number.isNaN(ts)) {
|
|
121
|
+
return typeof value === 'string' ? value : undefined;
|
|
122
|
+
}
|
|
123
|
+
const iso = date.toISOString();
|
|
124
|
+
const zone = Intl.DateTimeFormat().resolvedOptions().timeZone || 'local';
|
|
125
|
+
const local = new Intl.DateTimeFormat(undefined, {
|
|
126
|
+
dateStyle: 'medium',
|
|
127
|
+
timeStyle: 'long',
|
|
128
|
+
}).format(date);
|
|
129
|
+
return `${iso} • ${local} (${zone})`;
|
|
97
130
|
};
|
|
98
131
|
/**
|
|
99
132
|
* Format a duration in milliseconds into a human-readable string.
|
package/lib/utils/Name.d.ts
CHANGED
|
@@ -5,3 +5,4 @@ export declare const namesAsInitials: (firstName: string, lastName: string) => s
|
|
|
5
5
|
* Convert first and last names to a friendly name.
|
|
6
6
|
*/
|
|
7
7
|
export declare const toFriendlyName: (firstName?: string, lastName?: string) => string;
|
|
8
|
+
export declare const createRandomTimestampName: () => string;
|
package/lib/utils/Name.js
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
|
+
import { adjectives, animals, uniqueNamesGenerator, } from 'unique-names-generator';
|
|
6
|
+
const RANDOM_TIMESTAMP_NAME_CONFIGURATION = {
|
|
7
|
+
dictionaries: [adjectives, animals],
|
|
8
|
+
separator: '-',
|
|
9
|
+
};
|
|
5
10
|
export const asDisplayName = (givenName, familyName) => {
|
|
6
11
|
return givenName
|
|
7
12
|
? familyName
|
|
@@ -34,3 +39,6 @@ export const toFriendlyName = (firstName, lastName) => {
|
|
|
34
39
|
}
|
|
35
40
|
return '';
|
|
36
41
|
};
|
|
42
|
+
export const createRandomTimestampName = () => {
|
|
43
|
+
return `${uniqueNamesGenerator(RANDOM_TIMESTAMP_NAME_CONFIGURATION)}-${Date.now()}`;
|
|
44
|
+
};
|
package/lib/utils/Snapshot.js
CHANGED
|
@@ -6,7 +6,7 @@ import { adjectives, animals, uniqueNamesGenerator, } from 'unique-names-generat
|
|
|
6
6
|
/**
|
|
7
7
|
* Kernel snapshot description configuration.
|
|
8
8
|
*/
|
|
9
|
-
const
|
|
9
|
+
const CODE_SANDBOX_SNAPSHOT_DESCRIPTION_CONFIGURATION = {
|
|
10
10
|
dictionaries: [adjectives, animals],
|
|
11
11
|
separator: '-',
|
|
12
12
|
};
|
|
@@ -17,5 +17,5 @@ const KERNEL_SNAPSHOT_DESCRIPTION_CONFIGURATION = {
|
|
|
17
17
|
* @returns The kernel snapshot name
|
|
18
18
|
*/
|
|
19
19
|
export function createSandboxSnapshotName(suffix) {
|
|
20
|
-
return `${uniqueNamesGenerator(
|
|
20
|
+
return `${uniqueNamesGenerator(CODE_SANDBOX_SNAPSHOT_DESCRIPTION_CONFIGURATION)}-${suffix}`;
|
|
21
21
|
}
|
package/lib/utils/index.d.ts
CHANGED
package/lib/utils/index.js
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type APIKeyEditProps = {
|
|
2
|
+
/** Route to navigate after delete. Defaults to '/settings/iam/api-keys'. */
|
|
3
|
+
apiKeysListRoute?: string;
|
|
4
|
+
/** Whether to render the local edit title header. Defaults to true. */
|
|
5
|
+
showTitle?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare const APIKeyEdit: ({ apiKeysListRoute, showTitle, }?: APIKeyEditProps) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export default APIKeyEdit;
|