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. diff --git a/scripts/mintlify-post-processing/appended-articles.json b/scripts/mintlify-post-processing/appended-articles.json index 27fb69b8..f9c0df98 100644 --- a/scripts/mintlify-post-processing/appended-articles.json +++ b/scripts/mintlify-post-processing/appended-articles.json @@ -2,7 +2,14 @@ "interfaces/ConnectorsModule": [ "type-aliases/ConnectorIntegrationType", "interfaces/ConnectorIntegrationTypeRegistry", - "interfaces/UserConnectorsModule" + "interfaces/UserConnectorsModule", + "interfaces/ConnectorApiRequest", + "type-aliases/ConnectorApiQueryValue", + "interfaces/ConnectorApiResponse", + "type-aliases/ConnectorApiResponsePhase" + ], + "interfaces/AppModule": [ + "interfaces/AppPublicSettingsResponse" ], "type-aliases/EntitiesModule": [ "interfaces/EntityHandler", 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, 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", 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/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..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. */ @@ -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..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', @@ -556,7 +560,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 +568,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..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`. */ @@ -100,7 +107,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 +170,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 +455,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/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}', 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";