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
3 changes: 2 additions & 1 deletion scripts/mintlify-post-processing/appended-articles.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"type-aliases/EntitiesModule": [
"interfaces/EntityHandler",
"type-aliases/EntityRecord",
"interfaces/EntityTypeRegistry"
"interfaces/EntityTypeRegistry",
"type-aliases/SortField"
],
"interfaces/FunctionsModule": [
"type-aliases/FunctionName",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,79 @@ function applyNonExposedTypeLinkRemoval(dir, exposedTypeNames) {
}
}

/**
* Add clickable links for types in ParamFields that reference types on the same page
*/
function addTypeLinksToParamFields(dir) {
if (!fs.existsSync(dir)) return;
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
const entryPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
addTypeLinksToParamFields(entryPath);
} else if (
entry.isFile() &&
(entry.name.endsWith(".mdx") || entry.name.endsWith(".md"))
) {
let content = fs.readFileSync(entryPath, "utf-8");
let modified = false;

// Integrate clickable link into the description for SortField type
// Pattern: <ParamField ... type="SortField<T>">\n\nSort parameter, ...
// Replace with: <ParamField ... type="SortField<T>">\n\nA [`SortField<T>`](#sortfield) specifying sort order, ...
const paramFieldPattern = /(<ParamField [^>]*type=")(SortField<([^>]*)>)("[^>]*>\n\n)Sort parameter,/g;

content = content.replace(paramFieldPattern, (match, prefix, fullType, generic, suffix) => {
modified = true;
return `${prefix}${fullType}${suffix}A [\`${fullType}\`](#sortfield) specifying sort order,`;
});

if (modified) {
fs.writeFileSync(entryPath, content, "utf-8");
console.log(`Added type links to ParamFields: ${path.relative(DOCS_DIR, entryPath)}`);
}
}
}
}

/**
* Clean up SortField type signature to be more readable
*/
function cleanupSortFieldSignature(dir) {
if (!fs.existsSync(dir)) return;
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
const entryPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
cleanupSortFieldSignature(entryPath);
} else if (
entry.isFile() &&
(entry.name.endsWith(".mdx") || entry.name.endsWith(".md"))
) {
let content = fs.readFileSync(entryPath, "utf-8");
let modified = false;

// Replace the complex SortField signature with a cleaner version
// Match: > **SortField**\<`T`\> = ... & ... | `` `+${(...) & (...)}` `` | `` `-${(...) & (...)}` ``
// Replace with: > **SortField**\<`T`\> = `string` | `` `+${string}` `` | `` `-${string}` ``
const sortFieldSignaturePattern = /> \*\*SortField\*\*\\<`T`\\> = \.\.\. & \.\.\. \| `` `\+\$\{\(\.\.\.\) & \(\.\.\.\)\}` `` \| `` `-\$\{\(\.\.\.\) & \(\.\.\.\)\}` ``/;

if (sortFieldSignaturePattern.test(content)) {
content = content.replace(
sortFieldSignaturePattern,
"> **SortField**\\<`T`\\> = `keyof T` | `` `+${keyof T}` `` | `` `-${keyof T}` ``"
);
modified = true;
}

if (modified) {
fs.writeFileSync(entryPath, content, "utf-8");
console.log(`Cleaned SortField signature: ${path.relative(DOCS_DIR, entryPath)}`);
}
}
}
}

