@datalayer/core 1.2.10 → 1.2.12

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.
Files changed (41) hide show
  1. package/README.md +2 -2
  2. package/lib/api/iam/authentication.js +6 -4
  3. package/lib/api/iam/healthz.js +2 -2
  4. package/lib/api/iam/oauth2.js +18 -12
  5. package/lib/api/iam/secrets.js +1 -2
  6. package/lib/api/mcp/observability.d.ts +9 -2
  7. package/lib/api/mcp/observability.js +40 -15
  8. package/lib/client/auth/strategies.js +1 -1
  9. package/lib/client/mixins/IAMMixin.js +2 -2
  10. package/lib/components/checkout/StripeCheckout.d.ts +1 -1
  11. package/lib/components/checkout/StripeCheckout.js +1 -1
  12. package/lib/components/display/VisuallyHidden.d.ts +1 -2
  13. package/lib/components/sharing/sandboxSharing.js +7 -1
  14. package/lib/config/Configuration.d.ts +4 -4
  15. package/lib/config/Configuration.js +7 -7
  16. package/lib/config/index.d.ts +1 -0
  17. package/lib/config/index.js +1 -0
  18. package/lib/config/planes.d.ts +45 -0
  19. package/lib/config/planes.js +53 -0
  20. package/lib/hooks/useBackdrop.d.ts +4 -5
  21. package/lib/hooks/useCache.d.ts +29 -19
  22. package/lib/hooks/useCache.js +164 -189
  23. package/lib/hooks/useMcp.js +1 -1
  24. package/lib/hooks/useNavigate.js +10 -0
  25. package/lib/hooks/useWindowSize.js +1 -1
  26. package/lib/models/IAMProvidersSpecs.d.ts +10 -5
  27. package/lib/models/IAMProvidersSpecs.js +0 -23
  28. package/lib/navigation/adapters/react-router.d.ts +1 -1
  29. package/lib/navigation/adapters/react-router.js +3 -0
  30. package/lib/state/sessionEnd.js +1 -1
  31. package/lib/state/substates/CoreState.js +3 -16
  32. package/lib/state/substates/IAMState.d.ts +3 -3
  33. package/lib/state/substates/NavigationState.d.ts +82 -0
  34. package/lib/state/substates/NavigationState.js +255 -0
  35. package/lib/state/substates/index.d.ts +1 -0
  36. package/lib/state/substates/index.js +1 -0
  37. package/lib/utils/Screencapture.d.ts +15 -0
  38. package/lib/utils/Screencapture.js +26 -23
  39. package/lib/views/mcp/McpHome.js +1 -1
  40. package/package.json +6 -4
  41. package/scripts/generate-mcp-types.py +15 -9
@@ -727,6 +727,10 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
727
727
  */
728
728
  if (raw.publicUrl)
729
729
  meta.publicUrl = raw.publicUrl;
730
+ if (raw.shareCardUrl)
731
+ meta.shareCardUrl = raw.shareCardUrl;
732
+ if (raw.shareCardVersion)
733
+ meta.shareCardVersion = raw.shareCardVersion;
730
734
  return meta;
731
735
  };
