From 23864772a0c4347c602efc74553795424b19e3df Mon Sep 17 00:00:00 2001 From: danielle korn Date: Sun, 6 Sep 2026 09:26:45 +0300 Subject: [PATCH 1/6] docs(jsdoc): remove em dashes from SDK source comments Base44 docs style forbids em dashes, and JSDoc in this repo is published prose that renders straight into the Mintlify SDK reference. Seven of these were live on published pages. Each one is rewritten rather than mechanically swapped, preferring a comma or a sentence break. Comments only, no code changes. --- src/actor.ts | 14 +++++++------- src/client.ts | 2 +- src/client.types.ts | 4 ++-- src/modules/actors.ts | 12 ++++++------ src/modules/actors.types.ts | 14 +++++++------- src/modules/analytics.ts | 4 ++-- src/modules/app.types.ts | 8 ++++---- src/modules/auth.ts | 2 +- src/modules/auth.types.ts | 4 ++-- src/modules/connectors.ts | 4 ++-- src/modules/connectors.types.ts | 8 ++++---- src/modules/entities.ts | 2 +- src/utils/common.ts | 2 +- 13 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/actor.ts b/src/actor.ts index 153224cd..b08756c7 100644 --- a/src/actor.ts +++ b/src/actor.ts @@ -6,14 +6,14 @@ * export class MyActor extends Actor { ... } * * At deploy time the bundler replaces this import with the compiled - * Cloudflare Durable Object implementation — this file provides types only. + * Cloudflare Durable Object implementation. This file provides types only. */ import type { Base44Client } from "./client"; /** * A single client connection. `Send` is the message type this connection accepts - * via {@link send} — the actor's *outgoing* (server→client) messages. + * via {@link send}, the actor's *outgoing* (server→client) messages. */ export interface Conn { /** Unique per-connection id (one per socket/tab), the same value the client @@ -37,9 +37,9 @@ export interface Storage { * Base class for an Actor. * * @typeParam Incoming - messages this actor *receives* from clients - * (`handleMessage`'s `msg`) — the schema's `toServer` section. + * (`handleMessage`'s `msg`), the schema's `toServer` section. * @typeParam Outgoing - messages this actor *sends* to clients - * (`conn.send`/`broadcast`) — the schema's `toClient` section. + * (`conn.send`/`broadcast`), the schema's `toClient` section. * * With a generated `schema.jsonc`, wire both from the registry so they can't drift * from the client's types: @@ -56,7 +56,7 @@ export abstract class Actor { /** * Optional wake hook: runs once when the instance starts, before any - * connection is handled — safe to load persisted state here. + * connection is handled. It is safe to load persisted state here. */ handleStart(): void | Promise {} @@ -84,7 +84,7 @@ export abstract class Actor { /** * Managed ticker (opt-in). Override {@link shouldTick} and the platform runs * {@link handleTick} on a timer of {@link tickIntervalMs} while it returns true, - * and stops (letting the Durable Object hibernate — no compute cost) when it + * and stops (letting the Durable Object hibernate at no compute cost) when it * returns false. The platform owns scheduling, rescheduling, self-heal, and * error-safety. * @@ -111,7 +111,7 @@ export abstract class Actor { } /** - * Anonymous Base44 client scoped to this actor instance — no user or service + * Anonymous Base44 client scoped to this actor instance, with no user or service * auth, so entity access is RLS-gated (same as a logged-out visitor). Always * operates on production data: an actor runs server-side with no per-connection * identity, so a Test DB preview selected in the editor does not apply here. diff --git a/src/client.ts b/src/client.ts index 84bfc15a..0d5abecf 100644 --- a/src/client.ts +++ b/src/client.ts @@ -157,7 +157,7 @@ export function createClient(config: CreateClientConfig): Base44Client { // Dedicated client for actor connection-token mints: no onError (a legacy // actor answers every mint with an expected 409 before the proxy fallback, - // which must not reach the app's error handler — the actors module forwards + // which must not reach the app's error handler; the actors module forwards // genuine failures itself via onMintError) and no constructor token // (auth is per-request so a login/logout is picked up on every reconnect). const actorsAxiosClient = createAxiosClient({ diff --git a/src/client.types.ts b/src/client.types.ts index b94a6333..6a5cd41f 100644 --- a/src/client.types.ts +++ b/src/client.types.ts @@ -22,14 +22,14 @@ export interface CreateClientOptions { * Optional error handler that will be called whenever an API error occurs. * * Also receives {@link ActorsModule | actors} connection failures. Errors - * are usually {@linkcode Base44Error} instances — check `error.status`. + * are usually {@linkcode Base44Error} instances, so check `error.status`. */ onError?: (error: Error) => void; /** * Forces the actors transport. `"auto"` (default) connects directly to the * actor and falls back to the platform proxy when the app's actors don't * support direct connections; `"proxy"` always uses the platform proxy - * (ops rollback — no connection-token calls); `"direct"` disables the + * (ops rollback, with no connection-token calls); `"direct"` disables the * fallback (validation environments). * @internal */ diff --git a/src/modules/actors.ts b/src/modules/actors.ts index 493b2078..87ccb757 100644 --- a/src/modules/actors.ts +++ b/src/modules/actors.ts @@ -54,13 +54,13 @@ const DEAD_MS = 3_000; // 422 = no principal (e.g. anonymous outside a browser) or an id/room only the // proxy's looser validation accepts, 405 = a backend that predates the mint // endpoint (its actor deploy routes catch the path via `{handler_name:path}` -// but not the POST method — and the real endpoint never 405s a POST). The +// but not the POST method, and the real endpoint never 405s a POST). The // proxy serves migrated actors too, so falling back is always safe. const PROXY_FALLBACK_STATUSES = new Set([405, 409, 422, 503]); // Mint responses no retry can fix (bad request / forbidden / not found): the // connection closes instead of re-minting forever; a fresh connect() re-probes. -// 401 is deliberately absent — the auth token is re-read on every attempt, so a +// 401 is deliberately absent. The auth token is re-read on every attempt, so a // login recovers on the next retry. Disjoint from PROXY_FALLBACK_STATUSES. const TERMINAL_MINT_STATUSES = new Set([400, 403, 404]); @@ -80,7 +80,7 @@ function toError(err: unknown): Error { /** * A live connection to an actor instance. Only obtainable from - * {@link ActorRef.connect}, so `subscribe`/`send` are always valid — the socket + * {@link ActorRef.connect}, so `subscribe`/`send` are always valid. The socket * exists for this object's whole lifetime. */ class Connection { @@ -88,7 +88,7 @@ class Connection { private readonly listeners = new Set<(data: unknown) => void>(); private heartbeat: ReturnType | null = null; private closed = false; - /** The client-chosen conn id — becomes _pk → the actor's conn.id. */ + /** The client-chosen conn id. It becomes _pk → the actor's conn.id. */ readonly id: string; constructor( @@ -104,7 +104,7 @@ class Connection { // mint answers with a fallback status the choice is sticky for this // socket's lifetime (a fresh connect() after close() probes direct again, // picking up actors migrated in the meantime). Any other mint failure - // rejects, which ReconnectingWebSocket retries with backoff — except the + // rejects, which ReconnectingWebSocket retries with backoff, except the // terminal statuses, which close this connection for good. let useProxy = config.transport === "proxy"; const urlProvider = async (): Promise => { @@ -245,7 +245,7 @@ function makeActorRef( * The legacy platform-proxy URL, byte-for-byte what PartySocket built before * the direct path existed: same scheme swap (including its localhost-needs-a- * port quirk), case-preserved party segment, `_pk` first in the query. The - * `handler` param is load-bearing — the proxy reads it for the actor name. + * `handler` param is load-bearing. The proxy reads it for the actor name. */ export function buildProxyActorUrl( rawHost: string, diff --git a/src/modules/actors.types.ts b/src/modules/actors.types.ts index bb55bbed..34efba77 100644 --- a/src/modules/actors.types.ts +++ b/src/modules/actors.types.ts @@ -21,7 +21,7 @@ export interface ActorRegistry {} /** * Auto-populated by `base44 types generate` with the names of your deployed actors. - * Do not edit this interface manually — use {@link ActorRegistry} for message types. + * Do not edit this interface manually. Use {@link ActorRegistry} for message types. */ export interface ActorNameRegistry {} @@ -42,7 +42,7 @@ type ToServerFor = N extends keyof ActorRegistry /** Options for {@link ActorRef.connect}. */ export interface ActorConnectOptions { /** - * The connection id — becomes the actor's `conn.id`. Supply a stable value + * The connection id, used as the actor's `conn.id`. Supply a stable value * (e.g. persisted per tab) so a reconnect reuses the same server-side * identity; omit for an auto-generated per-connection id. */ @@ -57,7 +57,7 @@ export interface ActorSubscription { /** * A live connection to an actor instance, returned by {@link ActorRef.connect}. - * `subscribe`/`send` are always valid — you only get a `Connection` once the + * `subscribe`/`send` are always valid. You only get a `Connection` once the * socket has been opened, so there's no pre-connect state to guard against. */ export interface Connection { @@ -73,14 +73,14 @@ export interface Connection { /** * Tear down the socket, heartbeat, and all listeners. Safe to call more - * than once. A connection also closes itself when it fails permanently — - * see {@link ActorRef.connect}. + * than once. A connection also closes itself when it fails permanently. + * See {@link ActorRef.connect}. */ close(): void; } /** - * A handle to one actor instance — `base44.actors.MyActor(id)`. Call + * A handle to one actor instance, obtained from `base44.actors.MyActor(id)`. Call * {@link connect} to open the socket and get a {@link Connection}. */ export interface ActorRef { @@ -97,7 +97,7 @@ export interface ActorRef { } /** - * Client for a single named Actor — call it with an instance id to get an + * Client for a single named Actor. Call it with an instance id to get an * {@link ActorRef}. Typed automatically when the actor is registered in * {@link ActorRegistry}. */ diff --git a/src/modules/analytics.ts b/src/modules/analytics.ts index e9aebfc5..8d9677de 100644 --- a/src/modules/analytics.ts +++ b/src/modules/analytics.ts @@ -45,7 +45,7 @@ const analyticsSharedState = getSharedInstance( wasInitializationTracked: false, sessionContext: null as SessionContext | null, sessionStartTime: null as string | null, - // Memoized session id for when `localStorage` can't persist one — see + // Memoized session id for when `localStorage` can't persist one. See // getAnalyticsSessionId. fallbackSessionId: null as string | null, config: { @@ -342,7 +342,7 @@ async function getSessionContext( // With no token there is no identity to resolve: `me()` can only answer 401, // which the browser logs to the console before any handler here sees it. On // a public page that request is the sole reason an error appears, so skip - // it. This is not memoized — a visitor who logs in later must still resolve. + // it. This is not memoized. A visitor who logs in later must still resolve. if (!userAuthModule.hasToken()) { return { user_id: null, session_id: getAnalyticsSessionId() }; } diff --git a/src/modules/app.types.ts b/src/modules/app.types.ts index f3656fb4..93e47cb7 100644 --- a/src/modules/app.types.ts +++ b/src/modules/app.types.ts @@ -28,7 +28,7 @@ export interface AppPublicSettingsResponse { * ## Authentication Modes * * This module is available to use with a client in all authentication modes. The - * client's token, when it has one, is sent with the request — a signed-in visitor + * client's token, when it has one, is sent with the request, so a signed-in visitor * who has no access to the app is reported differently from an anonymous one. */ export interface AppModule { @@ -36,9 +36,9 @@ export interface AppModule { * Get the app's public configuration. * * Rejects with a {@linkcode Base44Error} when the visitor may not open the app: - * `status` is `403` and `data.extra_data.reason` says why — `"auth_required"` - * when the visitor must sign in, `"user_not_registered"` when the signed-in - * visitor has no access to this app. + * `status` is `403` and `data.extra_data.reason` says why. It is + * `"auth_required"` when the visitor must sign in, and + * `"user_not_registered"` when the signed-in visitor has no access to this app. * * @returns Promise resolving to the app's ID and access policy. * diff --git a/src/modules/auth.ts b/src/modules/auth.ts index b9e23747..51eb8543 100644 --- a/src/modules/auth.ts +++ b/src/modules/auth.ts @@ -99,7 +99,7 @@ export function createAuthModule( // two identical GETs, so the second pays the first's full latency on every // cold load. // - // This shares the pending promise only — it is cleared as soon as the request + // This shares the pending promise only, and it is cleared as soon as the request // settles, so no resolved user is ever retained. Caching the user across // requests would leave the app rendering a stale identity after logout or a // session swap. diff --git a/src/modules/auth.types.ts b/src/modules/auth.types.ts index 7c080efe..0f95a8a1 100644 --- a/src/modules/auth.types.ts +++ b/src/modules/auth.types.ts @@ -556,7 +556,7 @@ export interface AuthModule { /** * The auth module as constructed internally, before it is narrowed to * {@link AuthModule} on the public client. Not exported from the package - * index — SDK consumers see only {@link AuthModule}. + * index. SDK consumers see only {@link AuthModule}. * * @internal */ @@ -564,7 +564,7 @@ export interface InternalAuthModule extends AuthModule { /** * Whether an access token is currently set on the client. * - * Reports only the presence of a token, never its validity — an expired or + * Reports only the presence of a token, never its validity. An expired or * revoked token still reads as `true`. Callers use this to skip requests that * could not succeed without a session, not to decide that one is valid. */ diff --git a/src/modules/connectors.ts b/src/modules/connectors.ts index 5b691c3d..9391639e 100644 --- a/src/modules/connectors.ts +++ b/src/modules/connectors.ts @@ -151,8 +151,8 @@ function assertNonEmptyString(value: unknown, label: string): void { * POST a request to the connector proxy and normalize the response. * * The proxy reports upstream outcomes in the body rather than as HTTP status, so - * a provider 4xx/5xx arrives here as a resolved response with `success: false` — - * only Base44-side failures reject through the axios error interceptor. + * a provider 4xx/5xx arrives here as a resolved response with `success: false`. + * Only Base44-side failures reject through the axios error interceptor. * * @internal */ diff --git a/src/modules/connectors.types.ts b/src/modules/connectors.types.ts index d8650588..2f8b67c4 100644 --- a/src/modules/connectors.types.ts +++ b/src/modules/connectors.types.ts @@ -100,7 +100,7 @@ export interface ConnectorApiResponse { status: number | null; /** * The parsed upstream response body, or proxy error details when no response - * was received. `null` when the response was binary — see {@link dataBase64}. + * was received. It is `null` when the response was binary. See {@link dataBase64}. */ data: T | null; /** @@ -163,9 +163,9 @@ export interface ConnectorProxyRawResponse { * * ## Metered connectors * - * A few [platform connectors](#shared-connectors) are backed by paid third-party APIs that charge Base44 per call. For those, the OAuth token is **not** available to your code — {@linkcode getConnection | getConnection()} rejects with a `403`. Call them with {@linkcode callApi | callApi()} instead: Base44 attaches the credential server-side, forwards the request, and bills your workspace's integration credits for the call. + * A few [platform connectors](#shared-connectors) are backed by paid third-party APIs that charge Base44 per call. For those, the OAuth token is **not** available to your code, and {@linkcode getConnection | getConnection()} rejects with a `403`. Call them with {@linkcode callApi | callApi()} instead. Base44 attaches the credential server-side, forwards the request, and bills your workspace's integration credits for the call. * - * This applies to platform connectors only. A workspace-registered or app user connector runs on **your own** OAuth app, so the provider invoices you directly and there is nothing for Base44 to meter — those keep normal token access via {@linkcode getWorkspaceConnection | getWorkspaceConnection()} and {@linkcode getCurrentAppUserConnection | getCurrentAppUserConnection()}. + * This applies to platform connectors only. A workspace-registered or app user connector runs on **your own** OAuth app, so the provider invoices you directly and there is nothing for Base44 to meter. Those keep normal token access via {@linkcode getWorkspaceConnection | getWorkspaceConnection()} and {@linkcode getCurrentAppUserConnection | getCurrentAppUserConnection()}. * * Two things to keep in mind when writing against a metered connector: * @@ -448,7 +448,7 @@ export interface ConnectorsModule { * * @param integrationType - The type of integration, such as `'x'`. See [Available connectors](#available-connectors). * @param request - The upstream request to forward. See {@link ConnectorApiRequest}. - * @returns Promise resolving to a {@link ConnectorApiResponse}. Note that an upstream error is reported in `success` and `status`, not thrown — only Base44-side failures reject. + * @returns Promise resolving to a {@link ConnectorApiResponse}. Note that an upstream error is reported in `success` and `status`, not thrown. Only Base44-side failures reject. * * @example * ```typescript diff --git a/src/modules/entities.ts b/src/modules/entities.ts index 1eaaf287..6f6988c3 100644 --- a/src/modules/entities.ts +++ b/src/modules/entities.ts @@ -204,7 +204,7 @@ function createEntityHandler( // developer console so they know to fetch the full record on // demand (e.g. a follow-up entities.X.get(id) call) instead of // rendering the slimmed payload directly. Skip on delete events - // — the record no longer exists. + // because the record no longer exists. if (event.type !== "delete" && (event.data as any)?._oversize) { console.error( `[Base44 SDK] Realtime broadcast for ${entityName}#${event.id} was oversize and got slimmed for transport. ` + diff --git a/src/utils/common.ts b/src/utils/common.ts index d7bec21b..ea723131 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -2,7 +2,7 @@ export const isNode = typeof window === "undefined"; export const isInIFrame = !isNode && window.self !== window.top; // React Native defines `window` (so `isNode` is false there) but not `document`. -// Browser-only code paths gated on `window`/`isNode` alone would run — and crash — +// Browser-only code paths gated on `window`/`isNode` alone would run, and crash, // on React Native. Node (no `window`) is already handled by those `window` guards; // this flags the window-without-a-DOM case that isn't. export const isReactNative = !isNode && typeof document === "undefined"; From 87ccff5613680be50c2b3b8f24a25cd9e5acebe3 Mon Sep 17 00:00:00 2001 From: danielle korn Date: Sun, 6 Sep 2026 09:26:45 +0300 Subject: [PATCH 2/6] docs(skill): add em dash and grammar rules to sdk-docs-writing The em dash rule already exists in base44-docs-writing and changelog-writing, but sdk-docs-writing had no style guidance on it, which is how em dashes reached the published SDK reference. Moves the two facts that govern all writing in this skill up to the top, since they were buried under a style bullet: this JSDoc is published prose subject to the main docs style guide, and fixes belong in the source because the generated MDX is overwritten on every run. Also notes that colons should be rare, calls out the two grammar slips that come up when rewriting an em dash away, and removes the em dashes the skill was itself using. --- .claude/skills/sdk-docs-writing/SKILL.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/.claude/skills/sdk-docs-writing/SKILL.md b/.claude/skills/sdk-docs-writing/SKILL.md index ef1bfd94..cb36e7c9 100644 --- a/.claude/skills/sdk-docs-writing/SKILL.md +++ b/.claude/skills/sdk-docs-writing/SKILL.md @@ -13,12 +13,18 @@ Docs in this repo are **auto-generated** from JSDoc comments in TypeScript sourc You write JSDoc. The tooling produces the final pages. +Two things follow from that, and they govern everything below. + +**This JSDoc is published prose.** It renders into the public SDK reference, so it follows the same style rules as the rest of the Base44 docs. Read `mintlify-docs/.claude/skills/base44-docs-writing/SKILL.md` first, and treat the writing guidance here as the SDK-specific additions to it. + +**Fix the source, never the generated MDX.** Every run overwrites `developers/references/sdk/docs/` in `mintlify-docs`, so an edit made there is gone on the next regeneration. When something reads wrong on a published page, the fix belongs in the JSDoc that produced it. + ## Where docs come from | File pattern | Role | |---|---| -| `src/modules/*.types.ts` | **Public API surface** — JSDoc here becomes the published docs | -| `src/modules/*.ts` | Implementation — mark with `@internal` to hide from docs | +| `src/modules/*.types.ts` | **Public API surface.** JSDoc here becomes the published docs | +| `src/modules/*.ts` | Implementation. Mark with `@internal` to hide from docs | | `src/client.types.ts` | Client factory types | | `src/types.ts` | Shared types | @@ -75,6 +81,8 @@ Every public method needs: description, `@param` tags, `@returns`, and at least ## Writing style - **Developer audience.** These are SDK reference docs for JavaScript/TypeScript developers. +- **Never use em dashes.** Use a comma or a separate sentence instead. Colons are allowed but should be rare, so reach for one only to introduce a genuine list. +- **Grammar and punctuation must be correct.** This is public-facing professional documentation. Two slips come up often when rewriting an em dash away. Do not put a comma before a restrictive `because` clause, and do not leave a sentence fragment behind when you split one sentence into two. - **Concise descriptions.** First sentence is a verb phrase: "Lists records...", "Creates a new...", "Sends an invitation...". - **Sentence case** for free-text headings in JSDoc. - **State environment constraints** when a method is browser-only: "Requires a browser environment and can't be used in the backend." @@ -92,5 +100,6 @@ Every public method needs: description, `@param` tags, `@returns`, and at least 1. **JSDoc completeness:** Every public method has description, `@param`, `@returns`, and `@example`. 2. **`@internal` on implementation:** Factory functions, config interfaces, and helpers are marked `@internal`. 3. **Examples work:** Code examples are syntactically valid TypeScript and use the `base44.` call path. -4. **Pipeline config:** New public types are in `types-to-expose.json`. Helper types that belong on another page are in `appended-articles.json`. -5. **Generate and review:** Run `npm run create-docs` and check the output renders correctly. +4. **No em dashes:** `grep -rn '—' src/` comes back empty for any file you touched. +5. **Pipeline config:** New public types are in `types-to-expose.json`. Helper types that belong on another page are in `appended-articles.json`. +6. **Generate and review:** Run `npm run create-docs` and check the output renders correctly. From e6cec00e7d8a8a363f0e832fae8d13c3dcd40669 Mon Sep 17 00:00:00 2001 From: danielle korn Date: Sun, 6 Sep 2026 09:26:45 +0300 Subject: [PATCH 3/6] fix(docs-gen): fold new supporting types into module pages, hold back actors Two pipeline config gaps, both surfaced by regenerating the published reference for the first time in a while. Supporting types are meant to be appended into the page for the module that owns them, then dropped as standalone pages. That is what appended-articles.json does for EntityHandler, SortField, ConnectorIntegrationType and the rest, and it is why the SDK Reference nav lists only modules. The types added with connectors.callApi() and app.getPublicSettings() were registered in types-to-expose.json but never added to appended-articles.json, so they rendered as standalone pages and showed up in the nav next to real modules. This appends them to their owners. The append step already unlinks the source page, so no types-to-delete-after-processing.json entry is needed. Separately, the actors page is held back. A renamed module page is treated as exposed regardless of types-to-expose.json, so actors published as an 18-line page carrying a truncated type signature, two sentences and one snippet, with connect(), subscribe(), send(), close() and unsubscribe() absent entirely. Suppressing it keeps that off the public site until the JSDoc is written. --- scripts/mintlify-post-processing/appended-articles.json | 6 +++++- .../types-to-delete-after-processing.json | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/mintlify-post-processing/appended-articles.json b/scripts/mintlify-post-processing/appended-articles.json index 27fb69b8..37180997 100644 --- a/scripts/mintlify-post-processing/appended-articles.json +++ b/scripts/mintlify-post-processing/appended-articles.json @@ -2,8 +2,12 @@ "interfaces/ConnectorsModule": [ "type-aliases/ConnectorIntegrationType", "interfaces/ConnectorIntegrationTypeRegistry", - "interfaces/UserConnectorsModule" + "interfaces/UserConnectorsModule", + "interfaces/ConnectorApiRequest", + "interfaces/ConnectorApiResponse", + "type-aliases/ConnectorApiResponsePhase" ], + "interfaces/AppModule": ["interfaces/AppPublicSettingsResponse"], "type-aliases/EntitiesModule": [ "interfaces/EntityHandler", "type-aliases/EntityRecord", diff --git a/scripts/mintlify-post-processing/types-to-delete-after-processing.json b/scripts/mintlify-post-processing/types-to-delete-after-processing.json index 5083520f..247c3b9e 100644 --- a/scripts/mintlify-post-processing/types-to-delete-after-processing.json +++ b/scripts/mintlify-post-processing/types-to-delete-after-processing.json @@ -1,4 +1,5 @@ [ + "actors", "AiGatewayConnection", "DeleteManyResult", "DeleteResult", From 31e7efbc11abe647211c7daeb39bf96c88156809 Mon Sep 17 00:00:00 2001 From: danielle korn Date: Sun, 6 Sep 2026 09:42:43 +0300 Subject: [PATCH 4/6] docs(app): drop the cross-page link from AppPublicSettingsResponse TypeDoc resolved {@link AppModule.getPublicSettings} to AppModule.mdx#getpublicsettings, but AppModule renders as app.mdx and the type is appended into that same page, so the href pointed at a file that does not exist. The link was redundant in the first place. AppPublicSettingsResponse now renders directly beneath getPublicSettings() on the app page, so a plain code reference reads the same and cannot break. --- src/modules/app.types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/app.types.ts b/src/modules/app.types.ts index 93e47cb7..e2d4b78a 100644 --- a/src/modules/app.types.ts +++ b/src/modules/app.types.ts @@ -10,7 +10,7 @@ export type AppPublicSettings = | string; /** - * The app's public configuration, as returned by {@link AppModule.getPublicSettings}. + * The app's public configuration, as returned by `getPublicSettings()`. */ export interface AppPublicSettingsResponse { /** The app's ID. */ From 259b5df45e485adb4049f0b5353c449b12aaf032 Mon Sep 17 00:00:00 2001 From: danielle korn Date: Sun, 6 Sep 2026 10:24:49 +0300 Subject: [PATCH 5/6] fix(docs-gen): sort the nav by page name instead of by path The SDK Reference nav sorted on the full page path, so every module declared as an interface came before every module declared as a type alias, and the alphabet restarted partway down the list: agents, ai-gateway, analytics, app, app-logs, auth, connectors, functions, sso, entities, integrations Whether a module lands in TypeDoc's interfaces/ or type-aliases/ directory follows from how it happens to be declared and is invisible to a reader, so it should not drive nav order. Sorting on the page name gives one run: agents, ai-gateway, analytics, app, app-logs, auth, connectors, entities, functions, integrations, sso Applied in both places that build a nav group: copy-to-local-docs.js for mintlify-docs, and file-processing.js for the SDK's own docs.json. --- .../copy-to-local-docs.js | 15 ++++++++++++++- .../file-processing/file-processing.js | 10 +++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/scripts/mintlify-post-processing/copy-to-local-docs.js b/scripts/mintlify-post-processing/copy-to-local-docs.js index 5d68a64b..03e82f8d 100644 --- a/scripts/mintlify-post-processing/copy-to-local-docs.js +++ b/scripts/mintlify-post-processing/copy-to-local-docs.js @@ -74,6 +74,14 @@ Examples: // Target location within mintlify-docs for SDK reference docs const SDK_DOCS_TARGET_PATH = "developers/references/sdk/docs"; +/** Compare two nav page paths by the page name a reader actually sees. */ +function byPageName(a, b) { + return a + .split("/") + .pop() + .localeCompare(b.split("/").pop(), "en", { sensitivity: "base" }); +} + function scanSdkDocs(sdkDocsDir) { const result = {}; @@ -139,7 +147,12 @@ function updateDocsJson(repoDir, sdkFiles) { return Array.from(groupMap.entries()).map(([group, pages]) => ({ group, expanded: true, - pages: pages.sort(), + // Sort on the page name, not the full path. A module lands in + // interfaces/ or type-aliases/ depending on how it is declared, which is + // invisible to the reader, and sorting on the path groups by that + // instead: every interfaces/ module first, then the alphabet restarting + // for the type-aliases/ ones. + pages: pages.sort((a, b) => byPageName(a, b)), })); }; diff --git a/scripts/mintlify-post-processing/file-processing/file-processing.js b/scripts/mintlify-post-processing/file-processing/file-processing.js index a3fc1e38..54b79330 100755 --- a/scripts/mintlify-post-processing/file-processing/file-processing.js +++ b/scripts/mintlify-post-processing/file-processing/file-processing.js @@ -391,7 +391,15 @@ function generateDocsJson(docsContent) { if (existingGroup) { existingGroup.pages.push(...docsContent.typeAliases); - existingGroup.pages.sort(); // Sort combined pages alphabetically + // Sort on the page name rather than the full path, so a module declared + // as a type alias sorts next to its neighbours instead of after every + // interface-declared one. + existingGroup.pages.sort((a, b) => + a + .split("/") + .pop() + .localeCompare(b.split("/").pop(), "en", { sensitivity: "base" }) + ); } else { groups.push({ group: groupName, From ea0f5672ed0cece258a884dda0a9270b3dfce8a6 Mon Sep 17 00:00:00 2001 From: danielle korn Date: Sun, 6 Sep 2026 11:23:25 +0300 Subject: [PATCH 6/6] fix(docs): repair two rendering defects in the SDK reference 1. Four auth examples and two integrations examples lost their first line of code. The pipeline promotes a leading // comment to the Mintlify code-block title, and an example without one has its first real line consumed instead. inviteUser, resetPasswordRequest, resetPassword and changePassword each published a try block with no try, and an orphaned closing brace. These six are live on the site today. Each now opens with a comment that describes the example. 2. connectors.callApi() published its query parameter as Record. TypeDoc truncates long inline unions, so the union is given a name, ConnectorApiQueryValue, and appended into the connectors page. It renders as Record with the definition alongside the method. Both fix the cause. Neither touches the post-processing pipeline. --- scripts/mintlify-post-processing/appended-articles.json | 5 ++++- scripts/mintlify-post-processing/types-to-expose.json | 3 ++- src/modules/auth.types.ts | 4 ++++ src/modules/connectors.types.ts | 9 ++++++++- src/modules/integrations.types.ts | 2 ++ 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/scripts/mintlify-post-processing/appended-articles.json b/scripts/mintlify-post-processing/appended-articles.json index 37180997..f9c0df98 100644 --- a/scripts/mintlify-post-processing/appended-articles.json +++ b/scripts/mintlify-post-processing/appended-articles.json @@ -4,10 +4,13 @@ "interfaces/ConnectorIntegrationTypeRegistry", "interfaces/UserConnectorsModule", "interfaces/ConnectorApiRequest", + "type-aliases/ConnectorApiQueryValue", "interfaces/ConnectorApiResponse", "type-aliases/ConnectorApiResponsePhase" ], - "interfaces/AppModule": ["interfaces/AppPublicSettingsResponse"], + "interfaces/AppModule": [ + "interfaces/AppPublicSettingsResponse" + ], "type-aliases/EntitiesModule": [ "interfaces/EntityHandler", "type-aliases/EntityRecord", diff --git a/scripts/mintlify-post-processing/types-to-expose.json b/scripts/mintlify-post-processing/types-to-expose.json index 5d7ef016..72a30f7d 100644 --- a/scripts/mintlify-post-processing/types-to-expose.json +++ b/scripts/mintlify-post-processing/types-to-expose.json @@ -9,12 +9,14 @@ "AppModule", "AppPublicSettingsResponse", "AuthModule", + "ConnectorApiQueryValue", "ConnectorApiRequest", "ConnectorApiResponse", "ConnectorApiResponsePhase", "ConnectorIntegrationType", "ConnectorIntegrationTypeRegistry", "ConnectorsModule", + "CoreIntegrations", "CustomIntegrationsModule", "DeleteManyResult", "DeleteResult", @@ -27,7 +29,6 @@ "FunctionsModule", "ImportResult", "IntegrationsModule", - "CoreIntegrations", "SortField", "SsoModule", "UpdateManyResult" diff --git a/src/modules/auth.types.ts b/src/modules/auth.types.ts index 0f95a8a1..f0b0a528 100644 --- a/src/modules/auth.types.ts +++ b/src/modules/auth.types.ts @@ -357,6 +357,7 @@ export interface AuthModule { * * @example * ```typescript + * // Invite a user and handle failure * try { * await base44.auth.inviteUser('newuser@example.com', 'user'); * console.log('Invitation sent successfully!'); @@ -491,6 +492,7 @@ export interface AuthModule { * * @example * ```typescript + * // Request a password reset email * try { * await base44.auth.resetPasswordRequest('user@example.com'); * console.log('Password reset email sent!'); @@ -513,6 +515,7 @@ export interface AuthModule { * * @example * ```typescript + * // Complete a password reset with the emailed token * try { * await base44.auth.resetPassword({ * resetToken: 'token-from-email', @@ -538,6 +541,7 @@ export interface AuthModule { * * @example * ```typescript + * // Change the password for a signed-in user * try { * await base44.auth.changePassword({ * userId: 'user-123', diff --git a/src/modules/connectors.types.ts b/src/modules/connectors.types.ts index 2f8b67c4..4f8c796d 100644 --- a/src/modules/connectors.types.ts +++ b/src/modules/connectors.types.ts @@ -64,6 +64,13 @@ export type ConnectorApiResponsePhase = /** * A request to forward to a metered connector's API through the Base44 proxy. */ +/** A value acceptable as a query parameter on {@link ConnectorApiRequest.query}. */ +export type ConnectorApiQueryValue = + | string + | number + | boolean + | Array; + export interface ConnectorApiRequest { /** HTTP method for the upstream request. Defaults to `'GET'`. */ method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD"; @@ -81,7 +88,7 @@ export interface ConnectorApiRequest { */ path: string; /** Query parameters. Merged into the request URL alongside any already present in {@link path}. */ - query?: Record>; + query?: Record; /** Extra request headers. Only headers the connector explicitly allows are forwarded; the rest are dropped. */ headers?: Record; /** JSON request body. Ignored for `GET` and `HEAD`. */ diff --git a/src/modules/integrations.types.ts b/src/modules/integrations.types.ts index c4f37fa7..1b6c0b49 100644 --- a/src/modules/integrations.types.ts +++ b/src/modules/integrations.types.ts @@ -401,6 +401,7 @@ export type IntegrationsModule = { * * @example * ```typescript + * // Summarise text with an LLM * const response = await base44.integrations.Core.InvokeLLM({ * prompt: 'Explain quantum computing', * model: 'gpt_5' @@ -414,6 +415,7 @@ export type IntegrationsModule = { * * @example * ```typescript + * // Call a custom integration endpoint * const result = await base44.integrations.custom.call( * 'github', * 'get:/repos/{owner}/{repo}',