/**
* Main function
*/
Expand Down Expand Up @@ -1288,6 +1361,12 @@ function main() {
const appendedArticles = loadAppendedArticlesConfig();
applyAppendedArticles(appendedArticles);

// Add clickable links for types in ParamFields
addTypeLinksToParamFields(DOCS_DIR);

// Clean up SortField signature specifically (before general signature cleanup)
cleanupSortFieldSignature(DOCS_DIR);

// Clean up signatures: fix truncated generics, simplify keyof constraints, break long lines
applySignatureCleanup(DOCS_DIR);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,23 @@ function parseParametersWithExpansion(
if (!line) return null;
const trimmed = line.trim();

// Handle [`TypeName`](link) format first (backticks inside the link)
// Handle [`TypeName`](link)\<`T`\> format (with generics after the link)
const linkWithBackticksAndGenericsMatch = trimmed.match(/^\[`([^`]+)`\]\(([^)]+)\)(.*)$/);
if (linkWithBackticksAndGenericsMatch) {
const typeName = linkWithBackticksAndGenericsMatch[1];
const link = linkWithBackticksAndGenericsMatch[2];
const generics = linkWithBackticksAndGenericsMatch[3].trim();

// If there are generics, append them to the type name (cleaning up markdown escapes)
const fullType = generics ? typeName + generics.replace(/\\/g, '') : typeName;

return {
type: fullType,
link: link,
};
}

// Handle [`TypeName`](link) format (backticks inside the link, no generics)
const linkWithBackticksMatch = trimmed.match(/^\[`([^`]+)`\]\(([^)]+)\)$/);
if (linkWithBackticksMatch) {
return {
Expand Down Expand Up @@ -518,6 +534,7 @@ function parseParametersWithExpansion(
params.push({
name: cleanName,
type: type,
typeLink: typeLink, // Preserve the link
description: descriptionLines.join("\n").trim(),
optional,
nested,
Expand Down Expand Up @@ -571,7 +588,23 @@ function parseParameters(
if (!line) return null;
const trimmed = line.trim();

// Handle [`TypeName`](link) format first (backticks inside the link)
// Handle [`TypeName`](link)\<`T`\> format (with generics after the link)
const linkWithBackticksAndGenericsMatch = trimmed.match(/^\[`([^`]+)`\]\(([^)]+)\)(.*)$/);
if (linkWithBackticksAndGenericsMatch) {
const typeName = linkWithBackticksAndGenericsMatch[1];
const link = linkWithBackticksAndGenericsMatch[2];
const generics = linkWithBackticksAndGenericsMatch[3].trim();

// If there are generics, append them to the type name (cleaning up markdown escapes)
const fullType = generics ? typeName + generics.replace(/\\/g, '') : typeName;

return {
type: fullType,
link: link,
};
}

// Handle [`TypeName`](link) format (backticks inside the link, no generics)
const linkWithBackticksMatch = trimmed.match(/^\[`([^`]+)`\]\(([^)]+)\)$/);
if (linkWithBackticksMatch) {
return {
Expand Down Expand Up @@ -826,16 +859,16 @@ function buildParamFieldsSection(
for (const param of params) {
const requiredAttr = param.optional ? "" : " required";

// Track non-primitive parameter types for suppression

fieldsOutput += `<ParamField body="${param.name}" type="${param.type}"${requiredAttr}>\n`;
// Clean up the type string by removing markdown backticks
let typeAttr = param.type.replace(/`/g, '');
fieldsOutput += `<ParamField body="${param.name}" type="${typeAttr}"${requiredAttr}>\n`;

// Always show description in ParamField if it exists
if (param.description) {
fieldsOutput += `\n${param.description}\n`;
fieldsOutput += `\n${param.description}`;
}

fieldsOutput += "\n</ParamField>\n";
fieldsOutput += "\n\n</ParamField>\n";

// If param has nested fields, wrap them in an Accordion
if (param.nested.length > 0) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[
"DeleteManyResult",
"DeleteResult",
"ImportResult"
"ImportResult",
"SortField"
]
1 change: 1 addition & 0 deletions scripts/mintlify-post-processing/types-to-expose.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@
"ImportResult",
"IntegrationsModule",
"CoreIntegrations",
"SortField",
"SsoModule"
]
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export type {
RealtimeEventType,
RealtimeEvent,
RealtimeCallback,
SortField,
} from "./modules/entities.types.js";

export type {
Expand Down
12 changes: 7 additions & 5 deletions src/modules/entities.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,16 @@ export interface ImportResult<T = any> {
/**
* Sort field type for entity queries.
*
* Supports ascending (no prefix or `'+'`) and descending (`'-'`) sorting.
* Accepts any field name from the entity type with an optional prefix:
* - `'+'` prefix or no prefix: ascending sort
* - `'-'` prefix: descending sort
*
* @typeParam T - The entity type to derive sortable fields from.
*
* @example
* ```typescript
* // Ascending sort (default)
* // Specify sort direction by prefixing field names with + or -
* // Ascending sort
* 'created_date'
* '+created_date'
*
Expand All @@ -81,7 +84,7 @@ export type SortField<T> =
| `-${keyof T & string}`;

/**
* Fields added by the server to every entity record (id, dates, created_by, etc.).
* Fields added by the server to every entity record, such as `id`, `created_date`, `updated_date`, and `created_by`.
*/
interface ServerEntityFields {
/** Unique identifier of the record */
Expand All @@ -108,8 +111,7 @@ export interface EntityTypeRegistry {}
*
* @example
* ```typescript
* import type { EntityRecord } from '@base44/sdk';
*
* // Using EntityRecord to get the complete type for an entity
* // Combine your schema with server fields (id, created_date, etc.)
* type TaskRecord = EntityRecord['Task'];
*
Expand Down