Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
5147b18
docs(backend,shared): Generate typedoc output for backend docs
alexisintech Jun 13, 2026
49b7e87
docs(backend): Extract backend API methods into per-method MDX pages
alexisintech Jun 15, 2026
daceb9d
docs(backend,shared): Extract OrganizationAPI methods into per-method…
alexisintech Jun 17, 2026
9f65eee
fix broken organization API links
alexisintech Jun 17, 2026
6273c3f
fix(backend): enumerate OrganizationApi barrel exports to avoid name …
alexisintech Jun 17, 2026
e178b28
docs review - organization
SarahSoutoul Jun 17, 2026
231cddd
document the backend deleted-object
alexisintech Jun 17, 2026
135ca40
fix(backend): enumerate typedoc endpoint entry points explicitly
alexisintech Jun 17, 2026
4da4276
Document Billing, Allowlist Identifier, and Domains APIs
alexisintech Jun 18, 2026
64f24dd
docs review - user
SarahSoutoul Jun 18, 2026
9cb19e5
docs review - domains, allowlist and billing
SarahSoutoul Jun 18, 2026
49556f8
apply Organization docs fixes
alexisintech Jun 18, 2026
c385aa9
custom_google --> oauth_custom_google
alexisintech Jun 18, 2026
7007c43
update CreateAllowlistIdentifierParams
alexisintech Jun 18, 2026
002391a
clean up comment formatting
alexisintech Jun 18, 2026
f89143b
fix deprecation tag missing from params table; add back deprecation t…
alexisintech Jun 18, 2026
9e53ded
Merge branch 'main' into aa/DOCS-10984
alexisintech Jun 18, 2026
88e40b8
remove organization-domain-resource from custom plugin
alexisintech Jun 18, 2026
6127d23
Document Session, Client, Invitation API
alexisintech Jun 18, 2026
d8008bf
docs review - session, invitation & client
SarahSoutoul Jun 19, 2026
ce15d96
Document RedirectUrl, EmailAddress, PhoneNumber
alexisintech Jun 22, 2026
7292df0
Document EnterpriseConnection, SignInToken, AgentTask
alexisintech Jun 23, 2026
d01b0e4
Merge branch 'main' into aa/DOCS-10984
SarahSoutoul Jun 23, 2026
f7b8344
docs review - agent task, enterpriseconnection, sign in token
SarahSoutoul Jun 23, 2026
f14ab96
Document TestingToken, WaitlistEntry, Machine
alexisintech Jun 23, 2026
5102f77
Document M2MToken, APIKeys, OAuthApplication
alexisintech Jun 24, 2026
f526dd7
docs review - Testing Tokens, Waitlist Entries, and Machines APIs
SarahSoutoul Jun 24, 2026
513aed8
The timestamp --> The Unix timestamp
alexisintech Jun 24, 2026
ae0daa5
update types; handle changes to non-backend files
alexisintech Jun 29, 2026
80943b4
Merge branch 'main' into aa/DOCS-10984
alexisintech Jun 29, 2026
0653031
link fixes
alexisintech Jun 29, 2026
4680036
fix: correct m2-m-token-api slug in file-structure snapshot
alexisintech Jun 29, 2026
21c14d6
small copy change to list methods
alexisintech Jun 29, 2026
e4c482f
inline OrganizationDomainBulkOwnershipVerificationError and handle it…
alexisintech Jun 29, 2026
125b88f
docs(backend): mark getHandshakePayload as @internal
jacekradko Jun 29, 2026
90a053d
apply suggestions from coderabbit
alexisintech Jun 29, 2026
f3072bd
Document Instance API
alexisintech Jun 29, 2026
ef02903
docs review - Instance API
SarahSoutoul Jun 30, 2026
da89b29
remove two nonexistent links
alexisintech Jun 30, 2026
c1e7922
Merge branch 'main' into aa/DOCS-10984
SarahSoutoul Jun 30, 2026
f489c4d
Document revokeToken method
alexisintech Jun 30, 2026
a27b2d1
fix(backend): drop OrganizationApi UpdateParams from barrel to avoid …
alexisintech Jun 30, 2026
e65134a
capitalize Agent Task
alexisintech Jun 30, 2026
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
2 changes: 2 additions & 0 deletions .changeset/docs-backend-typedoc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
5 changes: 5 additions & 0 deletions .typedoc/__tests__/__snapshots__/clerk-properties.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@
| <a id="proxyurl"></a> `proxyUrl` | <code>undefined \| string</code> | **Required for applications that run behind a reverse proxy**. Your Clerk app's proxy URL. Can be either a relative path (`/__clerk`) or a full URL (`https://<your-domain>/__clerk`). |
| <a id="publishablekey"></a> `publishableKey` | `string` | Your Clerk [Publishable Key](!publishable-key). |
| <a id="sdkmetadata"></a> `sdkMetadata` | <code>undefined \| \{ environment?: string; name: string; version: string; \}</code> | If present, contains information about the SDK that the host application is using. For example, if Clerk is loaded through `@clerk/nextjs`, this would be `{ name: '@clerk/nextjs', version: '1.0.0' }`. You don't need to set this value yourself unless you're [developing an SDK](/docs/guides/development/sdk-development/overview). |
| `sdkMetadata.environment?` | `string` | Typically this will be the `NODE_ENV` that the SDK is currently running in. |
| `sdkMetadata.name` | `string` | The npm package name of the SDK. |
| `sdkMetadata.version` | `string` | The npm package version of the SDK. |
| <a id="session"></a> `session` | <code>undefined \| null \| [SignedInSessionResource](/docs/reference/objects/session)</code> | The currently active `Session`, which is guaranteed to be one of the sessions in `Client.sessions`. If there is no active session, this field will be `null`. If the session is loading, this field will be `undefined`. |
| <a id="status"></a> `status` | <code>"error" \| "degraded" \| "loading" \| "ready"</code> | The status of the `Clerk` instance. Possible values are: <ul> <li>`"error"`: Set when hotloading `clerk-js` or `Clerk.load()` failed.</li> <li>`"loading"`: Set during initialization.</li> <li>`"ready"`: Set when Clerk is fully operational.</li> <li>`"degraded"`: Set when Clerk is partially operational.</li> </ul> |
| <a id="telemetry"></a> `telemetry` | <code>undefined \| \{ isDebug: boolean; isEnabled: boolean; record: void; recordLog: void; \}</code> | [Telemetry](/docs/guides/how-clerk-works/security/clerk-telemetry) configuration. |
| `telemetry.isDebug` | `boolean` | If `true`, telemetry events are only logged to the console and not sent to Clerk. |
| `telemetry.isEnabled` | `boolean` | Indicates whether telemetry is enabled. |
| <a id="uiversion"></a> `uiVersion` | <code>undefined \| string</code> | The version of `@clerk/ui` that is currently loaded, or `undefined` if the prebuilt UI has not been loaded yet. |
| <a id="user"></a> `user` | <code>undefined \| null \| [UserResource](/docs/reference/objects/user)</code> | A shortcut to `Session.user` which holds the currently active `User` object. If the session is `null` or `undefined`, the user field will match. |
| <a id="version"></a> `version` | <code>undefined \| string</code> | The Clerk SDK version number. |
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
| Property | Type | Description |
| ------ | ------ | ------ |
| `verification` | <code>null \| \{ createdSessionId: string; status: "expired" \| "failed" \| "verified" \| "client_mismatch"; verifiedFromTheSameClient: boolean; \}</code> | The verification status of the email link. This property is populated by reading query parameters from the URL after the user visits the email link. Returns `null` if no verification status is available. |
| `verification.createdSessionId` | `string` | The ID of the session that was created upon completion of the current sign-in. |
| `verification.status` | <code>"expired" \| "failed" \| "verified" \| "client_mismatch"</code> | The verification status. |
| `verification.verifiedFromTheSameClient` | `boolean` | Whether the verification was from the same client. |
42 changes: 42 additions & 0 deletions .typedoc/__tests__/file-structure.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,48 @@ describe('Typedoc output', () => {

expect(nestedFolders).toMatchInlineSnapshot(`
[
"backend/agent-task-api",
"backend/agent-task-api/methods",
"backend/allowlist-identifier-api",
"backend/allowlist-identifier-api/methods",
"backend/api-keys-api",
"backend/api-keys-api/methods",
"backend/billing-api",
"backend/billing-api/methods",
"backend/client-api",
"backend/client-api/methods",
"backend/domain-api",
"backend/domain-api/methods",
"backend/email-address-api",
"backend/email-address-api/methods",
"backend/enterprise-connection-api",
"backend/enterprise-connection-api/methods",
"backend/instance-api",
"backend/instance-api/methods",
"backend/invitation-api",
"backend/invitation-api/methods",
"backend/m2-m-token-api",
"backend/m2-m-token-api/methods",
"backend/machine-api",
"backend/machine-api/methods",
"backend/o-auth-applications-api",
"backend/o-auth-applications-api/methods",
"backend/organization-api",
"backend/organization-api/methods",
"backend/phone-number-api",
"backend/phone-number-api/methods",
"backend/redirect-url-api",
"backend/redirect-url-api/methods",
"backend/session-api",
"backend/session-api/methods",
"backend/sign-in-token-api",
"backend/sign-in-token-api/methods",
"backend/testing-token-api",
"backend/testing-token-api/methods",
"backend/user-api",
"backend/user-api/methods",
"backend/waitlist-entry-api",
"backend/waitlist-entry-api/methods",
"react/legacy",
"shared/api-key-resource",
"shared/api-key-resource/methods",
Expand Down
86 changes: 85 additions & 1 deletion .typedoc/custom-plugin.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// @ts-check - Enable TypeScript checks for safer MDX post-processing and link rewriting
import { Converter } from 'typedoc';
import { Converter, DeclarationReflection, ReflectionKind, ReflectionType, RendererEvent } from 'typedoc';
import { MarkdownPageEvent } from 'typedoc-plugin-markdown';

/**
Expand Down Expand Up @@ -75,6 +75,7 @@ const LINK_REPLACEMENTS = [
['o-auth-consent-info', '/docs/reference/types/oauth-consent-info'],
['o-auth-consent-scope', '/docs/reference/types/oauth-consent-scope'],
['o-auth-strategy', '/docs/reference/types/sso#o-auth-strategy'],
['o-auth-provider', '/docs/reference/types/sso#o-auth-provider'],
['session', '/docs/reference/backend/types/backend-session'],
['session-activity', '/docs/reference/backend/types/backend-session-activity'],
['organization', '/docs/reference/backend/types/backend-organization'],
Expand All @@ -101,6 +102,7 @@ const LINK_REPLACEMENTS = [
['confirm-checkout-params', '/docs/reference/types/billing-checkout-resource#parameters'],
['billing-payment-method-resource', '/docs/reference/types/billing-payment-method-resource'],
['billing-payer-resource', '/docs/reference/types/billing-payer-resource'],
['billing-plan-price', '/docs/reference/types/billing-plan-price'],
['billing-plan-resource', '/docs/reference/types/billing-plan-resource'],
['billing-plan-unit-price', '/docs/reference/types/billing-plan-unit-price'],
['billing-plan-unit-price-tier', '/docs/reference/types/billing-plan-unit-price-tier'],
Expand Down Expand Up @@ -130,6 +132,10 @@ const LINK_REPLACEMENTS = [
['session-task', '/docs/reference/types/session-task'],
['public-user-data', '/docs/reference/types/public-user-data'],
['session-status', '/docs/reference/types/session-status'],
[
'create-organization-invitation-params',
'/docs/reference/backend/organization/create-organization-invitation#create-organization-invitation-params',
],
['create-organization-domain-params', '#create-organization-domain-params'],
['organization-domain-verification', '/docs/reference/types/organization-domain-resource'],
];
Expand Down Expand Up @@ -215,6 +221,10 @@ function getCatchAllReplacements() {
pattern: /(?<![\[\w`#])`?LocalizationResource`?(?![\]\w`])/g,
replace: '[LocalizationResource](/docs/guides/customizing-clerk/localization)',
},
{
pattern: /(?<![\[\w`#])`?Machine`?(?![\]\w`])/g,
replace: '[Machine](/docs/reference/backend/types/backend-machine)',
},
{
pattern: /(?<![\[\w`#])`?PasskeyResource`?(?![\]\w`])/g,
replace: '[PasskeyResource](/docs/reference/types/passkey-resource)',
Expand Down Expand Up @@ -293,6 +303,10 @@ function getCatchAllReplacements() {
pattern: /(?<![\[\w`#])`?OAuthStrategy`?(?![\]\w`])/g,
replace: '[OAuthStrategy](/docs/reference/types/sso#o-auth-strategy)',
},
{
pattern: /(?<![\[\w`#])`?OAuthProvider`?(?![\]\w`])/g,
replace: '[OAuthProvider](/docs/reference/types/sso#o-auth-provider)',
},
{
pattern: /(?<![\[\w`#])`?OrganizationResource`?(?![\]\w`])/g,
replace: '[OrganizationResource](/docs/reference/objects/organization)',
Expand Down Expand Up @@ -468,6 +482,33 @@ export function applyCatchAllMdReplacements(contents) {
.join('\n');
}

/**
* Walk a typedoc Type and return a flat list of property declarations to render as a merged table. Used by the `@expandProperties` flattener below to handle three shapes:
* - intersection types: walk each constituent
* - inline object literals (ReflectionType): take its declaration.children
* - named references (ReferenceType): take the target's children plus any properties contributed via type arguments, which captures the `Foo<{ ... }>` instantiation pattern where typedoc otherwise loses the generic parameter at the alias boundary.
*
* @param {import('typedoc').SomeType | undefined} type
* @param {Map<string, import('typedoc').Reflection>} reflectionsByName lookup for cross-package refs whose `.reflection` is not linked
* @returns {import('typedoc').DeclarationReflection[]}
*/
function collectPropertiesFromType(type, reflectionsByName) {
if (!type) return [];
if (type.type === 'reflection') {
return type.declaration?.children ?? [];
}
if (type.type === 'intersection') {
return type.types.flatMap(t => collectPropertiesFromType(t, reflectionsByName));
}
if (type.type === 'reference') {
const target = type.reflection ?? reflectionsByName.get(type.name);
const targetChildren = target?.children ?? [];
const argChildren = (type.typeArguments ?? []).flatMap(t => collectPropertiesFromType(t, reflectionsByName));
return [...targetChildren, ...argChildren];
Comment on lines +503 to +507

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In TypeDoc 0.28.5, where are object-literal members of a type alias like type Foo = { a: string } & Tstored:reflection.childrenorreflection.type.declaration.children?

💡 Result:

In TypeDoc 0.28.5, the object-literal members coming from a type alias like type Foo<T> = { a: string } & T end up stored under reflection.type.declaration.children (i.e., as children of the internal DeclarationReflection that belongs to the alias’s type), not under reflection.children. TypeDoc’s DeclarationReflection.getProperties() first checks this.children and, if that’s empty, falls back to this.type.declaration.children when this.type.type === "reflection" [1]. The ReflectionType model represents an object-literal-ish type by holding a declaration: DeclarationReflection [2], and it renders its members by iterating this.declaration.children [2]. Thus, for type aliases whose object literal is represented as a ReflectionType, the members are placed on reflection.type.declaration.children [2][1].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the plugin around the referenced lines.
file=".typedoc/custom-plugin.mjs"
wc -l "$file"
sed -n '470,540p' "$file"

# Find the helper and any handling of reflection/type.declaration.
rg -n "collectPropertiesFromType|type\.declaration|reflection\.children|children \?\?" "$file"

# Inspect nearby TypeDoc-related usage in the repo, if any.
rg -n "expandProperties|ClerkPaginationRequest|ClerkPaginationParams|typedoc" .

Repository: clerk/javascript

Length of output: 2017


Pull alias-backed members from the alias type .typedoc/custom-plugin.mjs:503-507 uses target?.children ?? [], but TypeDoc stores object-literal members for type aliases on target.type.declaration.children. Since children is usually an empty array, the fallback never runs and wrapper fields like limit / offset are omitted. Use an emptiness check before falling back to target.type.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.typedoc/custom-plugin.mjs around lines 503 - 507, The reference-handling
branch in collectPropertiesFromType is reading only target.children, which
misses members defined on type aliases. Update the logic for the type.type ===
'reference' path to first inspect target.children, and if that is empty then
fall back to target.type.declaration.children before combining with argChildren.
Keep the change scoped to collectPropertiesFromType and the target resolution
via type.reflection/reflectionsByName so alias-backed fields like limit and
offset are included.

}
return [];
}

/**
* @param {import('typedoc-plugin-markdown').MarkdownApplication} app
*/
Expand All @@ -483,6 +524,49 @@ export function load(app) {
}
});

/**
* Flatten the `Foo<{...}>` generic-instantiation pattern into a single merged properties table when `Foo` opts in via `@expandProperties`. typedoc-plugin-markdown would otherwise render an empty page for these aliases because the resolved type is a `ReferenceType` with no inline declaration — see `member.declaration.js` in the plugin, which only walks `IntersectionType` sub-types and has no branch for top-level `ReferenceType`.
*
* Runs at `RendererEvent.BEGIN` rather than `EVENT_RESOLVE_END` because the resolve hook fires per package, and cross-package references (e.g. `@clerk/backend` types referencing `ClerkPaginationRequest` from `@clerk/shared`) only link up after typedoc merges packages.
*
* The opt-in tag lives on the wrapper type so we never accidentally flatten unrelated generic aliases (e.g. `SignInErrors = Errors<SignInFields>`).
*/
app.renderer.on(RendererEvent.BEGIN, event => {
const all = Object.values(event.project.reflections);
const reflectionsByName = new Map();
for (const r of all) {
if (r.name && !reflectionsByName.has(r.name)) reflectionsByName.set(r.name, r);
}
const expandable = new Set();
for (const r of all) {
if (r.comment?.modifierTags?.has('@expandProperties')) {
expandable.add(r);
r.comment.modifierTags.delete('@expandProperties');
}
}
for (const reflection of all) {
if (
reflection.kindOf?.(ReflectionKind.TypeAlias) &&
reflection.type?.type === 'reference' &&
Array.isArray(reflection.type.typeArguments) &&
reflection.type.typeArguments.length > 0
) {
const target = reflection.type.reflection ?? reflectionsByName.get(reflection.type.name);
if (!target || !expandable.has(target)) continue;
const merged = collectPropertiesFromType(reflection.type, reflectionsByName);
if (merged.length > 0) {
// typedoc's package-level `sort: 'alphabetical'` is applied during conversion, before
// our synthetic merge runs. Sort here to match the alphabetical ordering used by
// every other table in the docs.
merged.sort((a, b) => a.name.localeCompare(b.name));
const decl = new DeclarationReflection('__type', ReflectionKind.TypeLiteral, reflection);
decl.children = merged;
reflection.type = new ReflectionType(decl);
}
}
}
});

app.renderer.on(MarkdownPageEvent.END, output => {
const fileName = output.url.split('/').pop();

Expand Down
Loading
Loading