@base44-preview/sdk 0.8.31-pr.178.78bd45c → 0.8.31-pr.178.f25a7cd

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.
@@ -1,4 +1,4 @@
1
- import { getActiveAccountIdFromPath } from "../utils/common.js";
1
+ import { getStoredActiveAccountId, setStoredActiveAccountId, } from "../utils/common.js";
2
2
  /**
3
3
  * Creates the accounts module (multi-tenancy) for the Base44 SDK.
4
4
  *
@@ -12,13 +12,16 @@ export function createAccountsModule(axios, appId) {
12
12
  const enc = encodeURIComponent;
13
13
  return {
14
14
  getActiveAccountId() {
15
- return getActiveAccountIdFromPath(appId);
15
+ return getStoredActiveAccountId(appId);
16
16
  },
17
- switchAccount(accountId, subPath = "") {
17
+ switchAccount(accountId) {
18
+ setStoredActiveAccountId(appId, accountId);
18
19
  if (typeof window === "undefined")
19
20
  return;
20
- const clean = subPath.replace(/^\/+/, "");
21
- window.location.assign(`/${accountId}${clean ? `/${clean}` : "/"}`);
21
+ window.location.reload();
22
+ },
23
+ clearActiveAccount() {
24
+ setStoredActiveAccountId(appId, null);
22
25
  },
23
26
  async listMine() {
24
27
  return axios.get(`${base}/me`);
@@ -4,8 +4,8 @@
4
4
  * An Account groups the app's end-users into an isolated tenant (a company,
5
5
  * team, or organization). Users join accounts via membership and act inside one
6
6
  * active account at a time. Account-scoped entities are transparently isolated
7
- * to the active account (carried by the `X-Active-Account-Id` header, derived
8
- * from the `/<account_id>/...` URL path).
7
+ * to the active account (carried by the `X-Active-Account-Id` header, read from
8
+ * stored client state in localStorage, keyed per app).
9
9
  */
10
10
  /** Account-management role. Distinct from the app's business roles. */
11
11
  export type AccountRole = "owner" | "admin" | "member";
