@base44-preview/sdk 0.8.31-pr.178.78bd45c → 0.8.31-pr.178.837440f
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/dist/modules/accounts.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getStoredActiveAccountId, setStoredActiveAccountId, } from "../utils/common.js";
|
|
2
2
|
/**
|
|
3
3
|
* Creates the accounts module (multi-tenancy) for the Base44 SDK.
|
|
4
4
|
*
|
|
@@ -10,15 +10,34 @@ import { getActiveAccountIdFromPath } from "../utils/common.js";
|
|
|
10
10
|
export function createAccountsModule(axios, appId) {
|
|
11
11
|
const base = `/apps/${appId}/accounts`;
|
|
12
12
|
const enc = encodeURIComponent;
|
|
13
|
+
// Resolve the account id to operate on: an explicit id wins, then the
|
|
14
|
+
// explicitly-stored client selection, then the server-resolved default
|
|
15
|
+
// (the sole-account case). Throws a clear error when none can be found so
|
|
16
|
+
// callers never silently send `/accounts/undefined/...` (which 404s as
|
|
17
|
+
// "Account not found").
|
|
18
|
+
const resolveAccountId = async (provided) => {
|
|
19
|
+
if (provided)
|
|
20
|
+
return provided;
|
|
21
|
+
const stored = getStoredActiveAccountId(appId);
|
|
22
|
+
if (stored)
|
|
23
|
+
return stored;
|
|
24
|
+
const mine = await axios.get(`${base}/me`);
|
|
25
|
+
if (mine.active_account_id)
|
|
26
|
+
return mine.active_account_id;
|
|
27
|
+
throw new Error("No active account: pass an accountId, or have the user select or create an account first.");
|
|
28
|
+
};
|
|
13
29
|
return {
|
|
14
30
|
getActiveAccountId() {
|
|
15
|
-
return
|
|
31
|
+
return getStoredActiveAccountId(appId);
|
|
16
32
|
},
|
|
17
|
-
switchAccount(accountId
|
|
33
|
+
switchAccount(accountId) {
|
|
34
|
+
setStoredActiveAccountId(appId, accountId);
|
|
18
35
|
if (typeof window === "undefined")
|
|
19
36
|
return;
|
|
20
|
-
|
|
21
|
-
|
|
37
|
+
window.location.reload();
|
|
38
|
+
},
|
|
39
|
+
clearActiveAccount() {
|
|
40
|
+
setStoredActiveAccountId(appId, null);
|
|
22
41
|
},
|
|
23
42
|
async listMine() {
|
|
24
43
|
return axios.get(`${base}/me`);
|
|
@@ -30,7 +49,8 @@ export function createAccountsModule(axios, appId) {
|
|
|
30
49
|
return axios.patch(`${base}/${accountId}`, params);
|
|
31
50
|
},
|
|
32
51
|
async listMembers(accountId) {
|
|
33
|
-
|
|
52
|
+
const id = await resolveAccountId(accountId);
|
|
53
|
+
return axios.get(`${base}/${id}/members`);
|
|
34
54
|
},
|
|
35
55
|
async invite(accountId, email, role = "member") {
|
|
36
56
|
return axios.post(`${base}/${accountId}/invites`, { email, role });
|
|
@@ -51,10 +71,35 @@ export function createAccountsModule(axios, appId) {
|
|
|
51
71
|
},
|
|
52
72
|
billing: {
|
|
53
73
|
async listPlans(accountId) {
|
|
54
|
-
|
|
74
|
+
const id = await resolveAccountId(accountId);
|
|
75
|
+
return axios.get(`${base}/${id}/billing/plans`);
|
|
76
|
+
},
|
|
77
|
+
async getSubscription(accountId) {
|
|
78
|
+
var _a, _b, _c, _d, _e, _f;
|
|
79
|
+
// /me is needed for the account's plan_id/billing_status, and also
|
|
80
|
+
// resolves the active account id — fetch it once and reuse it.
|
|
81
|
+
const mine = await axios.get(`${base}/me`);
|
|
82
|
+
const id = (_b = (_a = accountId !== null && accountId !== void 0 ? accountId : getStoredActiveAccountId(appId)) !== null && _a !== void 0 ? _a : mine.active_account_id) !== null && _b !== void 0 ? _b : undefined;
|
|
83
|
+
if (!id) {
|
|
84
|
+
throw new Error("No active account: pass an accountId, or have the user select or create an account first.");
|
|
85
|
+
}
|
|
86
|
+
const plans = await axios.get(`${base}/${id}/billing/plans`);
|
|
87
|
+
const account = (_c = mine.accounts.find((a) => a.id === id)) !== null && _c !== void 0 ? _c : null;
|
|
88
|
+
const planId = (_d = account === null || account === void 0 ? void 0 : account.plan_id) !== null && _d !== void 0 ? _d : null;
|
|
89
|
+
return {
|
|
90
|
+
account_id: id,
|
|
91
|
+
plan_id: planId,
|
|
92
|
+
billing_status: (_e = account === null || account === void 0 ? void 0 : account.billing_status) !== null && _e !== void 0 ? _e : "none",
|
|
93
|
+
plan: planId ? (_f = plans.find((p) => p.id === planId)) !== null && _f !== void 0 ? _f : null : null,
|
|
94
|
+
};
|
|
55
95
|
},
|
|
56
|
-
async startCheckout(
|
|
57
|
-
|
|
96
|
+
async startCheckout(accountIdOrParams, maybeParams) {
|
|
97
|
+
const explicitId = typeof accountIdOrParams === "string" ? accountIdOrParams : undefined;
|
|
98
|
+
const params = typeof accountIdOrParams === "string"
|
|
99
|
+
? maybeParams
|
|
100
|
+
: accountIdOrParams;
|
|
101
|
+
const id = await resolveAccountId(explicitId);
|
|
102
|
+
return axios.post(`${base}/${id}/billing/checkout`, params);
|
|
58
103
|
},
|
|
59
104
|
},
|
|
60
105
|
};
|
|
@@ -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,
|
|
8
|
-
*
|
|
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";
|
|
@@ -55,21 +55,38 @@ export interface CheckoutSession {
|
|
|
55
55
|
url: string;
|
|
56
56
|
session_id: string;
|
|
57
57
|
}
|
|
58
|
+
/** Parameters for starting a subscription checkout. */
|
|
59
|
+
export interface CheckoutParams {
|
|
60
|
+
plan_id: string;
|
|
61
|
+
success_url: string;
|
|
62
|
+
cancel_url: string;
|
|
63
|
+
}
|
|
64
|
+
/** The current subscription state of an account. */
|
|
65
|
+
export interface AccountSubscription {
|
|
66
|
+
account_id: string;
|
|
67
|
+
/** The active plan id, or `null` when the account has no subscription. */
|
|
68
|
+
plan_id: string | null;
|
|
69
|
+
/** Lifecycle status: "none" | "active" | "past_due" | "canceled". */
|
|
70
|
+
billing_status: string;
|
|
71
|
+
/** The resolved plan (matched from the account's available plans), or `null`. */
|
|
72
|
+
plan: AccountPlan | null;
|
|
73
|
+
}
|
|
58
74
|
/**
|
|
59
75
|
* The accounts module — manage multi-tenancy ("Accounts") from inside the app.
|
|
60
76
|
*
|
|
61
77
|
* Access via `base44.accounts`. Available when the app has multi-tenancy enabled.
|
|
62
78
|
*/
|
|
63
79
|
export interface AccountsModule {
|
|
64
|
-
/** The active account id, read from
|
|
80
|
+
/** The active account id, read from stored client state (or `undefined`). */
|
|
65
81
|
getActiveAccountId(): string | undefined;
|
|
66
82
|
/**
|
|
67
|
-
* Switch the active account by
|
|
68
|
-
*
|
|
83
|
+
* Switch the active account by persisting it to stored client state and
|
|
84
|
+
* reloading the page so all data follows the new account.
|
|
69
85
|
* @param accountId - The account to switch to.
|
|
70
|
-
* @param subPath - Optional in-account route to land on (defaults to the root).
|
|
71
86
|
*/
|
|
72
|
-
switchAccount(accountId: string
|
|
87
|
+
switchAccount(accountId: string): void;
|
|
88
|
+
/** Clear the stored active account (the backend falls back to the default). */
|
|
89
|
+
clearActiveAccount(): void;
|
|
73
90
|
/** List the accounts the current user belongs to, plus the active one. */
|
|
74
91
|
listMine(): Promise<MyAccountsResponse>;
|
|
75
92
|
/** Create a new account; the current user becomes its owner. */
|
|
@@ -82,8 +99,11 @@ export interface AccountsModule {
|
|
|
82
99
|
name?: string;
|
|
83
100
|
data?: Record<string, unknown>;
|
|
84
101
|
}): Promise<Account>;
|
|
85
|
-
/**
|
|
86
|
-
|
|
102
|
+
/**
|
|
103
|
+
* List an account's members (any active member).
|
|
104
|
+
* @param accountId - Defaults to the active account when omitted.
|
|
105
|
+
*/
|
|
106
|
+
listMembers(accountId?: string): Promise<AccountMembership[]>;
|
|
87
107
|
/** Invite a user by email to an account (managers only). */
|
|
88
108
|
invite(accountId: string, email: string, role?: AssignableAccountRole): Promise<AccountMembership>;
|
|
89
109
|
/** Accept a pending invite to an account for the current user. */
|
|
@@ -100,13 +120,21 @@ export interface AccountsModule {
|
|
|
100
120
|
}>;
|
|
101
121
|
/** Per-account billing. */
|
|
102
122
|
billing: {
|
|
103
|
-
/**
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
123
|
+
/**
|
|
124
|
+
* List the active plans available to an account.
|
|
125
|
+
* @param accountId - Defaults to the active account when omitted.
|
|
126
|
+
*/
|
|
127
|
+
listPlans(accountId?: string): Promise<AccountPlan[]>;
|
|
128
|
+
/**
|
|
129
|
+
* Get the current subscription state (plan + status) of an account.
|
|
130
|
+
* @param accountId - Defaults to the active account when omitted.
|
|
131
|
+
*/
|
|
132
|
+
getSubscription(accountId?: string): Promise<AccountSubscription>;
|
|
133
|
+
/**
|
|
134
|
+
* Start a subscription checkout session for a plan, then redirect the
|
|
135
|
+
* browser to the returned `url`. The account defaults to the active one.
|
|
136
|
+
*/
|
|
137
|
+
startCheckout(params: CheckoutParams): Promise<CheckoutSession>;
|
|
138
|
+
startCheckout(accountId: string, params: CheckoutParams): Promise<CheckoutSession>;
|
|
111
139
|
};
|
|
112
140
|
}
|
|
@@ -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,
|
|
8
|
-
*
|
|
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 {
|
|
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
|
|
135
|
-
//
|
|
136
|
-
//
|
|
137
|
-
//
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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
|
}
|
package/dist/utils/common.d.ts
CHANGED
|
@@ -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
|
|
4
|
+
* The active account id from stored client state, or undefined.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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
|
|
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;
|
package/dist/utils/common.js
CHANGED
|
@@ -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:
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
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
|
|
11
|
+
* The active account id from stored client state, or undefined.
|
|
10
12
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
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
|
|
17
|
+
export function getStoredActiveAccountId(appId) {
|
|
17
18
|
if (isNode)
|
|
18
19
|
return undefined;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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) +
|