732
736
  /**
@@ -6853,6 +6857,104 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
6853
6857
  onSuccess: invalidateArtifactVisibility,
6854
6858
  });
6855
6859
  };
6860
+ /** Publish a public artifact natively to LinkedIn through Library's saga. */
6861
+ const usePublishLinkedInShare = () => {
6862
+ return useMutation({
6863
+ mutationFn: async ({ itemId, commentary, idempotencyKey, imageDataUrl, imageAltText, }) => {
6864
+ const resp = await requestDatalayer({
6865
+ url: `${configuration.libraryUrl}/api/library/v1/items/${encodeURIComponent(itemId)}/shares/linkedin`,
6866
+ method: 'POST',
6867
+ headers: { 'Idempotency-Key': idempotencyKey },
6868
+ body: { commentary, imageDataUrl, imageAltText },
6869
+ });
6870
+ if (!resp.success) {
6871
+ throw new Error(resp.message || 'Failed to publish to LinkedIn');
6872
+ }
6873
+ return resp.share;
6874
+ },
6875
+ });
6876
+ };
6877
+ const useUnpublishLinkedInShare = () => {
6878
+ return useMutation({
6879
+ mutationFn: async (idempotencyKey) => {
6880
+ const resp = await requestDatalayer({
6881
+ url: `${configuration.libraryUrl}/api/library/v1/shares/linkedin/${encodeURIComponent(idempotencyKey)}`,
6882
+ method: 'DELETE',
6883
+ });
6884
+ if (!resp.success) {
6885
+ throw new Error(resp.message || 'Failed to unpublish from LinkedIn');
6886
+ }
6887
+ return resp.share;
6888
+ },
6889
+ });
6890
+ };
6891
+ const useLinkedInShares = (itemId, enabled = true) => {
6892
+ return useQuery({
6893
+ queryKey: ['library', 'social-shares', 'linkedin', itemId],
6894
+ queryFn: async () => {
6895
+ const resp = await requestDatalayer({
6896
+ url: `${configuration.libraryUrl}/api/library/v1/items/${encodeURIComponent(itemId)}/shares/linkedin`,
6897
+ method: 'GET',
6898
+ notifyOnError: false,
6899
+ });
6900
+ if (!resp.success) {
6901
+ throw new Error(resp.message || 'Failed to load LinkedIn publications');
6902
+ }
6903
+ return Array.isArray(resp.shares) ? resp.shares : [];
6904
+ },
6905
+ ...DEFAULT_QUERY_OPTIONS,
6906
+ enabled: Boolean(configuration.libraryUrl) && Boolean(itemId) && enabled,
6907
+ });
6908
+ };
6909
+ /** Publish one selected public result through the durable Bluesky saga. */
6910
+ const usePublishBlueskyShare = () => {
6911
+ return useMutation({
6912
+ mutationFn: async ({ itemId, finding, cellId, outputIndex, idempotencyKey, imageDataUrl, imageAltText, }) => {
6913
+ const resp = await requestDatalayer({
6914
+ url: `${configuration.libraryUrl}/api/library/v1/items/${encodeURIComponent(itemId)}/shares/bluesky`,
6915
+ method: 'POST',
6916
+ headers: { 'Idempotency-Key': idempotencyKey },
6917
+ body: { finding, cellId, outputIndex, imageDataUrl, imageAltText },
6918
+ });
6919
+ if (!resp.success) {
6920
+ throw new Error(resp.message || 'Failed to publish to Bluesky');
6921
+ }
6922
+ return resp.share;
6923
+ },
6924
+ });
6925
+ };
6926
+ const useUnpublishBlueskyShare = () => {
6927
+ return useMutation({
6928
+ mutationFn: async (idempotencyKey) => {
6929
+ const resp = await requestDatalayer({
6930
+ url: `${configuration.libraryUrl}/api/library/v1/shares/bluesky/${encodeURIComponent(idempotencyKey)}`,
6931
+ method: 'DELETE',
6932
+ });
6933
+ if (!resp.success) {
6934
+ throw new Error(resp.message || 'Failed to unpublish from Bluesky');
6935
+ }
6936
+ return resp.share;
6937
+ },
6938
+ });
6939
+ };
6940
+ const useBlueskyShares = (itemId, enabled = true) => {
6941
+ return useQuery({
6942
+ queryKey: ['library', 'social-shares', 'bluesky', itemId],
6943
+ queryFn: async () => {
6944
+ const resp = await requestDatalayer({
6945
+ url: `${configuration.libraryUrl}/api/library/v1/items/${encodeURIComponent(itemId)}/shares/bluesky`,
6946
+ method: 'GET',
6947
+ notifyOnError: false,
6948
+ });
6949
+ if (!resp.success) {
6950
+ throw new Error(resp.message || 'Failed to load Bluesky publications');
6951
+ }
6952
+ return Array.isArray(resp.shares) ? resp.shares : [];
6953
+ },
6954
+ ...DEFAULT_QUERY_OPTIONS,
6955
+ enabled: Boolean(configuration.libraryUrl) && Boolean(itemId) && enabled,
6956
+ });
6957
+ };
6856
6958
  /**
6857
6959
  * Tell the library that an artifact was reused: cloned into a space, or
6858
6960
  * instantiated as a runtime. The reuse itself belongs to the service that
@@ -6860,11 +6962,14 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
6860
6962
  */
