@base44-preview/sdk 0.8.30-pr.160.b403af6 → 0.8.31-pr.178.4dde9c5
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/client.js +6 -0
- package/dist/client.types.d.ts +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/modules/accounts.d.ts +11 -0
- package/dist/modules/accounts.js +100 -0
- package/dist/modules/accounts.types.d.ts +181 -0
- package/dist/modules/accounts.types.js +10 -0
- package/dist/modules/connectors.js +15 -16
- package/dist/modules/connectors.types.d.ts +7 -9
- package/dist/utils/axios-client.d.ts +2 -1
- package/dist/utils/axios-client.js +12 -2
- package/dist/utils/common.d.ts +16 -0
- package/dist/utils/common.js +48 -0
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -9,6 +9,7 @@ import { createFunctionsModule } from "./modules/functions.js";
|
|
|
9
9
|
import { createAgentsModule } from "./modules/agents.js";
|
|
10
10
|
import { createAppLogsModule } from "./modules/app-logs.js";
|
|
11
11
|
import { createUsersModule } from "./modules/users.js";
|
|
12
|
+
import { createAccountsModule } from "./modules/accounts.js";
|
|
12
13
|
import { RoomsSocket } from "./utils/socket-utils.js";
|
|
13
14
|
import { createAnalyticsModule } from "./modules/analytics.js";
|
|
14
15
|
/**
|
|
@@ -83,12 +84,14 @@ export function createClient(config) {
|
|
|
83
84
|
baseURL: `${serverUrl}/api`,
|
|
84
85
|
headers,
|
|
85
86
|
token,
|
|
87
|
+
appId: String(appId),
|
|
86
88
|
onError: options === null || options === void 0 ? void 0 : options.onError,
|
|
87
89
|
});
|
|
88
90
|
const functionsAxiosClient = createAxiosClient({
|
|
89
91
|
baseURL: `${serverUrl}/api`,
|
|
90
92
|
headers: functionHeaders,
|
|
91
93
|
token,
|
|
94
|
+
appId: String(appId),
|
|
92
95
|
interceptResponses: false,
|
|
93
96
|
onError: options === null || options === void 0 ? void 0 : options.onError,
|
|
94
97
|
});
|
|
@@ -100,12 +103,14 @@ export function createClient(config) {
|
|
|
100
103
|
baseURL: `${serverUrl}/api`,
|
|
101
104
|
headers: serviceRoleHeaders,
|
|
102
105
|
token: serviceToken,
|
|
106
|
+
appId: String(appId),
|
|
103
107
|
onError: options === null || options === void 0 ? void 0 : options.onError,
|
|
104
108
|
});
|
|
105
109
|
const serviceRoleFunctionsAxiosClient = createAxiosClient({
|
|
106
110
|
baseURL: `${serverUrl}/api`,
|
|
107
111
|
headers: functionHeaders,
|
|
108
112
|
token: serviceToken,
|
|
113
|
+
appId: String(appId),
|
|
109
114
|
interceptResponses: false,
|
|
110
115
|
});
|
|
111
116
|
const userAuthModule = createAuthModule(axiosClient, functionsAxiosClient, appId, {
|
|
@@ -152,6 +157,7 @@ export function createClient(config) {
|
|
|
152
157
|
}),
|
|
153
158
|
appLogs: createAppLogsModule(axiosClient, appId),
|
|
154
159
|
users: createUsersModule(axiosClient, appId),
|
|
160
|
+
accounts: createAccountsModule(axiosClient, appId),
|
|
155
161
|
analytics: createAnalyticsModule({
|
|
156
162
|
axiosClient,
|
|
157
163
|
serverUrl,
|
package/dist/client.types.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type { FunctionsModule } from "./modules/functions.types.js";
|
|
|
7
7
|
import type { AgentsModule } from "./modules/agents.types.js";
|
|
8
8
|
import type { AppLogsModule } from "./modules/app-logs.types.js";
|
|
9
9
|
import type { AnalyticsModule } from "./modules/analytics.types.js";
|
|
10
|
+
import type { AccountsModule } from "./modules/accounts.types.js";
|
|
10
11
|
/**
|
|
11
12
|
* Options for creating a Base44 client.
|
|
12
13
|
*/
|
|
@@ -79,6 +80,8 @@ export interface CreateClientConfig {
|
|
|
79
80
|
* Provides access to all SDK modules for interacting with the app.
|
|
80
81
|
*/
|
|
81
82
|
export interface Base44Client {
|
|
83
|
+
/** {@link AccountsModule | Accounts module} for multi-tenancy (accounts, members, billing). */
|
|
84
|
+
accounts: AccountsModule;
|
|
82
85
|
/** {@link AgentsModule | Agents module} for managing AI agent conversations. */
|
|
83
86
|
agents: AgentsModule;
|
|
84
87
|
/** {@link AnalyticsModule | Analytics module} for tracking custom events in your app. */
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export type { IntegrationsModule, IntegrationEndpointFunction, CoreIntegrations,
|
|
|
10
10
|
export type { FunctionsModule, FunctionName, FunctionNameRegistry, } from "./modules/functions.types.js";
|
|
11
11
|
export type { AgentsModule, AgentName, AgentNameRegistry, AgentConversation, AgentMessage, AgentMessageReasoning, AgentMessageToolCall, AgentMessageUsage, AgentMessageCustomContext, AgentMessageMetadata, CreateConversationParams, } from "./modules/agents.types.js";
|
|
12
12
|
export type { AppLogsModule } from "./modules/app-logs.types.js";
|
|
13
|
+
export type { AccountsModule, Account, AccountMembership, AccountPlan, AccountRole, AssignableAccountRole, AccountStatus, AccountMembershipStatus, MyAccountsResponse, CheckoutSession, } from "./modules/accounts.types.js";
|
|
13
14
|
export type { SsoModule, SsoAccessTokenResponse } from "./modules/sso.types.js";
|
|
14
15
|
export type { ConnectorsModule, UserConnectorsModule, } from "./modules/connectors.types.js";
|
|
15
16
|
export type { CustomIntegrationsModule, CustomIntegrationCallParams, CustomIntegrationCallResponse, } from "./modules/custom-integrations.types.js";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AxiosInstance } from "axios";
|
|
2
|
+
import type { AccountsModule } from "./accounts.types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Creates the accounts module (multi-tenancy) for the Base44 SDK.
|
|
5
|
+
*
|
|
6
|
+
* @param axios - Axios instance (responses are unwrapped to data).
|
|
7
|
+
* @param appId - Application ID.
|
|
8
|
+
* @returns The accounts module.
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export declare function createAccountsModule(axios: AxiosInstance, appId: string): AccountsModule;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { getStoredActiveAccountId, setStoredActiveAccountId, } from "../utils/common.js";
|
|
2
|
+
/**
|
|
3
|
+
* Creates the accounts module (multi-tenancy) for the Base44 SDK.
|
|
4
|
+
*
|
|
5
|
+
* @param axios - Axios instance (responses are unwrapped to data).
|
|
6
|
+
* @param appId - Application ID.
|
|
7
|
+
* @returns The accounts module.
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export function createAccountsModule(axios, appId) {
|
|
11
|
+
const base = `/apps/${appId}/accounts`;
|
|
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
|
+
};
|
|
29
|
+
return {
|
|
30
|
+
getActiveAccountId() {
|
|
31
|
+
return getStoredActiveAccountId(appId);
|
|
32
|
+
},
|
|
33
|
+
switchAccount(accountId) {
|
|
34
|
+
setStoredActiveAccountId(appId, accountId);
|
|
35
|
+
if (typeof window === "undefined")
|
|
36
|
+
return;
|
|
37
|
+
window.location.reload();
|
|
38
|
+
},
|
|
39
|
+
setActiveAccount(accountId) {
|
|
40
|
+
setStoredActiveAccountId(appId, accountId);
|
|
41
|
+
},
|
|
42
|
+
clearActiveAccount() {
|
|
43
|
+
setStoredActiveAccountId(appId, null);
|
|
44
|
+
},
|
|
45
|
+
async listMine() {
|
|
46
|
+
return axios.get(`${base}/me`);
|
|
47
|
+
},
|
|
48
|
+
async getPublicAccount(slug) {
|
|
49
|
+
return axios.get(`${base}/public/by-slug/${enc(slug)}`);
|
|
50
|
+
},
|
|
51
|
+
async joinAccount(slug) {
|
|
52
|
+
return axios.post(`${base}/by-slug/${enc(slug)}/join`, {});
|
|
53
|
+
},
|
|
54
|
+
async create(params) {
|
|
55
|
+
return axios.post(base, params);
|
|
56
|
+
},
|
|
57
|
+
async update(accountId, params) {
|
|
58
|
+
return axios.patch(`${base}/${accountId}`, params);
|
|
59
|
+
},
|
|
60
|
+
async listMembers(accountId) {
|
|
61
|
+
const id = await resolveAccountId(accountId);
|
|
62
|
+
return axios.get(`${base}/${id}/members`);
|
|
63
|
+
},
|
|
64
|
+
async invite(accountId, email, role = "member") {
|
|
65
|
+
return axios.post(`${base}/${accountId}/invites`, { email, role });
|
|
66
|
+
},
|
|
67
|
+
async acceptInvite(accountId) {
|
|
68
|
+
return axios.post(`${base}/${accountId}/accept`, {});
|
|
69
|
+
},
|
|
70
|
+
async changeMemberRole(accountId, email, role) {
|
|
71
|
+
return axios.patch(`${base}/${accountId}/members/${enc(email)}/role`, {
|
|
72
|
+
role,
|
|
73
|
+
});
|
|
74
|
+
},
|
|
75
|
+
async removeMember(accountId, email) {
|
|
76
|
+
return axios.delete(`${base}/${accountId}/members/${enc(email)}`);
|
|
77
|
+
},
|
|
78
|
+
async transferOwnership(accountId, email) {
|
|
79
|
+
return axios.post(`${base}/${accountId}/transfer-ownership`, { email });
|
|
80
|
+
},
|
|
81
|
+
billing: {
|
|
82
|
+
async listPlans(accountId) {
|
|
83
|
+
const id = await resolveAccountId(accountId);
|
|
84
|
+
return axios.get(`${base}/${id}/billing/plans`);
|
|
85
|
+
},
|
|
86
|
+
async getSubscription(accountId) {
|
|
87
|
+
const id = await resolveAccountId(accountId);
|
|
88
|
+
return axios.get(`${base}/${id}/billing/subscription`);
|
|
89
|
+
},
|
|
90
|
+
async startCheckout(accountIdOrParams, maybeParams) {
|
|
91
|
+
const explicitId = typeof accountIdOrParams === "string" ? accountIdOrParams : undefined;
|
|
92
|
+
const params = typeof accountIdOrParams === "string"
|
|
93
|
+
? maybeParams
|
|
94
|
+
: accountIdOrParams;
|
|
95
|
+
const id = await resolveAccountId(explicitId);
|
|
96
|
+
return axios.post(`${base}/${id}/billing/checkout`, params);
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the {@link AccountsModule | accounts} module (multi-tenancy).
|
|
3
|
+
*
|
|
4
|
+
* An Account groups the app's end-users into an isolated tenant (a company,
|
|
5
|
+
* team, or organization). Users join accounts via membership and act inside one
|
|
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, read from
|
|
8
|
+
* stored client state in localStorage, keyed per app).
|
|
9
|
+
*/
|
|
10
|
+
/** Account-management role. Distinct from the app's business roles. */
|
|
11
|
+
export type AccountRole = "owner" | "admin" | "member";
|
|
12
|
+
/** Assignable (non-owner) role used for invites/role changes. */
|
|
13
|
+
export type AssignableAccountRole = "admin" | "member";
|
|
14
|
+
export type AccountStatus = "active" | "suspended";
|
|
15
|
+
export type AccountMembershipStatus = "pending" | "active";
|
|
16
|
+
/** An account (tenant) within the app. */
|
|
17
|
+
export interface Account {
|
|
18
|
+
id: string;
|
|
19
|
+
app_id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
status: AccountStatus;
|
|
22
|
+
plan_id?: string | null;
|
|
23
|
+
billing_status?: string;
|
|
24
|
+
/** The current user's role in this account (present on `listMine()` results). */
|
|
25
|
+
my_role?: AccountRole;
|
|
26
|
+
/** Builder-defined custom fields. */
|
|
27
|
+
data?: Record<string, unknown>;
|
|
28
|
+
created_date?: string;
|
|
29
|
+
}
|
|
30
|
+
/** The accounts the current user belongs to, plus the active one. */
|
|
31
|
+
export interface MyAccountsResponse {
|
|
32
|
+
accounts: Account[];
|
|
33
|
+
active_account_id: string | null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Public, unauthenticated view of an account (its landing page), resolved by
|
|
37
|
+
* slug. Carries identity plus only the builder-designated public custom fields.
|
|
38
|
+
*/
|
|
39
|
+
export interface PublicAccount {
|
|
40
|
+
id: string;
|
|
41
|
+
name: string;
|
|
42
|
+
slug: string | null;
|
|
43
|
+
/** Builder-flagged public companion fields (e.g. logo, tagline). */
|
|
44
|
+
data: Record<string, unknown>;
|
|
45
|
+
}
|
|
46
|
+
/** A user's membership in an account. */
|
|
47
|
+
export interface AccountMembership {
|
|
48
|
+
id: string;
|
|
49
|
+
account_id: string;
|
|
50
|
+
email: string;
|
|
51
|
+
role: AccountRole;
|
|
52
|
+
status: AccountMembershipStatus;
|
|
53
|
+
}
|
|
54
|
+
/** A subscription plan/tier offered to accounts. */
|
|
55
|
+
export interface AccountPlan {
|
|
56
|
+
id: string;
|
|
57
|
+
name: string;
|
|
58
|
+
description?: string | null;
|
|
59
|
+
price_amount: number;
|
|
60
|
+
currency: string;
|
|
61
|
+
interval: "month" | "year";
|
|
62
|
+
is_active: boolean;
|
|
63
|
+
}
|
|
64
|
+
/** A provider checkout session. */
|
|
65
|
+
export interface CheckoutSession {
|
|
66
|
+
url: string;
|
|
67
|
+
session_id: string;
|
|
68
|
+
}
|
|
69
|
+
/** Parameters for starting a subscription checkout. */
|
|
70
|
+
export interface CheckoutParams {
|
|
71
|
+
plan_id: string;
|
|
72
|
+
success_url: string;
|
|
73
|
+
cancel_url: string;
|
|
74
|
+
}
|
|
75
|
+
/** The current subscription state of an account. */
|
|
76
|
+
export interface AccountSubscription {
|
|
77
|
+
account_id: string;
|
|
78
|
+
/** The active plan id, or `null` when the account has no subscription. */
|
|
79
|
+
plan_id: string | null;
|
|
80
|
+
/** Lifecycle status: "none" | "active" | "past_due" | "canceled". */
|
|
81
|
+
billing_status: string;
|
|
82
|
+
/** The payment rail backing the subscription, or `null`. */
|
|
83
|
+
billing_provider: string | null;
|
|
84
|
+
/** The current plan, or `null` when the account has no subscription. */
|
|
85
|
+
plan: AccountPlan | null;
|
|
86
|
+
/** When the current paid period ends / renews (ISO 8601), or `null`. */
|
|
87
|
+
current_period_end: string | null;
|
|
88
|
+
/** True when the subscription will not renew at period end. */
|
|
89
|
+
cancel_at_period_end: boolean;
|
|
90
|
+
/** When the subscription was canceled (ISO 8601), or `null`. */
|
|
91
|
+
canceled_at: string | null;
|
|
92
|
+
/** When the subscription started (ISO 8601), or `null`. */
|
|
93
|
+
started_at: string | null;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The accounts module — manage multi-tenancy ("Accounts") from inside the app.
|
|
97
|
+
*
|
|
98
|
+
* Access via `base44.accounts`. Available when the app has multi-tenancy enabled.
|
|
99
|
+
*/
|
|
100
|
+
export interface AccountsModule {
|
|
101
|
+
/** The active account id, read from stored client state (or `undefined`). */
|
|
102
|
+
getActiveAccountId(): string | undefined;
|
|
103
|
+
/**
|
|
104
|
+
* Switch the active account by persisting it to stored client state and
|
|
105
|
+
* reloading the page so all data follows the new account.
|
|
106
|
+
* @param accountId - The account to switch to.
|
|
107
|
+
*/
|
|
108
|
+
switchAccount(accountId: string): void;
|
|
109
|
+
/**
|
|
110
|
+
* Persist the active account WITHOUT reloading the page.
|
|
111
|
+
*
|
|
112
|
+
* Use on the public landing page to select the account before redirecting to
|
|
113
|
+
* login, so the app resolves that account after the visitor returns. For
|
|
114
|
+
* switching accounts inside the running app, use {@link switchAccount} (which
|
|
115
|
+
* reloads so all data follows the new account).
|
|
116
|
+
*/
|
|
117
|
+
setActiveAccount(accountId: string): void;
|
|
118
|
+
/** Clear the stored active account (the backend falls back to the default). */
|
|
119
|
+
clearActiveAccount(): void;
|
|
120
|
+
/** List the accounts the current user belongs to, plus the active one. */
|
|
121
|
+
listMine(): Promise<MyAccountsResponse>;
|
|
122
|
+
/**
|
|
123
|
+
* Resolve a public account by its slug (unauthenticated) for its landing page.
|
|
124
|
+
* @param slug - The account's URL slug.
|
|
125
|
+
*/
|
|
126
|
+
getPublicAccount(slug: string): Promise<PublicAccount>;
|
|
127
|
+
/**
|
|
128
|
+
* Self-join an account by slug (the current user becomes a member). Requires
|
|
129
|
+
* login and that the app enables public joining; otherwise rejects.
|
|
130
|
+
* @param slug - The account's URL slug.
|
|
131
|
+
*/
|
|
132
|
+
joinAccount(slug: string): Promise<AccountMembership>;
|
|
133
|
+
/** Create a new account; the current user becomes its owner. */
|
|
134
|
+
create(params: {
|
|
135
|
+
name: string;
|
|
136
|
+
data?: Record<string, unknown>;
|
|
137
|
+
}): Promise<Account>;
|
|
138
|
+
/** Rename and/or update an account's custom fields (managers only). */
|
|
139
|
+
update(accountId: string, params: {
|
|
140
|
+
name?: string;
|
|
141
|
+
data?: Record<string, unknown>;
|
|
142
|
+
}): Promise<Account>;
|
|
143
|
+
/**
|
|
144
|
+
* List an account's members (any active member).
|
|
145
|
+
* @param accountId - Defaults to the active account when omitted.
|
|
146
|
+
*/
|
|
147
|
+
listMembers(accountId?: string): Promise<AccountMembership[]>;
|
|
148
|
+
/** Invite a user by email to an account (managers only). */
|
|
149
|
+
invite(accountId: string, email: string, role?: AssignableAccountRole): Promise<AccountMembership>;
|
|
150
|
+
/** Accept a pending invite to an account for the current user. */
|
|
151
|
+
acceptInvite(accountId: string): Promise<AccountMembership>;
|
|
152
|
+
/** Change a member's role (managers only; not for the owner). */
|
|
153
|
+
changeMemberRole(accountId: string, email: string, role: AssignableAccountRole): Promise<AccountMembership>;
|
|
154
|
+
/** Remove a member from an account (managers only; not the owner). */
|
|
155
|
+
removeMember(accountId: string, email: string): Promise<{
|
|
156
|
+
removed: boolean;
|
|
157
|
+
}>;
|
|
158
|
+
/** Transfer ownership to another active member (owner only). */
|
|
159
|
+
transferOwnership(accountId: string, email: string): Promise<{
|
|
160
|
+
transferred: boolean;
|
|
161
|
+
}>;
|
|
162
|
+
/** Per-account billing. */
|
|
163
|
+
billing: {
|
|
164
|
+
/**
|
|
165
|
+
* List the active plans available to an account.
|
|
166
|
+
* @param accountId - Defaults to the active account when omitted.
|
|
167
|
+
*/
|
|
168
|
+
listPlans(accountId?: string): Promise<AccountPlan[]>;
|
|
169
|
+
/**
|
|
170
|
+
* Get the current subscription state (plan + status) of an account.
|
|
171
|
+
* @param accountId - Defaults to the active account when omitted.
|
|
172
|
+
*/
|
|
173
|
+
getSubscription(accountId?: string): Promise<AccountSubscription>;
|
|
174
|
+
/**
|
|
175
|
+
* Start a subscription checkout session for a plan, then redirect the
|
|
176
|
+
* browser to the returned `url`. The account defaults to the active one.
|
|
177
|
+
*/
|
|
178
|
+
startCheckout(params: CheckoutParams): Promise<CheckoutSession>;
|
|
179
|
+
startCheckout(accountId: string, params: CheckoutParams): Promise<CheckoutSession>;
|
|
180
|
+
};
|
|
181
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the {@link AccountsModule | accounts} module (multi-tenancy).
|
|
3
|
+
*
|
|
4
|
+
* An Account groups the app's end-users into an isolated tenant (a company,
|
|
5
|
+
* team, or organization). Users join accounts via membership and act inside one
|
|
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, read from
|
|
8
|
+
* stored client state in localStorage, keyed per app).
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
@@ -21,25 +21,24 @@ export function createConnectorsModule(axios, appId) {
|
|
|
21
21
|
// @ts-expect-error
|
|
22
22
|
return response.access_token;
|
|
23
23
|
},
|
|
24
|
-
async getConnection(
|
|
24
|
+
async getConnection(integrationType) {
|
|
25
25
|
var _a;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (!arg) {
|
|
29
|
-
throw new Error("Integration type is required and must be a string");
|
|
30
|
-
}
|
|
31
|
-
url = `/apps/${appId}/external-auth/tokens/${arg}`;
|
|
32
|
-
}
|
|
33
|
-
else if (arg && typeof arg === "object" && typeof arg.connectorId === "string") {
|
|
34
|
-
if (!arg.connectorId) {
|
|
35
|
-
throw new Error("Connector ID is required and must be a string");
|
|
36
|
-
}
|
|
37
|
-
url = `/apps/${appId}/external-auth/tokens/by-connector/${arg.connectorId}`;
|
|
26
|
+
if (!integrationType || typeof integrationType !== "string") {
|
|
27
|
+
throw new Error("Integration type is required and must be a string");
|
|
38
28
|
}
|
|
39
|
-
|
|
40
|
-
|
|
29
|
+
const response = await axios.get(`/apps/${appId}/external-auth/tokens/${integrationType}`);
|
|
30
|
+
const data = response;
|
|
31
|
+
return {
|
|
32
|
+
accessToken: data.access_token,
|
|
33
|
+
connectionConfig: (_a = data.connection_config) !== null && _a !== void 0 ? _a : null,
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
async getWorkspaceConnection(connectorId) {
|
|
37
|
+
var _a;
|
|
38
|
+
if (!connectorId || typeof connectorId !== "string") {
|
|
39
|
+
throw new Error("Connector ID is required and must be a string");
|
|
41
40
|
}
|
|
42
|
-
const response = await axios.get(
|
|
41
|
+
const response = await axios.get(`/apps/${appId}/external-auth/tokens/connectors/${connectorId}`);
|
|
43
42
|
const data = response;
|
|
44
43
|
return {
|
|
45
44
|
accessToken: data.access_token,
|
|
@@ -255,30 +255,28 @@ export interface ConnectorsModule {
|
|
|
255
255
|
* Retrieves the OAuth access token and connection configuration for a **workspace-registered** connector
|
|
256
256
|
* (a connector backed by an OAuth app registered in the workspace, consented to once by the app builder).
|
|
257
257
|
*
|
|
258
|
-
* Use this
|
|
258
|
+
* Use this method when the app's backend function needs to use a connector identified by its
|
|
259
259
|
* workspace-connector ID rather than a platform integration type. The token returned represents
|
|
260
260
|
* the app builder's consent against the workspace's OAuth app and is shared across all app users
|
|
261
|
-
* of the app — identical semantics to the platform-shared
|
|
261
|
+
* of the app — identical semantics to the platform-shared {@link getConnection} form,
|
|
262
262
|
* differing only in which OAuth app was used to produce the token.
|
|
263
263
|
*
|
|
264
|
-
* @param
|
|
264
|
+
* @param connectorId - The ID of the workspace connector (the `OrganizationConnector` database ID) as surfaced in the builder chat context.
|
|
265
265
|
* @returns Promise resolving to a {@link ConnectorConnectionResponse} with `accessToken` and `connectionConfig`.
|
|
266
266
|
*
|
|
267
267
|
* @example
|
|
268
268
|
* ```typescript
|
|
269
269
|
* // Get the connection for a workspace-registered connector
|
|
270
|
-
* const { accessToken, connectionConfig } = await base44.asServiceRole.connectors.
|
|
271
|
-
*
|
|
272
|
-
*
|
|
270
|
+
* const { accessToken, connectionConfig } = await base44.asServiceRole.connectors.getWorkspaceConnection(
|
|
271
|
+
* 'abc123def',
|
|
272
|
+
* );
|
|
273
273
|
*
|
|
274
274
|
* const response = await fetch(`https://${connectionConfig?.subdomain}.snowflakecomputing.com/api/v2/statements`, {
|
|
275
275
|
* headers: { Authorization: `Bearer ${accessToken}` },
|
|
276
276
|
* });
|
|
277
277
|
* ```
|
|
278
278
|
*/
|
|
279
|
-
|
|
280
|
-
connectorId: string;
|
|
281
|
-
}): Promise<ConnectorConnectionResponse>;
|
|
279
|
+
getWorkspaceConnection(connectorId: string): Promise<ConnectorConnectionResponse>;
|
|
282
280
|
/**
|
|
283
281
|
* @internal
|
|
284
282
|
* @deprecated Use {@link getCurrentAppUserConnection} instead.
|
|
@@ -90,10 +90,11 @@ export declare class Base44Error extends Error {
|
|
|
90
90
|
* @returns Configured axios instance
|
|
91
91
|
* @internal
|
|
92
92
|
*/
|
|
93
|
-
export declare function createAxiosClient({ baseURL, headers, token, interceptResponses, onError, }: {
|
|
93
|
+
export declare function createAxiosClient({ baseURL, headers, token, appId, interceptResponses, onError, }: {
|
|
94
94
|
baseURL: string;
|
|
95
95
|
headers?: Record<string, string>;
|
|
96
96
|
token?: string;
|
|
97
|
+
appId?: string;
|
|
97
98
|
interceptResponses?: boolean;
|
|
98
99
|
onError?: (error: Error) => void;
|
|
99
100
|
}): import("axios").AxiosInstance;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
|
-
import { 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.
|
|
@@ -114,7 +114,7 @@ function safeErrorLog(prefix, error) {
|
|
|
114
114
|
* @returns Configured axios instance
|
|
115
115
|
* @internal
|
|
116
116
|
*/
|
|
117
|
-
export function createAxiosClient({ baseURL, headers = {}, token, interceptResponses = true, onError, }) {
|
|
117
|
+
export function createAxiosClient({ baseURL, headers = {}, token, appId, interceptResponses = true, onError, }) {
|
|
118
118
|
const client = axios.create({
|
|
119
119
|
baseURL,
|
|
120
120
|
headers: {
|
|
@@ -131,6 +131,16 @@ export function createAxiosClient({ baseURL, headers = {}, token, interceptRespo
|
|
|
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 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
|
+
if (activeAccountId) {
|
|
142
|
+
config.headers.set("X-Active-Account-Id", activeAccountId);
|
|
143
|
+
}
|
|
134
144
|
}
|
|
135
145
|
const requestId = uuidv4();
|
|
136
146
|
config.requestId = requestId;
|
package/dist/utils/common.d.ts
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
1
|
export declare const isNode: boolean;
|
|
2
2
|
export declare const isInIFrame: boolean;
|
|
3
|
+
/**
|
|
4
|
+
* The active account id from stored client state, or undefined.
|
|
5
|
+
*
|
|
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.
|
|
9
|
+
*/
|
|
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;
|
|
3
19
|
export declare const generateUuid: () => string;
|
package/dist/utils/common.js
CHANGED
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
export const isNode = typeof window === "undefined";
|
|
2
2
|
export const isInIFrame = !isNode && window.self !== window.top;
|
|
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.
|
|
8
|
+
const ACCOUNT_ID_RE = /^[a-f0-9]{24}$/;
|
|
9
|
+
const activeAccountStorageKey = (appId) => `base44:active_account:${appId}`;
|
|
10
|
+
/**
|
|
11
|
+
* The active account id from stored client state, or undefined.
|
|
12
|
+
*
|
|
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.
|
|
16
|
+
*/
|
|
17
|
+
export function getStoredActiveAccountId(appId) {
|
|
18
|
+
if (isNode)
|
|
19
|
+
return 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
|
+
}
|
|
50
|
+
}
|
|
3
51
|
export const generateUuid = () => {
|
|
4
52
|
return (Math.random().toString(36).substring(2, 15) +
|
|
5
53
|
Math.random().toString(36).substring(2, 15));
|