@base44-preview/sdk 0.8.52-pr.298.d08e0ba → 0.8.52-pr.301.106bb9e

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 CHANGED
@@ -151,5 +151,3 @@ npm run create-docs
151
151
  cd docs
152
152
  mintlify dev
153
153
  ```
154
-
155
- See [experimental app-user MFA](MFA.md) for challenge handling and managed continuation.
package/dist/index.d.ts CHANGED
@@ -18,4 +18,3 @@ export { Actor, type Conn } from "./actor.js";
18
18
  export type { ConnectorsModule, UserConnectorsModule, ConnectorApiRequest, ConnectorApiResponse, ConnectorApiResponsePhase, } from "./modules/connectors.types.js";
19
19
  export type { CustomIntegrationsModule, CustomIntegrationCallParams, CustomIntegrationCallResponse, } from "./modules/custom-integrations.types.js";
20
20
  export type { GetAccessTokenOptions, SaveAccessTokenOptions, RemoveAccessTokenOptions, GetLoginUrlOptions, } from "./utils/auth-utils.types.js";
21
- export type { MfaChallenge, MfaModule, MfaProof, LoginResult, MfaEnrollmentResult } from "./modules/mfa.js";
@@ -1,4 +1,3 @@
1
- import { createMfaModule, prepareMfaPkce } from "./mfa.js";
2
1
  import { resetAnalyticsSessionContext } from "./analytics.js";
3
2
  function isInsideIframe() {
4
3
  if (typeof window === "undefined")
@@ -20,9 +19,9 @@ function loginViaPopup(url, redirectUrl, expectedOrigin) {
20
19
  const height = 600;
21
20
  const left = Math.round(window.screenX + (window.outerWidth - width) / 2);
22
21
  const top = Math.round(window.screenY + (window.outerHeight - height) / 2);
23
- const popup = window.open("about:blank", "base44_auth", `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`);
22
+ const popup = window.open(url, "base44_auth", `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`);
24
23
  if (!popup) {
25
- return Promise.resolve();
24
+ return;
26
25
  }
27
26
  const cleanup = () => {
28
27
  window.removeEventListener("message", onMessage);
@@ -53,7 +52,6 @@ function loginViaPopup(url, redirectUrl, expectedOrigin) {
53
52
  cleanup();
54
53
  }, 500);
55
54
  window.addEventListener("message", onMessage);
56
- return url.then(value => { popup.location.href = value; }, error => { cleanup(); throw error; });
57
55
  }
58
56
  /**
59
57
  * Creates the auth module for the Base44 SDK.
@@ -84,8 +82,7 @@ export function createAuthModule(axios, functionsAxiosClient, appId, options) {
84
82
  // to the identity transitions below (`setToken`, `logout`) instead of to the
85
83
  // header a caller may have set on the instance directly.
86
84
  let hasAccessToken = Boolean(options.token);
87
- const module = {
88
- mfa: createMfaModule(axios, appId, token => module.setToken(token)),
85
+ return {
89
86
  hasToken() {
90
87
  return hasAccessToken;
91
88
  },
@@ -122,10 +119,9 @@ export function createAuthModule(axios, functionsAxiosClient, appId, options) {
122
119
  window.location.href = loginUrl;
123
120
  },
124
121
  // Redirects the user to a provider's login page
125
- async loginWithProvider(provider, fromUrl = "/") {
122
+ loginWithProvider(provider, fromUrl = "/") {
126
123
  // Build the full redirect URL
127
124
  const redirectUrl = new URL(fromUrl, window.location.origin).toString();
128
- const mfaPkce = provider === "sso" ? Promise.resolve("") : prepareMfaPkce(appId).then(value => `&app_mfa_code_challenge=${value}`);
129
125
  const queryParams = `app_id=${appId}&from_url=${encodeURIComponent(redirectUrl)}`;
130
126
  // SSO uses a different URL structure with appId in the path
131
127
  let authPath;
@@ -141,11 +137,11 @@ export function createAuthModule(axios, functionsAxiosClient, appId, options) {
141
137
  // When running inside an iframe, use a popup to avoid OAuth providers
142
138
  // blocking iframe navigation.
143
139
  if (isInsideIframe()) {
144
- const popupLoginUrl = mfaPkce.then(pkce => `${loginUrl}${pkce}&popup_origin=${encodeURIComponent(window.location.origin)}`);
140
+ const popupLoginUrl = `${loginUrl}&popup_origin=${encodeURIComponent(window.location.origin)}`;
145
141
  return loginViaPopup(popupLoginUrl, redirectUrl, window.location.origin);
146
142
  }
147
143
  // Default: full-page redirect
148
- window.location.href = loginUrl + await mfaPkce;
144
+ window.location.href = loginUrl;
149
145
  },
150
146
  // Logout the current user
151
147
  logout(redirectUrl) {
@@ -211,8 +207,6 @@ export function createAuthModule(axios, functionsAxiosClient, appId, options) {
211
207
  password,
212
208
  ...(turnstileToken && { turnstile_token: turnstileToken }),
213
209
  });
214
- if (response.mfa_required)
215
- return response;
216
210
  const { access_token, user } = response;
217
211
  if (access_token) {
218
212
  this.setToken(access_token);
@@ -284,5 +278,4 @@ export function createAuthModule(axios, functionsAxiosClient, appId, options) {
284
278
  });
285
279
  },
286
280
  };
287
- return module;
288
281
  }
@@ -1,4 +1,3 @@
1
- import type { LoginResult, MfaModule } from "./mfa.js";
2
1
  /**
3
2
  * An authenticated user.
4
3
  */
@@ -38,7 +37,6 @@ export interface User {
38
37
  * Response from login endpoints containing user information and access token.
39
38
  */
40
39
  export interface LoginResponse {
41
- mfa_required?: false;
42
40
  /** JWT access token for authentication. */
43
41
  access_token: string;
44
42
  /** User information. */
@@ -119,8 +117,6 @@ export interface AuthModuleOptions {
119
117
  * The auth module is only available in user authentication mode (`base44.auth`).
120
118
  */
121
119
  export interface AuthModule {
122
- /** Multi-factor enrollment and login for this app. */
123
- mfa: MfaModule;
124
120
  /**
125
121
  * Gets the current authenticated user's information.
126
122
  *
@@ -223,7 +219,7 @@ export interface AuthModule {
223
219
  * ```