@@ -61,15 +61,16 @@ export interface CheckoutSession {
61
61
  * Access via `base44.accounts`. Available when the app has multi-tenancy enabled.
62
62
  */
63
63
  export interface AccountsModule {
64
- /** The active account id, read from the current URL path (or `undefined`). */
64
+ /** The active account id, read from stored client state (or `undefined`). */
65
65
  getActiveAccountId(): string | undefined;
66
66
  /**
67
- * Switch the active account by navigating to its folder (`/<accountId>/...`).
68
- * A full navigation re-roots the app so all data follows the new account.
67
+ * Switch the active account by persisting it to stored client state and
68
+ * reloading the page so all data follows the new account.
69
69
  * @param accountId - The account to switch to.
70
- * @param subPath - Optional in-account route to land on (defaults to the root).
71
70
  */
72
- switchAccount(accountId: string, subPath?: string): void;
71
+ switchAccount(accountId: string): void;
72
+ /** Clear the stored active account (the backend falls back to the default). */
73
+ clearActiveAccount(): void;
73
74
  /** List the accounts the current user belongs to, plus the active one. */
74
75
  listMine(): Promise<MyAccountsResponse>;
75
76
  /** Create a new account; the current user becomes its owner. */
@@ -4,7 +4,7 @@
4
4
  * An Account groups the app's end-users into an isolated tenant (a company,
5
5
  * team, or organization). Users join accounts via membership and act inside one
6
6
  * active account at a time. Account-scoped entities are transparently isolated
7
- * to the active account (carried by the `X-Active-Account-Id` header, derived
8
- * from the `/<account_id>/...` URL path).
7
+ * to the active account (carried by the `X-Active-Account-Id` header, read from
8
+ * stored client state in localStorage, keyed per app).
9
9
  */
10
10
  export {};
@@ -1,5 +1,5 @@
1
1
  import axios from "axios";
2
- import { getActiveAccountIdFromPath, isInIFrame } from "./common.js";
2
+ import { getStoredActiveAccountId, isInIFrame } from "./common.js";
3
3
  import { v4 as uuidv4 } from "uuid";
4
4
  /**
5
5
  * Custom error class for Base44 SDK errors.
@@ -131,13 +131,13 @@ export function createAxiosClient({ baseURL, headers = {}, token, appId, interce
131
131
  client.interceptors.request.use((config) => {
132
132
  if (typeof window !== "undefined") {
133
133
  config.headers.set("X-Origin-URL", window.location.href);
134
- // Multi-tenancy: forward the active account (from the URL path) per request
135
- // so account-scoped reads/writes stay isolated to the current tenant even
136
- // after a client-side account switch. The path is the canonical source, so
137
- // it overrides any stale default header (e.g. one frozen at module load);
138
- // no-op for single-tenant apps (no account segment in the path). The app id
139
- // is passed so the sandbox base path (/<appId>/) is never read as an account.
140
- const activeAccountId = getActiveAccountIdFromPath(appId);
134
+ // Multi-tenancy: forward the active account from stored client state
135
+ // (localStorage, keyed per app) on every request so account-scoped
136
+ // reads/writes stay isolated to the current tenant. No-op when unset
137
+ // the backend then defaults to the user's sole active account.
138
+ const activeAccountId = appId
139
+ ? getStoredActiveAccountId(appId)
140
+ : undefined;
141
141
  if (activeAccountId) {
142
142
  config.headers.set("X-Active-Account-Id", activeAccountId);
143
143
  }
@@ -1,12 +1,19 @@
1
1
  export declare const isNode: boolean;
2
2
  export declare const isInIFrame: boolean;
3
3
  /**
4
- * The active account id from the URL, or undefined.
4
+ * The active account id from stored client state, or undefined.
5
5
  *
6
- * In the sandbox/preview the app is served under `/<appId>/` (the dev-server base
7
- * path), so the first segment is the app id its own base, NOT an account. When
8
- * `appId` is supplied and matches the leading segment, it's skipped so the app id
9
- * is never sent as an account id; the account, if any, is the next segment.
6
+ * Browser-only: reads `localStorage['base44:active_account:<appId>']` and returns
7
+ * it when it's a valid 24-hex account id, else undefined. Returns undefined in
8
+ * non-browser environments or if storage access throws.
10
9
  */
11
- export declare function getActiveAccountIdFromPath(appId?: string): string | undefined;
10
+ export declare function getStoredActiveAccountId(appId: string): string | undefined;
11
+ /**
12
+ * Persist (or clear) the active account id in stored client state.
13
+ *
14
+ * Browser-only: writes `localStorage['base44:active_account:<appId>']` when
15
+ * `accountId` is a valid 24-hex id, and removes the key when it is null or
16
+ * invalid. No-op in non-browser environments or if storage access throws.
17
+ */
18
+ export declare function setStoredActiveAccountId(appId: string, accountId: string | null): void;
12
19
  export declare const generateUuid: () => string;
@@ -1,24 +1,52 @@
1
1
  export const isNode = typeof window === "undefined";
2
2
  export const isInIFrame = !isNode && window.self !== window.top;
3
- // Multi-tenancy: apps are served under `/<account_id>/<route>` where the first
4
- // path segment is a 24-hex Mongo ObjectId. Read it at request time so the active
5
- // account is always current even after client-side (Link/useNavigate) account
6
- // switches that don't reload the module.
3
+ // Multi-tenancy: the active account is explicit client state, not the URL path.
4
+ // It is persisted in localStorage keyed per app (`base44:active_account:<appId>`)
5
+ // so it survives reloads and works under any base path (e.g. the sandbox/preview
6
+ // where the app is served under a non-account base path). When unset, no header
7
+ // is sent and the backend defaults to the user's sole active account.
7
8
  const ACCOUNT_ID_RE = /^[a-f0-9]{24}$/;
9
+ const activeAccountStorageKey = (appId) => `base44:active_account:${appId}`;
8
10
  /**
9
- * The active account id from the URL, or undefined.
11
+ * The active account id from stored client state, or undefined.
10
12
  *
11
- * In the sandbox/preview the app is served under `/<appId>/` (the dev-server base
12
- * path), so the first segment is the app id its own base, NOT an account. When
13
- * `appId` is supplied and matches the leading segment, it's skipped so the app id
14
- * is never sent as an account id; the account, if any, is the next segment.
13
+ * Browser-only: reads `localStorage['base44:active_account:<appId>']` and returns
14
+ * it when it's a valid 24-hex account id, else undefined. Returns undefined in
15
+ * non-browser environments or if storage access throws.
15
16
  */
16
- export function getActiveAccountIdFromPath(appId) {
17
+ export function getStoredActiveAccountId(appId) {
17
18
  if (isNode)
18
19
  return undefined;
19
- const segments = window.location.pathname.split("/").filter(Boolean);
20
- const candidate = appId && segments[0] === appId ? segments[1] : segments[0];
21
- return candidate && ACCOUNT_ID_RE.test(candidate) ? candidate : undefined;
20
+ try {
21
+ const stored = window.localStorage.getItem(activeAccountStorageKey(appId));
22
+ return stored && ACCOUNT_ID_RE.test(stored) ? stored : undefined;
23
+ }
24
+ catch (_a) {
25
+ return undefined;
26
+ }
27
+ }
28
+ /**
29
+ * Persist (or clear) the active account id in stored client state.
30
+ *
31
+ * Browser-only: writes `localStorage['base44:active_account:<appId>']` when
32
+ * `accountId` is a valid 24-hex id, and removes the key when it is null or
33
+ * invalid. No-op in non-browser environments or if storage access throws.
34
+ */
35
+ export function setStoredActiveAccountId(appId, accountId) {
36
+ if (isNode)
37
+ return;
38
+ try {
39
+ const key = activeAccountStorageKey(appId);
40
+ if (accountId && ACCOUNT_ID_RE.test(accountId)) {
41
+ window.localStorage.setItem(key, accountId);
42
+ }
43
+ else {
44
+ window.localStorage.removeItem(key);
45
+ }
46
+ }
47
+ catch (_a) {
48
+ /* storage unavailable — ignore */
49
+ }
22
50
  }
23
51
  export const generateUuid = () => {
24
52
  return (Math.random().toString(36).substring(2, 15) +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@base44-preview/sdk",
3
- "version": "0.8.31-pr.178.78bd45c",
3
+ "version": "0.8.31-pr.178.f25a7cd",
4
4
  "description": "JavaScript SDK for Base44 API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",