Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 57 additions & 32 deletions scripts/mintlify-post-processing/copy-to-local-docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,47 +160,72 @@ function updateDocsJson(repoDir, sdkFiles) {
`SDK Reference pages: ${JSON.stringify(sdkReferencePages, null, 2)}`
);

// Navigate to: Developers tab -> SDK section -> groups -> SDK Reference
// Supports both legacy "anchors" format and current "dropdowns" format.
const developersTab = docs.navigation.tabs.find(
(tab) => tab.tab === "Developers"
);

if (!developersTab) {
console.error("Could not find 'Developers' tab in docs.json");
// docs.json supports three navigation shapes we've seen in the wild:
// 1. top-level tabs (legacy) navigation.tabs
// 2. top-level tabs with dropdowns/anchors navigation.tabs[].dropdowns | .anchors
// 3. i18n layout (current) navigation.languages[].tabs[]...
// The SDK reference mdx files are English-only, so for every locale we point its
// SDK Reference group at the same English paths. This is what the docs site
// effectively shows today anyway.
//
// We locate the target group by content (any group whose pages reference
// `/sdk/docs/`) rather than by tab/group name, because the surrounding labels
// are translated per locale while the "SDK" dropdown id and the page paths
// stay stable. Preserves the existing translated group label.
const tabsContainers =
docs.navigation.languages?.map((l) => l.tabs).filter(Boolean) ??
[docs.navigation.tabs].filter(Boolean);

if (tabsContainers.length === 0) {
console.error("Could not find navigation.tabs or navigation.languages in docs.json");
process.exit(1);
}

// Find the SDK section (try dropdowns first, then fall back to anchors)
const sdkAnchor =
developersTab.dropdowns?.find((d) => d.dropdown === "SDK") ??
developersTab.anchors?.find((a) => a.anchor === "SDK");

if (!sdkAnchor) {
console.error("Could not find 'SDK' dropdown or anchor in Developers tab");
process.exit(1);
const groupReferencesSdkDocs = (group) =>
JSON.stringify(group).includes(`${basePath}/`);

let updatedCount = 0;
for (const tabs of tabsContainers) {
for (const tab of tabs) {
const sdkAnchor =
tab.dropdowns?.find((d) => d.dropdown === "SDK") ??
tab.anchors?.find((a) => a.anchor === "SDK");
if (!sdkAnchor?.groups) continue;

const sdkRefIndex = sdkAnchor.groups.findIndex(groupReferencesSdkDocs);
if (sdkRefIndex === -1) continue;

const existing = sdkAnchor.groups[sdkRefIndex];

// Preserve existing subgroup labels (translated per locale) by position.
// Falls back to the English category-map label when no existing subgroup
// sits at that index (e.g. a locale that gains a new subgroup).
const existingSubgroups = Array.isArray(existing.pages) ? existing.pages : [];
const localizedPages = sdkReferencePages.map((g, i) => ({
...g,
group: existingSubgroups[i]?.group ?? g.group,
}));

sdkAnchor.groups[sdkRefIndex] = {
...existing,
group: existing.group,
icon: existing.icon ?? "brackets-curly",
expanded: true,
pages: localizedPages,
};
updatedCount++;
}
}

// Find SDK Reference within the SDK anchor's groups
const sdkRefIndex = sdkAnchor.groups.findIndex(
(g) => g.group === "SDK Reference"
);

if (sdkRefIndex === -1) {
console.error("Could not find 'SDK Reference' group in SDK anchor");
if (updatedCount === 0) {
console.error(
"Could not find any SDK Reference navigation group to update (looked for groups whose pages reference '/sdk/docs/')"
);
process.exit(1);
}

// Update the SDK Reference pages with our generated groups
sdkAnchor.groups[sdkRefIndex] = {
group: "SDK Reference",
icon: "brackets-curly",
expanded: true,
pages: sdkReferencePages,
};

// Write updated docs.json
console.log(`Writing updated docs.json to ${docsJsonPath}...`);
console.log(`Writing updated docs.json to ${docsJsonPath} (${updatedCount} locale(s))...`);
fs.writeFileSync(docsJsonPath, JSON.stringify(docs, null, 2) + "\n", "utf8");

console.log("Successfully updated docs.json");
Expand Down
12 changes: 6 additions & 6 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ export type { Base44Client, CreateClientConfig, CreateClientOptions };
* The client supports three authentication modes:
* - **Anonymous**: Access modules without authentication using `base44.moduleName`. Operations are scoped to public data and permissions.
* - **User authentication**: Access modules with user-level permissions using `base44.moduleName`. Operations are scoped to the authenticated user's data and permissions. Use `base44.auth.loginViaEmailPassword()` or other auth methods to get a token.
* - **Service role authentication**: Access modules with elevated permissions using `base44.asServiceRole.moduleName`. Operations can access any data available to the app's admin. Only available in Base44-hosted backend functions. Create a client with service role authentication using {@linkcode createClientFromRequest | createClientFromRequest()}.
* - **Service role authentication**: Access modules with elevated permissions using `base44.asServiceRole.moduleName`. Operations bypass entity access rules and field-level security, giving full read and write access to all of the app's data. Only available in Base44-hosted backend functions. Create a client with service role authentication using {@linkcode createClientFromRequest | createClientFromRequest()}.
*
* For example, when using the {@linkcode EntitiesModule | entities} module:
* - **Anonymous**: Can only read public data.
* - **User authentication**: Can access the current user's data.
* - **Service role authentication**: Can access all data that admins can access.
* - **Service role authentication**: Can read and write any record, bypassing access rules.
*
* Most modules are available in all three modes, but with different permission levels. However, some modules are only available in specific authentication modes.
*
Expand Down Expand Up @@ -302,7 +302,7 @@ export function createClient(config: CreateClientConfig): Base44Client {
/**
* Provides access to service role modules.
*
* Service role authentication provides elevated permissions for backend operations. Unlike user authentication, which is scoped to a specific user's permissions, service role authentication has access to the data and operations available to the app's admin.
* Service role authentication provides elevated permissions for backend operations. Unlike user authentication, which is scoped to a specific user's permissions, service role authentication bypasses entity access rules and field-level security entirely, giving full read and write access to all of the app's data.
*
* @throws {Error} When accessed without providing a serviceToken during client creation.
*
Expand All @@ -313,7 +313,7 @@ export function createClient(config: CreateClientConfig): Base44Client {
* serviceToken: 'service-role-token'
* });
*
* // Also access a module with elevated permissions
* // Read every user record, bypassing the User entity's access rules
* const allUsers = await base44.asServiceRole.entities.User.list();
* ```
*/
Expand All @@ -335,7 +335,7 @@ export function createClient(config: CreateClientConfig): Base44Client {
*
* This function is designed for use in Base44-hosted backend functions. For frontends and external backends, use {@linkcode createClient | createClient()} instead.
*
* When used in a Base44-hosted backend function, `createClientFromRequest()` automatically extracts authentication tokens from the request headers that Base44 injects when forwarding requests. The returned client includes service role access using `base44.asServiceRole`, which provides admin-level permissions.
* When used in a Base44-hosted backend function, `createClientFromRequest()` automatically extracts authentication tokens from the request headers that Base44 injects when forwarding requests. The returned client includes service role access using `base44.asServiceRole`, which bypasses entity access rules and field-level security.
*
* To learn more about the Base44 client, see {@linkcode createClient | createClient()}.
*
Expand Down Expand Up @@ -374,7 +374,7 @@ export function createClient(config: CreateClientConfig): Base44Client {
* try {
* const base44 = createClientFromRequest(req);
*
* // Access admin data with service role permissions
* // Read across all users, bypassing the Orders entity's access rules
* const recentOrders = await base44.asServiceRole.entities.Orders.list('-created_at', 50);
*
* return Response.json({ orders: recentOrders });
Expand Down
4 changes: 2 additions & 2 deletions src/client.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export interface CreateClientConfig {
*/
token?: string;
/**
* Service role authentication token. Provides elevated permissions to access data available to the app's admin. Only available in Base44-hosted backend functions. Automatically added to client's created using {@linkcode createClientFromRequest | createClientFromRequest()}.
* Service role authentication token. Provides elevated permissions that bypass entity access rules and field-level security. Only available in Base44-hosted backend functions. Automatically added to clients created using {@linkcode createClientFromRequest | createClientFromRequest()}.
* @internal
*/
serviceToken?: string;
Expand Down Expand Up @@ -122,7 +122,7 @@ export interface Base44Client {
/**
* Provides access to supported modules with elevated permissions.
*
* Service role authentication provides elevated permissions for backend operations. Unlike user authentication, which is scoped to a specific user's permissions, service role authentication has access to the data and operations available to the app's admin.
* Service role authentication provides elevated permissions for backend operations. Unlike user authentication, which is scoped to a specific user's permissions, service role authentication bypasses entity access rules and field-level security entirely, giving full read and write access to all of the app's data.
*
* @throws {Error} When accessed without providing a serviceToken during client creation
*/
Expand Down
2 changes: 1 addition & 1 deletion src/modules/agents.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ export interface AgentsModuleConfig {
* This module is available to use with a client in all authentication modes:
*
* - **Anonymous or User authentication** (`base44.agents`): Access is scoped to the current user's permissions. Users must be authenticated to create and access conversations.
* - **Service role authentication** (`base44.asServiceRole.agents`): Operations have elevated admin-level permissions. Can access all conversations that the app's admin role has access to.
* - **Service role authentication** (`base44.asServiceRole.agents`): Operations are invoked with the service role for backend code that needs elevated permissions.
*
* ## Generated Types
*
Expand Down
4 changes: 2 additions & 2 deletions src/modules/entities.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ type DynamicEntitiesModule = {
* This module is available to use with a client in all authentication modes:
*
* - **Anonymous or User authentication** (`base44.entities`): Access is scoped to the current user's permissions. Anonymous users can only access public entities, while authenticated users can access entities they have permission to view or modify.
* - **Service role authentication** (`base44.asServiceRole.entities`): Operations have elevated admin-level permissions. Can access all entities that the app's admin role has access to.
* - **Service role authentication** (`base44.asServiceRole.entities`): Operations bypass entity access rules and field-level security entirely. Can read and write any record in any entity.
*
* ## Entity Handlers
*
Expand Down Expand Up @@ -753,7 +753,7 @@ type DynamicEntitiesModule = {
*
* @example
* ```typescript
* // List all users (admin only)
* // List every user, bypassing the User entity's access rules
* const allUsers = await base44.asServiceRole.entities.User.list();
* ```
*/
Expand Down
2 changes: 1 addition & 1 deletion src/modules/functions.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export interface FunctionsModuleConfig {
* This module is available to use with a client in all authentication modes:
*
* - **Anonymous or User authentication** (`base44.functions`): Functions are invoked with the current user's permissions. Anonymous users invoke functions without authentication, while authenticated users invoke functions with their authentication context.
* - **Service role authentication** (`base44.asServiceRole.functions`): Functions are invoked with elevated admin-level permissions. The function code receives a request with admin authentication context.
* - **Service role authentication** (`base44.asServiceRole.functions`): Functions are invoked with the service role for backend code that needs elevated permissions.
*
* ## Generated Types
*
Expand Down
2 changes: 1 addition & 1 deletion src/modules/integrations.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ export interface CoreIntegrations {
* This module is available to use with a client in all authentication modes:
*
* - **Anonymous or User authentication** (`base44.integrations`): Integration methods are invoked with the current user's permissions. Anonymous users invoke methods without authentication, while authenticated users invoke methods with their authentication context.
* - **Service role authentication** (`base44.asServiceRole.integrations`): Integration methods are invoked with elevated admin-level permissions. The methods execute with admin authentication context.
* - **Service role authentication** (`base44.asServiceRole.integrations`): Integration methods are invoked with the service role for backend code that needs elevated permissions.
*/
export type IntegrationsModule = {
/**
Expand Down
Loading