224
220
  *
225
221
  */
226
- loginWithProvider(provider: string, fromUrl?: string): Promise<void>;
222
+ loginWithProvider(provider: string, fromUrl?: string): void;
227
223
  /**
228
224
  * Logs out the current user.
229
225
  *
@@ -306,7 +302,7 @@ export interface AuthModule {
306
302
  * );
307
303
  * ```
308
304
  */
309
- loginViaEmailPassword(email: string, password: string, turnstileToken?: string): Promise<LoginResult>;
305
+ loginViaEmailPassword(email: string, password: string, turnstileToken?: string): Promise<LoginResponse>;
310
306
  /**
311
307
  * Checks if the current user is authenticated.
312
308
  *
@@ -431,7 +427,7 @@ export interface AuthModule {
431
427
  * );
432
428
  * ```
433
429
  */
434
- verifyOtp(params: VerifyOtpParams): Promise<LoginResult>;
430
+ verifyOtp(params: VerifyOtpParams): Promise<any>;
435
431
  /**
436
432
  * Resends an OTP code to the user's email address.
437
433
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@base44-preview/sdk",
3
- "version": "0.8.52-pr.298.d08e0ba",
3
+ "version": "0.8.52-pr.301.106bb9e",
4
4
  "description": "JavaScript SDK for Base44 API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -10,7 +10,6 @@
10
10
  ],
11
11
  "scripts": {
12
12
  "build": "tsc",
13
- "lint": "eslint src",
14
13
  "test": "npm run test:types && vitest run",
15
14
  "test:types": "tsc --noEmit -p tsconfig.type-tests.json",
16
15
  "test:unit": "vitest run tests/unit",
@@ -31,24 +30,6 @@
31
30
  "socket.io-client": "^4.8.3",
32
31
  "uuid": "^13.0.2"
33
32
  },
34
- "devDependencies": {
35
- "@types/hast": "^3.0.4",
36
- "@types/node": "^25.0.1",
37
- "@types/unist": "^3.0.3",
38
- "@typescript-eslint/parser": "^8.51.0",
39
- "@vitest/coverage-istanbul": "^4.1.9",
40
- "@vitest/coverage-v8": "^4.1.9",
41
- "@vitest/ui": "^4.1.9",
42
- "dotenv": "^16.3.1",
43
- "eslint": "^9.39.2",
44
- "eslint-plugin-import": "^2.32.0",
45
- "nock": "^13.4.0",
46
- "typedoc": "^0.28.14",
47
- "typedoc-plugin-markdown": "^4.9.0",
48
- "typescript": "^5.3.2",
49
- "typescript-eslint": "^8.51.0",
50
- "vitest": "^4.1.9"
51
- },
52
33
  "keywords": [
53
34
  "base44",
54
35
  "api",
@@ -58,10 +39,11 @@
58
39
  "license": "MIT",
59
40
  "repository": {
60
41
  "type": "git",
61
- "url": "git+https://github.com/base44/javascript-sdk.git"
42
+ "url": "git+https://github.com/base44/javascript-sdk.git",
43
+ "directory": "packages/sdk"
62
44
  },
63
45
  "bugs": {
64
46
  "url": "https://github.com/base44/javascript-sdk/issues"
65
47
  },
66
- "homepage": "https://github.com/base44/javascript-sdk#readme"
48
+ "homepage": "https://github.com/base44/javascript-sdk/tree/main/packages/sdk#readme"
67
49
  }
@@ -1,52 +0,0 @@
1
- import type { AxiosInstance } from 'axios';
2
- import type { LoginResponse } from './auth.types.js';
3
- /** A restricted, short-lived login outcome. It is never an access token. */
4
- export interface MfaChallenge {
5
- mfa_required: true;
6
- next_step: 'enroll' | 'verify';
7
- mfa_methods: ('totp' | 'sms')[];
8
- mfa_session_token: string;
9
- expires_in_seconds: number;
10
- phone_hint?: string;
11
- access_token?: never;
12
- user?: never;
13
- }
14
- export type LoginResult = LoginResponse | MfaChallenge;
15
- export interface MfaEnrollmentResult extends LoginResponse {
16
- backup_codes?: string[];
17
- }
18
- export interface MfaProof {
19
- code: string;
20
- method: 'totp' | 'sms';
21
- remember_device?: boolean;
22
- }
23
- /** App-scoped MFA. Pass the challenge credential explicitly; do not set it as the SDK token. */
24
- export interface MfaModule {
25
- getStatus(): Promise<{
26
- mfa_enabled: boolean;
27
- methods: ('totp' | 'sms')[];
28
- backup_codes_remaining: number;
29
- policy: 'off' | 'required';
30
- }>;
31
- /** Requires an app admin session; resets a user in this app only. */
32
- resetForUser(appUserId: string): Promise<{
33
- success: true;
34
- }>;
35
- /** Open managed settings with fresh primary authentication and factor verification. */
36
- openSecurity(returnTo?: string): void;
37
- setupTotp(challenge: MfaChallenge): Promise<{
38
- secret: string;
39
- secret_formatted: string;
40
- qr_code: string;
41
- }>;
42
- sendSms(challenge: MfaChallenge, phoneNumber: string): Promise<unknown>;
43
- enrollTotp(challenge: MfaChallenge, code: string, rememberDevice?: boolean): Promise<MfaEnrollmentResult>;
44
- enrollSms(challenge: MfaChallenge, code: string, rememberDevice?: boolean): Promise<MfaEnrollmentResult>;
45
- verify(challenge: MfaChallenge, proof: MfaProof): Promise<LoginResponse>;
46
- verifyRecoveryCode(challenge: MfaChallenge, code: string, rememberDevice?: boolean): Promise<LoginResponse>;
47
- resendSms(challenge: MfaChallenge): Promise<unknown>;
48
- /** Open Base44's managed MFA flow on this app's origin. */
49
- continueLogin(challenge: MfaChallenge, returnTo?: string): Promise<void>;
50
- }
51
- export declare function prepareMfaPkce(appId: string): Promise<string>;
52
- export declare function createMfaModule(axios: AxiosInstance, appId: string, setToken: (token: string) => void): MfaModule;
@@ -1,43 +0,0 @@
1
- export async function prepareMfaPkce(appId) {
2
- const encode = (value) => btoa(String.fromCharCode(...value)).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
3
- const verifier = encode(crypto.getRandomValues(new Uint8Array(32)));
4
- sessionStorage.setItem(`app-mfa-pkce:${appId}`, verifier);
5
- return encode(new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier))));
6
- }
7
- export function createMfaModule(axios, appId, setToken) {
8
- const post = async (challenge, path, payload = {}) => {
9
- const response = await axios.post(`/apps/${appId}/auth/mfa${path}`, payload, {
10
- headers: { Authorization: `Bearer ${challenge.mfa_session_token}` }, withCredentials: true,
11
- });
12
- const token = response.access_token;
13
- if (token)
14
- setToken(token);
15
- return response;
16
- };
17
- return {
18
- getStatus: () => axios.get(`/apps/${appId}/auth/mfa/status`),
19
- resetForUser: appUserId => axios.post(`/apps/${appId}/auth/mfa/reset`, { app_user_id: appUserId }),
20
- openSecurity(returnTo = '/') {
21
- const target = new URL(returnTo, window.location.origin);
22
- if (target.origin !== window.location.origin)
23
- throw new Error('MFA must return to this app.');
24
- window.location.href = `/auth/mfa?${new URLSearchParams({ security: '1', from_url: target.pathname + target.search + target.hash })}`;
25
- },
26
- setupTotp: challenge => post(challenge, '/totp/setup'),
27
- sendSms: (challenge, phoneNumber) => post(challenge, '/sms/send-code', { phone_number: phoneNumber }),
28
- enrollTotp: (challenge, code, rememberDevice = false) => post(challenge, '/totp/verify', { code, remember_device: rememberDevice }),
29
- enrollSms: (challenge, code, rememberDevice = false) => post(challenge, '/sms/verify', { code, remember_device: rememberDevice }),
30
- verify: (challenge, proof) => post(challenge, '/verify', proof),
31
- verifyRecoveryCode: (challenge, code, rememberDevice = false) => post(challenge, '/verify-backup', { backup_code: code, remember_device: rememberDevice }),
32
- resendSms: challenge => post(challenge, '/resend'),
33
- async continueLogin(challenge, returnTo = '/') {
34
- const target = new URL(returnTo, window.location.origin);
35
- if (target.origin !== window.location.origin)
36
- throw new Error('MFA must return to this app.');
37
- const codeChallenge = await prepareMfaPkce(appId);
38
- const handoff = await post(challenge, '/handoff', { code_challenge: codeChallenge });
39
- const query = new URLSearchParams({ app_id: appId, mfa_code: handoff.code, from_url: target.pathname + target.search + target.hash });
40
- window.location.href = `/auth/mfa?${query}`;
41
- },
42
- };
43
- }