6861
6963
  const useCountItemReuse = () => {
6862
6964
  return useMutation({
6863
- mutationFn: async ({ itemId, kind, }) => {
6965
+ mutationFn: async ({ itemId, kind, signupSource, shareRef, }) => {
6864
6966
  const resp = await requestDatalayer({
6865
6967
  url: `${configuration.libraryUrl}/api/library/v1/items/${encodeURIComponent(itemId)}/reused`,
6866
6968
  method: 'POST',
6867
- body: { kind },
6969
+ body: {
6970
+ kind,
6971
+ ...(signupSource && shareRef ? { signupSource, shareRef } : {}),
6972
+ },
6868
6973
  });
6869
6974
  if (!resp.success) {
6870
6975
  throw new Error(resp.message || 'Failed to count the reuse');
@@ -7062,215 +7167,80 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
7062
7167
  },
7063
7168
  });
7064
7169
  };
7065
- /**
7066
- * Get LinkedIn profile via proxy
7067
- */
7170
+ /** Get the server-connected LinkedIn profile. */
7068
7171
  const useGetLinkedinProfile = () => {
7069
7172
  return useMutation({
7070
- mutationFn: async (accessToken) => {
7173
+ mutationFn: async () => {
7071
7174
  return requestDatalayer({
7072
- url: `${configuration.iamUrl}/api/iam/v1/proxy/request`,
7073
- method: 'POST',
7074
- body: {
7075
- request_method: 'GET',
7076
- request_url: 'https://api.linkedin.com/v2/userinfo',
7077
- request_token: accessToken,
7078
- },
7175
+ url: `${configuration.iamUrl}/api/iam/v1/social/linkedin/profile`,
7176
+ method: 'GET',
7079
7177
  });
7080
7178
  },
7081
7179
  });
7082
7180
  };
7083
- /**
7084
- * Post LinkedIn share
7085
- */
7181
+ /** Publish a LinkedIn text post through the server-held connection. */
7086
7182
  const usePostLinkedinShare = () => {
7087
7183
  return useMutation({
7088
- mutationFn: async ({ linkedinUserUrn, postText, accessToken, }) => {
7089
- const postShareRequest = {
7090
- author: linkedinUserUrn,
7091
- lifecycleState: 'PUBLISHED',
7092
- specificContent: {
7093
- 'com.linkedin.ugc.ShareContent': {
7094
- shareCommentary: { text: postText },
7095
- shareMediaCategory: 'NONE',
7096
- },
7097
- },
7098
- visibility: {
7099
- 'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC',
7100
- },
7101
- };
7184
+ mutationFn: async ({ postText }) => {
7102
7185
  return requestDatalayer({
7103
- url: `${configuration.iamUrl}/api/iam/v1/proxy/request`,
7186
+ url: `${configuration.iamUrl}/api/iam/v1/social/linkedin/posts`,
7104
7187
  method: 'POST',
7105
- body: {
7106
- request_method: 'POST',
7107
- request_url: 'https://api.linkedin.com/v2/ugcPosts',
7108
- request_token: accessToken,
7109
- request_body: postShareRequest,
7110
- },
7188
+ body: { commentary: postText },
7111
7189
  });
7112
7190
  },
7113
7191
  });
7114
7192
  };
7115
- /**
7116
- * Post LinkedIn share with image upload
7117
- */
7193
+ /** Publish a LinkedIn post, optionally with one uploaded image. */
7118
7194
  const usePostLinkedinShareWithUpload = () => {
7119
7195
  return useMutation({
7120
- mutationFn: async ({ linkedinUserUrn, postText, uploadObject, accessToken, }) => {
7121
- let shareRequest;
7122
- if (uploadObject) {
7123
- // Step 1: Register upload
7124
- const registerUploadRequest = {
7125
- registerUploadRequest: {
7126
- recipes: ['urn:li:digitalmediaRecipe:feedshare-image'],
7127
- owner: linkedinUserUrn,
7128
- serviceRelationships: [
7129
- {
7130
- relationshipType: 'OWNER',
7131
- identifier: 'urn:li:userGeneratedContent',
7132
- },
7133
- ],
7134
- },
7135
- };
7136
- const registerResp = await requestDatalayer({
7137
- url: `${configuration.iamUrl}/api/iam/v1/proxy/request`,
7138
- method: 'POST',
7139
- body: {
7140
- request_method: 'POST',
7141
- request_url: 'https://api.linkedin.com/v2/assets?action=registerUpload',
7142
- request_token: accessToken,
7143
- request_body: registerUploadRequest,
7144
- },
7145
- });
7146
- const asset = registerResp.response.value.asset;
7147
- const uploadUrl = registerResp.response.value.uploadMechanism['com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest'].uploadUrl;
7148
- // Step 2: Upload image
7149
- await requestDatalayer({
7150
- url: `${configuration.iamUrl}/api/iam/v1/proxy/request`,
7151
- method: 'POST',
7152
- body: {
7153
- request_method: 'PUT',
7154
- request_url: uploadUrl,
7155
- request_token: accessToken,
7156
- request_body: {
7157
- uploadURL: uploadUrl,
7158
- content: uploadObject,
7159
- userURN: linkedinUserUrn,
7160
- },
7161
- },
7162
- });
7163
- // Step 3: Create share with media
7164
- shareRequest = {
7165
- author: linkedinUserUrn,
7166
- lifecycleState: 'PUBLISHED',
7167
- specificContent: {
7168
- 'com.linkedin.ugc.ShareContent': {
7169
- shareCommentary: { text: postText },
7170
- shareMediaCategory: 'IMAGE',
7171
- media: [
7172
- {
7173
- status: 'READY',
7174
- description: { text: 'Datalayer Notebook' },
7175
- media: asset,
7176
- title: { text: 'Datalayer Notebook' },
7177
- },
7178
- ],
7179
- },
7180
- },
7181
- visibility: {
7182
- 'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC',
7183
- },
7184
- };
7185
- }
7186
- else {
7187
- // Text-only share (no image upload)
7188
- shareRequest = {
7189
- author: linkedinUserUrn,
7190
- lifecycleState: 'PUBLISHED',
7191
- specificContent: {
7192
- 'com.linkedin.ugc.ShareContent': {
7193
- shareCommentary: { text: postText },
7194
- shareMediaCategory: 'NONE',
7195
- },
7196
- },
7197
- visibility: {
7198
- 'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC',
7199
- },
7200
- };
7201
- }
7196
+ mutationFn: async ({ postText, uploadObject, }) => {
7202
7197
  return requestDatalayer({
7203
- url: `${configuration.iamUrl}/api/iam/v1/proxy/request`,
7198
+ url: `${configuration.iamUrl}/api/iam/v1/social/linkedin/posts`,
7204
7199
  method: 'POST',
7205
7200
  body: {
7206
- request_method: 'POST',
7207
- request_url: 'https://api.linkedin.com/v2/ugcPosts',
7208
- request_token: accessToken,
7209
- request_body: shareRequest,
7210
- },
7211
- });
7212
- },
7213
- });
7214
- };
7215
- // ============================================================================
7216
- // Proxy Operations
7217
- // ============================================================================
7218
- /**
7219
- * Proxy GET request
7220
- */
7221
- const useProxyGET = () => {
7222
- return useMutation({
7223
- mutationFn: async ({ url, token }) => {
7224
- return requestDatalayer({
7225
- url: `${configuration.iamUrl}/api/iam/v1/proxy/request`,
7226
- method: 'POST',
7227
- body: {
7228
- request_method: 'GET',
7229
- request_url: url,
7230
- request_token: token,
7231
- },
7232
- });
7233
- },
7234
- });
7235
- };
7236
- /**
7237
- * Proxy POST request
7238
- */
7239
- const useProxyPOST = () => {
7240
- return useMutation({
7241
- mutationFn: async ({ url, body, token, }) => {
7242
- return requestDatalayer({
7243
- url: `${configuration.iamUrl}/api/iam/v1/proxy/request`,
7244
- method: 'POST',
7245
- body: {
7246
- request_method: 'POST',
7247
- request_url: url,
7248
- request_token: token,
7249
- request_body: body,
7201
+ commentary: postText,
7202
+ image_data_url: uploadObject,
7250
7203
  },
7251
7204
  });
7252
7205
  },
7253
7206
  });
7254
7207
  };
7208
+ /** Connect-only AT Protocol account operations. */
7209
+ const useGetBlueskyConnection = () => useMutation({
7210
+ mutationFn: async () => requestDatalayer({
7211
+ url: `${configuration.iamUrl}/api/iam/v1/social/bluesky/profile`,
7212
+ method: 'GET',
7213
+ notifyOnError: false,
7214
+ }),
7215
+ });
7255
7216
  /**
7256
- * Proxy PUT request
7257
- */
7258
- const useProxyPUT = () => {
7259
- return useMutation({
7260
- mutationFn: async ({ url, body, token, }) => {
7261
- return requestDatalayer({
7262
- url: `${configuration.iamUrl}/api/iam/v1/proxy/request`,
7263
- method: 'POST',
7264
- body: {
7265
- request_method: 'PUT',
7266
- request_url: url,
7267
- request_token: token,
7268
- request_body: body,
7269
- },
7270
- });
7271
- },
7272
- });
7273
- };
7217
+ * Begin a Bluesky connection.
7218
+ *
7219
+ * `returnOrigin` is where the reader should come back to — their own origin,
7220
+ * so a connection begun on a developer's machine does not end on
7221
+ * production. IAM takes the origin only and builds the address itself, so
7222
+ * this cannot ask to be sent anywhere.
7223
+ */
7224
+ const useConnectBluesky = () => useMutation({
7225
+ mutationFn: async (asked) => {
7226
+ const { identifier, returnOrigin } = typeof asked === 'string'
7227
+ ? { identifier: asked, returnOrigin: undefined }
7228
+ : asked;
7229
+ return requestDatalayer({
7230
+ url: `${configuration.iamUrl}/api/iam/v1/social/bluesky/connect`,
7231
+ method: 'POST',
7232
+ body: returnOrigin
7233
+ ? { identifier, return_origin: returnOrigin }
7234
+ : { identifier },
7235
+ });
7236
+ },
7237
+ });
7238
+ const useDisconnectBluesky = () => useMutation({
7239
+ mutationFn: async () => requestDatalayer({
7240
+ url: `${configuration.iamUrl}/api/iam/v1/social/bluesky/connection`,
7241
+ method: 'DELETE',
7242
+ }),
7243
+ });
7274
7244
  // ============================================================================
7275
7245
  // Waiting List & Growth
7276
7246
  // ============================================================================
@@ -8319,11 +8289,16 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
8319
8289
  useGetLinkedinProfile,
8320
8290
  usePostLinkedinShare,
8321
8291
  usePostLinkedinShareWithUpload,
8292
+ useGetBlueskyConnection,
8293
+ useConnectBluesky,
8294
+ useDisconnectBluesky,
8295
+ usePublishLinkedInShare,
8296
+ useUnpublishLinkedInShare,
8297
+ useLinkedInShares,
8298
+ usePublishBlueskyShare,
8299
+ useUnpublishBlueskyShare,
8300
+ useBlueskyShares,
8322
8301
  useRegisterToWaitingList,
8323
- // Proxy
8324
- useProxyGET,
8325
- useProxyPOST,
8326
- useProxyPUT,
8327
8302
  // Users
8328
8303
  useUser,
8329
8304
  useUserByHandle,
@@ -34,7 +34,7 @@ import { deleteMcpPolicy, getAdmittedClients, getMcpPolicy, setMcpPolicy, } from
34
34
  import { createServiceAgent, listServiceAgents, revokeServiceAgent, rotateServiceAgentKey, } from '../api/iam/serviceAgents.js';
35
35
  import { useCoreStore, useIAMStore } from '../state/index.js';
36
36
  import { queryKeys } from './useCache.js';
37
- const useMcpServerUrl = () => useCoreStore(state => state.configuration.jupyterMcpServerUrl);
37
+ const useMcpServerUrl = () => useCoreStore(state => state.configuration.datalayerMcpServerUrl);
38
38
  const useIamUrl = () => useCoreStore(state => state.configuration.iamUrl);
39
39
  const useOtelUrl = () => useCoreStore(state => state.configuration.otelUrl);
40
40
  // -- Tasks -----------------------------------------------------------------
@@ -14,10 +14,17 @@
14
14
  * `window.open` otherwise, so a button gets it too. `newTab` in the options
15
15
  * opens a new tab outright.
16
16
  *
17
+ * Every navigation that stays in this tab is also **recorded** against the
18
+ * shell the reader is in ({@link state/substates/NavigationState}). That is
19
+ * what lets a reader switch from Agentify back to Home and find the page they
20
+ * left rather than a landing page, and it is done here — the one place every
21
+ * navigation goes through — rather than in an effect per layout.
22
+ *
17
23
  * @module hooks/useNavigate
18
24
  */
19
25
  import { useCallback, useMemo } from 'react';
20
26
  import { useLayoutStore } from '../state/index.js';
27
+ import { navigationStore } from '../state/substates/NavigationState.js';
21
28
  import { createNativeNavigate } from '../navigation/adapters/native.js';
22
29
  // Import React Router hooks from our wrapper
23
30
  import { useNavigateRR } from '../navigation/adapters/react-router.js';
@@ -125,6 +132,9 @@ export const useNavigate = () => {
125
132
  window.scrollTo(0, 0);
126
133
  document.body.scrollTop = 0;
127
134
  }
135
+ // Where the reader is now, for the shell they are in. A new tab and a
136
+ // step back through history are both already past by here.
137
+ navigationStore.getState().rememberRoute(to);
128
138
  if (rrNavigate) {
129
139
  rrNavigate(to, { replace: options.replace, state: options.state });
130
140
  return;
@@ -50,7 +50,7 @@ export function useWindowSize() {
50
50
  return windowSize;
51
51
  }
52
52
  const breakpointSwitch = (value) => {
53
- let current = BreakpointSize.XXLARGE;
53
+ let current;
54
54
  switch (true) {
55
55
  case value >= 320 && value < 544:
56
56
  current = BreakpointSize.XSMALL;
@@ -1,9 +1,15 @@
1
1
  import { IUser } from './User';
2
2
  export type IIAMProviderName = 'bluesky' | 'discord' | 'github' | 'google' | 'linkedin' | 'okta' | 'x';
3
+ /** Providers whose access token is intentionally available to browser code. */
4
+ export type IBrowserTokenProviderName = Exclude<IIAMProviderName, 'bluesky' | 'linkedin'>;
3
5
  export type IIAMProviderSpec = {
4
6
  name: IIAMProviderName;
5
7
  oauth2CallbackServerRoute: string;
6
8
  oauth2CallbackUIRoute: string;
9
+ };
10
+ /** Provider metadata used only when its access token may be read by the UI. */
11
+ export type IBrowserTokenProviderSpec = IIAMProviderSpec & {
12
+ name: IBrowserTokenProviderName;
7
13
  accessTokenCookieName: (user: IUser) => string;
8
14
  refreshTokenCookieName: string;
9
15
  userInfoURL: string;
@@ -13,11 +19,10 @@ export type IIAMProviderSpec = {
13
19
  };
14
20
  export declare class IAMProvidersSpecs {
15
21
  private constructor();
16
- static getProvider(providerIAMProvidersType: any): IIAMProviderSpec;
17
- static readonly Bluesky: IIAMProviderSpec;
18
- static readonly GitHub: IIAMProviderSpec;
19
- static readonly Google: IIAMProviderSpec;
22
+ static getProvider(providerIAMProvidersType: IBrowserTokenProviderName): IBrowserTokenProviderSpec;
23
+ static readonly GitHub: IBrowserTokenProviderSpec;
24
+ static readonly Google: IBrowserTokenProviderSpec;
20
25
  static readonly LinkedIn: IIAMProviderSpec;
21
- static readonly Okta: IIAMProviderSpec;
26
+ static readonly Okta: IBrowserTokenProviderSpec;
22
27
  }
23
28
  export default IAMProvidersSpecs;
@@ -6,18 +6,12 @@ export class IAMProvidersSpecs {
6
6
  constructor() { }
7
7
  static getProvider(providerIAMProvidersType) {
8
8
  switch (providerIAMProvidersType) {
9
- case 'bluesky': {
10
- return this.Bluesky;
11
- }
12
9
  case 'github': {
13
10
  return this.GitHub;
14
11
  }
15
12
  case 'google': {
16
13
  return this.Google;
17
14
  }
18
- case 'linkedin': {
19
- return this.LinkedIn;
20
- }
21
15
  case 'okta': {
22
16
  return this.Okta;
23
17
  }
@@ -27,17 +21,6 @@ export class IAMProvidersSpecs {
27
21
  }
28
22
  }
29
23
  }
30
- static Bluesky = {
31
- name: 'bluesky',
32
- oauth2CallbackServerRoute: 'jupyter_iam/oauth2/callback',
33
- oauth2CallbackUIRoute: '/iam/oauth2/bluesky/callback',
34
- accessTokenCookieName: (user) => `__datalayer__bluesky_access_token_${user.id}`,
35
- refreshTokenCookieName: '__datalayer__bluesky_refresh_token',
36
- userInfoURL: '',
37
- tokenRefreshURL: '',
38
- postShareURL: '',
39
- registerUploadURL: '',
40
- };
41
24
  static GitHub = {
42
25
  name: 'github',
43
26
  oauth2CallbackServerRoute: 'jupyter_iam/oauth2/callback',
@@ -64,12 +47,6 @@ export class IAMProvidersSpecs {
64
47
  name: 'linkedin',
65
48
  oauth2CallbackServerRoute: 'jupyter_iam/oauth2/callback',
66
49
  oauth2CallbackUIRoute: '/iam/oauth2/linkedin/callback',
67
- accessTokenCookieName: (user) => `__datalayer__linkedin_access_token_${user.id}`,
68
- refreshTokenCookieName: '__datalayer__linkedin_refresh_token',
69
- userInfoURL: 'https://api.linkedin.com/v2/userinfo',
70
- tokenRefreshURL: '',
71
- postShareURL: 'https://api.linkedin.com/v2/ugcPosts',
72
- registerUploadURL: 'https://api.linkedin.com/v2/assets?action=registerUpload',
73
50
  };
74
51
  static Okta = {
75
52
  name: 'okta',
@@ -1,4 +1,4 @@
1
1
  import * as ReactRouterDom from 'react-router-dom';
2
2
  export declare const useParamsRR: typeof ReactRouterDom.useParams;
3
3
  export declare const useLocationRR: typeof ReactRouterDom.useLocation;
4
- export declare const useNavigateRR: typeof ReactRouterDom.useNavigate;
4
+ export declare const useNavigateRR: () => ReactRouterDom.NavigateFunction;
@@ -9,4 +9,7 @@ import * as ReactRouterDom from 'react-router-dom';
9
9
  // Export hooks for use in our navigation hooks
10
10
  export const useParamsRR = ReactRouterDom.useParams;
11
11
  export const useLocationRR = ReactRouterDom.useLocation;
12
+ // Typed here rather than inferred: the inferred type carries React Router's
13
+ // own doc comment, whose links (`redirect`, `To`, `<ScrollRestoration>`) point
14
+ // at symbols these docs do not include, and typedoc fails the build on them.
12
15
  export const useNavigateRR = ReactRouterDom.useNavigate;
@@ -142,7 +142,7 @@ export const claimSessionState = (userUid) => {
142
142
  return;
143
143
  }
144
144
  const localStorage = storageOf('localStorage');
145
- let owner = null;
145
+ let owner;
146
146
  try {
147
147
  owner = localStorage?.getItem(SESSION_OWNER_KEY) ?? null;
148
148
  }
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import { createStore } from 'zustand/vanilla';
6
6
  import { useStore } from 'zustand';
7
+ import { DEFAULT_PLANE_URLS } from '../../config/planes.js';
7
8
  import { configLogger } from '../../utils/Logger.js';
8
9
  let loadConfigurationFromServer = true;
9
10
  let initialConfiguration = {
@@ -15,22 +16,8 @@ let initialConfiguration = {
15
16
  whiteLabel: true,
16
17
  loadConfigurationFromServer: true,
17
18
  jupyterServerless: false,
18
- iamUrl: 'https://prod1.datalayer.run',
19
- contentsUrl: 'https://r1.datalayer.run',
20
- managerUrl: 'https://prod1.datalayer.run',
21
- runtimesUrl: 'https://r1.datalayer.run',
22
- schedulerUrl: 'https://r1.datalayer.run',
23
- libraryUrl: 'https://prod1.datalayer.run',
24
- spacerUrl: 'https://prod1.datalayer.run',
25
- aiAgentsUrl: 'https://r1.datalayer.run',
26
- aiInferenceUrl: 'https://r1.datalayer.run',
27
- jupyterMcpServerUrl: 'https://mcp.datalayer.run/mcp',
28
- otelUrl: 'https://prod1.datalayer.run',
29
- // Defaults to prod so telemetry is consumed from the production OTEL service
30
- growthUrl: 'https://prod1.datalayer.run',
31
- inboundsUrl: 'https://prod1.datalayer.run',
32
- successUrl: 'https://prod1.datalayer.run',
33
- supportUrl: 'https://prod1.datalayer.run',
19
+ // Which plane each service is on is said once, in `config/planes`.
20
+ ...DEFAULT_PLANE_URLS,
34
21
  launcher: {
35
22
  category: 'Datalayer',
36
23
  name: 'Datalayer',
@@ -1,4 +1,4 @@
1
- import { IUser, IIAMProviderName } from '../../models';
1
+ import { IUser, IIAMProviderName, IBrowserTokenProviderName } from '../../models';
2
2
  import type { ICredits, ICreditsReservation } from '../../models';
3
3
  /**
4
4
  * Limit to warn about low credits in milliseconds.
@@ -55,8 +55,8 @@ export type IAMState = IIAMState & {
55
55
  */
56
56
  refreshCredits: () => Promise<void>;
57
57
  checkIAMToken: (token: string) => Promise<void>;
58
- setIAMProviderAccessToken: (provider: IIAMProviderName, accessToken?: string | null) => void;
59
- getIAMProviderAccessToken: (user: IUser, provider: IIAMProviderName) => string | undefined;
58
+ setIAMProviderAccessToken: (provider: IBrowserTokenProviderName, accessToken?: string | null) => void;
59
+ getIAMProviderAccessToken: (user: IUser, provider: IBrowserTokenProviderName) => string | undefined;
60
60
  refreshUser: () => Promise<void>;
61
61
  refreshUserByTokenStored: () => Promise<void>;
62
62
  refreshUserByToken: (token: string) => Promise<void>;