@databiosphere/findable-ui 51.1.0 → 52.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -219,7 +219,11 @@ export interface ListViewConfig {
219
219
  rowPreviewView?: ComponentsConfig;
220
220
  rowSelectionView?: ComponentsConfig;
221
221
  }
222
- export interface OAuthProvider<P = any> {
222
+ export declare enum OAUTH_FLOW {
223
+ AUTHORIZATION_CODE = "AUTHORIZATION_CODE",
224
+ IMPLICIT = "IMPLICIT"
225
+ }
226
+ interface OAuthProviderBase<P = any> {
223
227
  authorization: {
224
228
  params: {
225
229
  scope: string;
@@ -232,6 +236,14 @@ export interface OAuthProvider<P = any> {
232
236
  profile: (profile: P) => UserProfile;
233
237
  userinfo: string;
234
238
  }
239
+ export interface ImplicitFlowProvider<P = any> extends OAuthProviderBase<P> {
240
+ flow: OAUTH_FLOW.IMPLICIT;
241
+ }
242
+ export interface AuthorizationCodeFlowProvider<P = any> extends OAuthProviderBase<P> {
243
+ authorize: string;
244
+ flow: OAUTH_FLOW.AUTHORIZATION_CODE;
245
+ }
246
+ export type OAuthProvider<P = any> = ImplicitFlowProvider<P> | AuthorizationCodeFlowProvider<P>;
235
247
  /**
236
248
  * Option Method.
237
249
  */
@@ -1,3 +1,8 @@
1
+ export var OAUTH_FLOW;
2
+ (function (OAUTH_FLOW) {
3
+ OAUTH_FLOW["AUTHORIZATION_CODE"] = "AUTHORIZATION_CODE";
4
+ OAUTH_FLOW["IMPLICIT"] = "IMPLICIT";
5
+ })(OAUTH_FLOW || (OAUTH_FLOW = {}));
1
6
  /**
2
7
  * Sort direction.
3
8
  */
@@ -1,15 +1,17 @@
1
- import { OAuthProvider } from "../config/entities";
2
- import { SessionDispatch } from "./types";
1
+ import { type OAuthProvider } from "../config/entities";
2
+ import { type LoginDispatch } from "./services/common";
3
+ import type { SessionDispatch } from "./types";
3
4
  /**
4
5
  * Google Sign-In service.
5
6
  */
6
7
  export declare const service: {
7
8
  /**
8
9
  * Login with Google OAuth.
10
+ * Dispatches to the configured flow based on `provider.flow`.
9
11
  * @param provider - OAuth provider configuration.
10
12
  * @param dispatch - Dispatch functions for auth state.
11
13
  */
12
- login: (provider: OAuthProvider, dispatch: Pick<SessionDispatch, "authDispatch" | "authenticationDispatch" | "tokenDispatch">) => void;
14
+ login: (provider: OAuthProvider, dispatch: LoginDispatch) => void;
13
15
  /**
14
16
  * Logout and clear all auth state.
15
17
  * @param dispatch - Dispatch functions for auth state.
@@ -1,54 +1,30 @@
1
- import { requestAuth, resetAuthState } from "../auth/dispatch/auth";
2
- import { requestAuthentication, resetAuthenticationState, updateAuthentication, } from "../auth/dispatch/authentication";
3
- import { resetCredentialsState } from "../auth/dispatch/credentials";
4
- import { resetTokenState, updateToken } from "../auth/dispatch/token";
5
- import { AUTHENTICATION_STATUS } from "../auth/types/authentication";
6
- import { fetchProfile, getAuthenticationRequestOptions } from "./utils/auth";
1
+ import { OAUTH_FLOW } from "../config/entities";
2
+ import { login as authorizationCodeFlowLogin } from "./services/authorizationCodeFlow";
3
+ import { logout } from "./services/common";
4
+ import { login as implicitFlowLogin } from "./services/implicitFlow";
7
5
  /**
8
6
  * Google Sign-In service.
9
7
  */
10
8
  export const service = {
11
9
  /**
12
10
  * Login with Google OAuth.
11
+ * Dispatches to the configured flow based on `provider.flow`.
13
12
  * @param provider - OAuth provider configuration.
14
13
  * @param dispatch - Dispatch functions for auth state.
15
14
  */
16
15
  login: (provider, dispatch) => {
17
- const client = google.accounts.oauth2.initTokenClient({
18
- callback: (response) => {
19
- const { id, profile, userinfo } = provider;
20
- const { access_token: token } = response;
21
- dispatch.authDispatch?.(requestAuth());
22
- dispatch.authenticationDispatch?.(requestAuthentication());
23
- dispatch.tokenDispatch?.(updateToken({ providerId: id, token }));
24
- fetchProfile(userinfo, getAuthenticationRequestOptions(token), {
25
- onError: () => {
26
- dispatch.authDispatch?.(resetAuthState());
27
- dispatch.authenticationDispatch?.(updateAuthentication({
28
- profile: undefined,
29
- status: AUTHENTICATION_STATUS.SETTLED,
30
- }));
31
- dispatch.tokenDispatch?.(resetTokenState());
32
- },
33
- onSuccess: (r) => dispatch.authenticationDispatch?.(updateAuthentication({
34
- profile: profile(r),
35
- status: AUTHENTICATION_STATUS.PENDING, // Authentication is pending until session controller is resolved.
36
- })),
37
- });
38
- },
39
- client_id: provider.clientId,
40
- scope: provider.authorization.params.scope,
41
- });
42
- client.requestAccessToken();
16
+ if (provider.flow === OAUTH_FLOW.AUTHORIZATION_CODE) {
17
+ authorizationCodeFlowLogin(provider, dispatch);
18
+ }
19
+ else {
20
+ implicitFlowLogin(provider, dispatch);
21
+ }
43
22
  },
44
23
  /**
45
24
  * Logout and clear all auth state.
46
25
  * @param dispatch - Dispatch functions for auth state.
47
26
  */
48
27
  logout: (dispatch) => {
49
- dispatch.authDispatch?.(resetAuthState());
50
- dispatch.authenticationDispatch?.(resetAuthenticationState());
51
- dispatch.credentialsDispatch?.(resetCredentialsState());
52
- dispatch.tokenDispatch?.(resetTokenState());
28
+ logout(dispatch);
53
29
  },
54
30
  };
@@ -0,0 +1,10 @@
1
+ import type { AuthorizationCodeFlowProvider } from "../../config/entities";
2
+ import { type LoginDispatch } from "./common";
3
+ /**
4
+ * Login using the OAuth 2.0 authorization code flow.
5
+ * Uses Google's initCodeClient to request an authorization code,
6
+ * then exchanges it for an access token via the configured authorize endpoint.
7
+ * @param provider - OAuth provider configuration.
8
+ * @param dispatch - Dispatch functions for auth state.
9
+ */
10
+ export declare function login(provider: AuthorizationCodeFlowProvider, dispatch: LoginDispatch): void;
@@ -0,0 +1,38 @@
1
+ import { createOnAccessToken, createResetSession, } from "./common";
2
+ /**
3
+ * Login using the OAuth 2.0 authorization code flow.
4
+ * Uses Google's initCodeClient to request an authorization code,
5
+ * then exchanges it for an access token via the configured authorize endpoint.
6
+ * @param provider - OAuth provider configuration.
7
+ * @param dispatch - Dispatch functions for auth state.
8
+ */
9
+ export function login(provider, dispatch) {
10
+ const { authorize } = provider;
11
+ const resetSession = createResetSession(dispatch);
12
+ const onAccessToken = createOnAccessToken(provider, dispatch, resetSession);
13
+ const client = google.accounts.oauth2.initCodeClient({
14
+ callback: (response) => {
15
+ fetch(authorize, {
16
+ body: JSON.stringify(response),
17
+ headers: { "Content-Type": "application/json" },
18
+ method: "POST",
19
+ })
20
+ .then((r) => {
21
+ if (!r.ok) {
22
+ throw new Error(`authorize request failed (${r.status})`);
23
+ }
24
+ return r.json();
25
+ })
26
+ .then((tokens) => {
27
+ if (!tokens?.access_token) {
28
+ throw new Error("authorize response missing access_token");
29
+ }
30
+ onAccessToken(tokens.access_token);
31
+ })
32
+ .catch(resetSession);
33
+ },
34
+ client_id: provider.clientId,
35
+ scope: provider.authorization.params.scope,
36
+ });
37
+ client.requestCode();
38
+ }
@@ -0,0 +1,23 @@
1
+ import type { OAuthProvider } from "../../config/entities";
2
+ import type { SessionDispatch } from "../types";
3
+ export type LoginDispatch = Pick<SessionDispatch, "authDispatch" | "authenticationDispatch" | "tokenDispatch">;
4
+ /**
5
+ * Creates a function that resets the session state on auth failure.
6
+ * @param dispatch - Dispatch functions for auth state.
7
+ * @returns reset session function.
8
+ */
9
+ export declare function createResetSession(dispatch: LoginDispatch): () => void;
10
+ /**
11
+ * Creates a function that handles a successful access token.
12
+ * Dispatches auth state updates and fetches the user profile.
13
+ * @param provider - OAuth provider configuration.
14
+ * @param dispatch - Dispatch functions for auth state.
15
+ * @param resetSession - Reset session function.
16
+ * @returns on access token function.
17
+ */
18
+ export declare function createOnAccessToken(provider: OAuthProvider, dispatch: LoginDispatch, resetSession: () => void): (token: string) => void;
19
+ /**
20
+ * Logout and clear all auth state.
21
+ * @param dispatch - Dispatch functions for auth state.
22
+ */
23
+ export declare function logout(dispatch: SessionDispatch): void;
@@ -0,0 +1,54 @@
1
+ import { requestAuth, resetAuthState } from "../../auth/dispatch/auth";
2
+ import { requestAuthentication, resetAuthenticationState, updateAuthentication, } from "../../auth/dispatch/authentication";
3
+ import { resetCredentialsState } from "../../auth/dispatch/credentials";
4
+ import { resetTokenState, updateToken } from "../../auth/dispatch/token";
5
+ import { AUTHENTICATION_STATUS } from "../../auth/types/authentication";
6
+ import { fetchProfile, getAuthenticationRequestOptions } from "../utils/auth";
7
+ /**
8
+ * Creates a function that resets the session state on auth failure.
9
+ * @param dispatch - Dispatch functions for auth state.
10
+ * @returns reset session function.
11
+ */
12
+ export function createResetSession(dispatch) {
13
+ return () => {
14
+ dispatch.authDispatch?.(resetAuthState());
15
+ dispatch.authenticationDispatch?.(updateAuthentication({
16
+ profile: undefined,
17
+ status: AUTHENTICATION_STATUS.SETTLED,
18
+ }));
19
+ dispatch.tokenDispatch?.(resetTokenState());
20
+ };
21
+ }
22
+ /**
23
+ * Creates a function that handles a successful access token.
24
+ * Dispatches auth state updates and fetches the user profile.
25
+ * @param provider - OAuth provider configuration.
26
+ * @param dispatch - Dispatch functions for auth state.
27
+ * @param resetSession - Reset session function.
28
+ * @returns on access token function.
29
+ */
30
+ export function createOnAccessToken(provider, dispatch, resetSession) {
31
+ const { id, profile, userinfo } = provider;
32
+ return (token) => {
33
+ dispatch.authDispatch?.(requestAuth());
34
+ dispatch.authenticationDispatch?.(requestAuthentication());
35
+ dispatch.tokenDispatch?.(updateToken({ providerId: id, token }));
36
+ fetchProfile(userinfo, getAuthenticationRequestOptions(token), {
37
+ onError: resetSession,
38
+ onSuccess: (r) => dispatch.authenticationDispatch?.(updateAuthentication({
39
+ profile: profile(r),
40
+ status: AUTHENTICATION_STATUS.PENDING,
41
+ })),
42
+ });
43
+ };
44
+ }
45
+ /**
46
+ * Logout and clear all auth state.
47
+ * @param dispatch - Dispatch functions for auth state.
48
+ */
49
+ export function logout(dispatch) {
50
+ dispatch.authDispatch?.(resetAuthState());
51
+ dispatch.authenticationDispatch?.(resetAuthenticationState());
52
+ dispatch.credentialsDispatch?.(resetCredentialsState());
53
+ dispatch.tokenDispatch?.(resetTokenState());
54
+ }
@@ -0,0 +1,9 @@
1
+ import type { ImplicitFlowProvider } from "../../config/entities";
2
+ import { type LoginDispatch } from "./common";
3
+ /**
4
+ * Login using the OAuth 2.0 implicit flow.
5
+ * Uses Google's initTokenClient to request an access token directly.
6
+ * @param provider - OAuth provider configuration.
7
+ * @param dispatch - Dispatch functions for auth state.
8
+ */
9
+ export declare function login(provider: ImplicitFlowProvider, dispatch: LoginDispatch): void;
@@ -0,0 +1,17 @@
1
+ import { createOnAccessToken, createResetSession, } from "./common";
2
+ /**
3
+ * Login using the OAuth 2.0 implicit flow.
4
+ * Uses Google's initTokenClient to request an access token directly.
5
+ * @param provider - OAuth provider configuration.
6
+ * @param dispatch - Dispatch functions for auth state.
7
+ */
8
+ export function login(provider, dispatch) {
9
+ const resetSession = createResetSession(dispatch);
10
+ const onAccessToken = createOnAccessToken(provider, dispatch, resetSession);
11
+ const client = google.accounts.oauth2.initTokenClient({
12
+ callback: (response) => onAccessToken(response.access_token),
13
+ client_id: provider.clientId,
14
+ scope: provider.authorization.params.scope,
15
+ });
16
+ client.requestAccessToken();
17
+ }
@@ -3,6 +3,17 @@ import { AuthAction, AuthContextProps } from "../auth/types/auth";
3
3
  import { AuthenticationAction, AuthenticationContextProps } from "../auth/types/authentication";
4
4
  import { CredentialsAction, CredentialsContextProps } from "../auth/types/credentials";
5
5
  import { TokenAction, TokenContextProps, TokenState } from "../auth/types/token";
6
+ /**
7
+ * Authorization code response from Google OAuth.
8
+ */
9
+ export interface CodeResponse {
10
+ code?: string;
11
+ error?: string;
12
+ error_description?: string;
13
+ error_uri?: string;
14
+ scope?: string;
15
+ state?: string;
16
+ }
6
17
  /**
7
18
  * Google Sign-In authentication provider props.
8
19
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@databiosphere/findable-ui",
3
- "version": "51.1.0",
3
+ "version": "52.0.0",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
@@ -44,7 +44,6 @@
44
44
  "@types/jest": "^29.5.14",
45
45
  "@types/react": "^19.2.7",
46
46
  "@types/react-dom": "^19.2.3",
47
- "@types/react-gtm-module": "^2.0.1",
48
47
  "@types/react-window": "^1.8.5",
49
48
  "@typescript-eslint/eslint-plugin": "^8.50.0",
50
49
  "eslint": "^8.57.1",
@@ -88,7 +87,6 @@
88
87
  "react": "^19.2.3",
89
88
  "react-dom": "^19.2.3",
90
89
  "react-dropzone": "^14.3.8",
91
- "react-gtm-module": "^2.0.11",
92
90
  "react-idle-timer": "^5.7.2",
93
91
  "react-window": "^1.8.11",
94
92
  "rehype-raw": "^7.0.0",