Compare commits

..

2 Commits

Author SHA1 Message Date
Samy Pessé c0b339e406 Version Packages (#3075)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-04-02 13:36:04 +02:00
Nolann B. da485f5144 Fix read-only in generateSchemaExample (#3069) 2025-04-02 13:03:51 +02:00
20 changed files with 138 additions and 192 deletions
-6
View File
@@ -1,6 +0,0 @@
---
'@gitbook/react-openapi': patch
'gitbook': patch
---
Fix missing headers in OpenAPIResponses
-6
View File
@@ -1,6 +0,0 @@
---
'@gitbook/react-openapi': patch
'gitbook': patch
---
Fix OpenAPI enum display
+7 -7
View File
@@ -35,7 +35,7 @@
},
"packages/colors": {
"name": "@gitbook/colors",
"version": "0.3.1",
"version": "0.3.0",
"devDependencies": {
"typescript": "^5.5.3",
},
@@ -49,7 +49,7 @@
},
"packages/gitbook": {
"name": "gitbook",
"version": "0.9.1",
"version": "0.8.2",
"dependencies": {
"@gitbook/api": "*",
"@gitbook/cache-do": "workspace:*",
@@ -136,7 +136,7 @@
},
"packages/gitbook-v2": {
"name": "gitbook-v2",
"version": "0.2.3",
"version": "0.2.2",
"dependencies": {
"@gitbook/api": "*",
"@gitbook/cache-tags": "workspace:*",
@@ -162,7 +162,7 @@
"name": "@gitbook/icons",
"version": "0.2.0",
"bin": {
"gitbook-icons": "./bin/gitbook-icons.js"
"gitbook-icons": "./bin/gitbook-icons.js",
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.6.0",
@@ -180,7 +180,7 @@
},
"packages/openapi-parser": {
"name": "@gitbook/openapi-parser",
"version": "2.1.2",
"version": "2.1.1",
"dependencies": {
"@scalar/openapi-parser": "^0.10.10",
"@scalar/openapi-types": "^0.1.9",
@@ -219,7 +219,7 @@
"name": "@gitbook/react-math",
"version": "0.6.0",
"bin": {
"gitbook-math": "./bin/gitbook-math.js"
"gitbook-math": "./bin/gitbook-math.js",
},
"dependencies": {
"object-hash": "^3.0.0",
@@ -234,7 +234,7 @@
},
"packages/react-openapi": {
"name": "@gitbook/react-openapi",
"version": "1.1.8",
"version": "1.1.6",
"dependencies": {
"@gitbook/openapi-parser": "workspace:*",
"@scalar/api-client-react": "^1.2.5",
@@ -179,9 +179,4 @@ export interface GitBookDataFetcher {
integrationName: string;
request: api.RenderIntegrationUI;
}): Promise<DataFetcherResponse<api.ContentKitRenderOutput>>;
getAction(params: {
url: string
claims: any
}): Promise<DataFetcherResponse<{ text: string; url: string; icon?: string }>>;
}
+11
View File
@@ -1,5 +1,16 @@
# gitbook
## 0.9.2
### Patch Changes
- da7b369: Fix missing headers in OpenAPIResponses
- 139a805: Fix OpenAPI enum display
- Updated dependencies [da7b369]
- Updated dependencies [da485f5]
- Updated dependencies [139a805]
- @gitbook/react-openapi@1.1.9
## 0.9.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "gitbook",
"version": "0.9.1",
"version": "0.9.2",
"private": true,
"scripts": {
"dev": "env-cmd --silent -f ../../.env.local next dev",
@@ -25,21 +25,10 @@ export async function POST(req: NextRequest) {
);
}
try {
const result = await revalidateTags(json.tags);
return NextResponse.json({
success: true,
stats: result.stats,
});
} catch (err: unknown) {
return NextResponse.json(
{
error: 'Failed to revalidate tags',
message: err instanceof Error ? err.message : 'Internal Server Error',
stack: err instanceof Error ? err.stack : '',
},
{ status: 500 }
);
}
const result = await revalidateTags(json.tags);
return NextResponse.json({
success: true,
stats: result.stats,
});
}
@@ -13,7 +13,6 @@ import assertNever from 'assert-never';
import { Annotation } from './Annotation/Annotation';
import type { DocumentContextProps } from './DocumentView';
import { Emoji } from './Emoji';
import { InlineAction } from './InlineAction';
import { InlineImage } from './InlineImage';
import { InlineLink } from './InlineLink';
import { InlineMath } from './Math';
@@ -62,8 +61,6 @@ export function Inline<
return <Mention {...contextProps} inline={inline} />;
case 'inline-image':
return <InlineImage {...contextProps} inline={inline} />;
case 'action':
return <InlineAction {...contextProps} inline={inline} />;
default:
assertNever(inline);
}
@@ -1,33 +0,0 @@
import { getVisitorAuthClaims } from '@/lib/adaptive';
import { getDataOrNull } from '@v2/lib/data';
import { getSiteURLDataFromMiddleware } from '@v2/lib/middleware';
import type { InlineProps } from './Inline';
import { TrackEventButton } from './TrackEventButton';
export async function InlineAction(props: InlineProps<any>) {
const { inline, context } = props;
if (!context.contentContext) {
throw new Error('inline action requires a contentContext');
}
const action = inline.data.action;
if (action.type === 'url') {
return <TrackEventButton action={inline.data.action} resolved={{ url: action.url, text: action.text }} />
}
// API action
const { dataFetcher } = context.contentContext;
const siteData = await getSiteURLDataFromMiddleware();
const claims = getVisitorAuthClaims(siteData)
const resolved = await getDataOrNull(dataFetcher.getAction({ url: inline.data.action.url, claims }));
if (!resolved) {
throw new Error('inline action not found');
}
return <TrackEventButton action={inline.data.action} resolved={resolved} />
}
@@ -1,36 +0,0 @@
'use client';
import { tcls } from '@/lib/tailwind';
import { useTrackEvent } from '../Insights';
import { LoadingButton } from '../primitives';
export function TrackEventButton(props: {
action: any;
resolved: { url: string; text: string };
}) {
const { action, resolved } = props;
const trackEvent = useTrackEvent();
return (
<LoadingButton
onClick={async () => {
trackEvent({ type: 'action_click', action: action });
window.open(resolved.url, '_blank', 'noopener noreferrer');
}}
href={resolved.url}
variant="primary"
size="medium"
className={tcls(
'theme-bold:bg-header-link theme-bold:text-header-background theme-bold:shadow-none theme-bold:hover:bg-header-link theme-bold:hover:text-header-background theme-bold:hover:shadow-none'
)}
// insights={{
// type: 'link_click',
// link: {
// target: linkTarget,
// position: SiteInsightsLinkPosition.Header,
// },
// }}
>
{resolved.text}
</LoadingButton>
);
}
@@ -93,7 +93,6 @@ export function InsightsProvider(props: InsightsProviderProps) {
const flushEventsSync = useEventCallback(() => {
const session = getSession();
const visitorId = visitorIdRef.current;
console.log('flushEventsSync');
if (!visitorId) {
throw new Error('Visitor ID should be set before flushing events');
}
@@ -127,8 +126,6 @@ export function InsightsProvider(props: InsightsProviderProps) {
};
}
console.log('allEvents', allEvents.length)
if (allEvents.length > 0) {
if (enabled) {
sendEvents({
@@ -146,7 +143,6 @@ export function InsightsProvider(props: InsightsProviderProps) {
const visitorId = visitorIdRef.current ?? (await getVisitorId(appURL));
visitorIdRef.current = visitorId;
console.log('flushBatchedEvents');
flushEventsSync();
}, 1500);
@@ -171,8 +167,6 @@ export function InsightsProvider(props: InsightsProviderProps) {
context,
};
console.log('trackEvent', event, eventsRef.current[pathname].pageContext);
if (eventsRef.current[pathname].pageContext !== undefined) {
// If the pageId is set, we know that the page_view event has been tracked
// and we can flush the events
@@ -6,7 +6,7 @@ import { type ClassValue, tcls } from '@/lib/tailwind';
import { Link, type LinkInsightsProps } from './Link';
export type ButtonProps = {
type ButtonProps = {
href?: string;
variant?: 'primary' | 'secondary';
size?: 'default' | 'medium' | 'small';
@@ -1,16 +0,0 @@
'use client';
import { tcls } from '@/lib/tailwind';
import { useTransition } from 'react';
import { Button, type ButtonProps } from './Button';
export function LoadingButton({ href, onClick, className, ...rest }: ButtonProps & { onClick: () => Promise<void> }) {
const [isPending, startTransition] = useTransition();
const handleClick = (e) => {
e.preventDefault();
startTransition(onClick);
return false;
}
return <Button className={tcls(className, isPending ? 'animate-pulse' : '')} {...rest} onClick={handleClick} />
}
@@ -8,4 +8,3 @@ export * from './StyledLink';
export * from './DateRelative';
export * from './Emoji';
export * from './LoadingPane';
export * from './LoadingButton';
-1
View File
@@ -6,7 +6,6 @@ import { headers } from 'next/headers';
export async function shouldTrackEvents(): Promise<boolean> {
const headersList = await headers();
return true;
if (
process.env.NODE_ENV === 'development' ||
(process.env.GITBOOK_BLOCK_PAGE_VIEWS_TRACKING &&
-16
View File
@@ -270,22 +270,6 @@ async function getDataFetcherV1(): Promise<GitBookDataFetcher> {
return result;
});
},
getAction(params) {
return wrapDataFetcherError(async () => {
console.log('fetching', params.url);
const url = new URL(params.url);
Object.keys(params.claims).forEach((key) => {
url.searchParams.append(key, params.claims[key]);
});
const result = await fetch(url.toString());
console.log('fetched', result.statusText)
if (!result) {
throw new DataFetcherError('Action not found', 404);
}
return await result.json();
});
}
};
return dataFetcher;
+8
View File
@@ -1,5 +1,13 @@
# @gitbook/react-openapi
## 1.1.9
### Patch Changes
- da7b369: Fix missing headers in OpenAPIResponses
- da485f5: Fix read-only in generateSchemaExample
- 139a805: Fix OpenAPI enum display
## 1.1.8
### Patch Changes
+1 -1
View File
@@ -8,7 +8,7 @@
"default": "./dist/index.js"
}
},
"version": "1.1.8",
"version": "1.1.9",
"sideEffects": false,
"dependencies": {
"@gitbook/openapi-parser": "workspace:*",
@@ -268,6 +268,7 @@ function getExamplesFromMediaTypeObject(args: {
value: {
[root]: generateSchemaExample(mediaTypeObject.schema, {
xml: mediaType === 'application/xml',
mode: 'read',
}),
},
},
@@ -277,7 +278,11 @@ function getExamplesFromMediaTypeObject(args: {
return [
{
key: 'default',
example: { value: generateSchemaExample(mediaTypeObject.schema) },
example: {
value: generateSchemaExample(mediaTypeObject.schema, {
mode: 'read',
}),
},
},
];
}
@@ -16,14 +16,10 @@ export function generateSchemaExample(
schema: OpenAPIV3.SchemaObject,
options?: GenerateSchemaExampleOptions
): JSONValue | undefined {
return getExampleFromSchema(
schema,
{
emptyString: 'text',
...options,
},
3 // Max depth for circular references
);
return getExampleFromSchema(schema, {
emptyString: 'text',
...options,
});
}
/**
@@ -103,21 +99,6 @@ function guessFromFormat(schema: Record<string, any>, fallback = '') {
return genericExampleValues[schema.format] ?? fallback;
}
/** Map of all the results */
const resultCache = new WeakMap<Record<string, any>, any>();
/** Store result in the cache, and return the result */
function cache(schema: Record<string, any>, result: unknown) {
// Avoid unnecessary WeakMap operations for primitive values
if (typeof result !== 'object' || result === null) {
return result;
}
resultCache.set(schema, result);
return result;
}
/**
* This function takes an OpenAPI schema and generates an example from it
* Forked from : https://github.com/scalar/scalar/blob/main/packages/oas-utils/src/spec-getters/getExampleFromSchema.ts
@@ -152,8 +133,20 @@ const getExampleFromSchema = (
},
level = 0,
parentSchema?: Record<string, any>,
name?: string
name?: string,
resultCache = new WeakMap<Record<string, any>, any>()
): any => {
// Store result in the cache, and return the result
function cache(schema: Record<string, any>, result: unknown) {
// Avoid unnecessary WeakMap operations for primitive values
if (typeof result !== 'object' || result === null) {
return result;
}
resultCache.set(schema, result);
return result;
}
// Check if the result is already cached
if (resultCache.has(schema)) {
return resultCache.get(schema);
@@ -245,7 +238,8 @@ const getExampleFromSchema = (
options,
level + 1,
schema,
propertyName
propertyName,
resultCache
);
if (typeof response[propertyXmlTagName ?? propertyName] === 'undefined') {
@@ -269,7 +263,8 @@ const getExampleFromSchema = (
options,
level + 1,
schema,
exampleKey
exampleKey,
resultCache
);
}
}
@@ -290,21 +285,51 @@ const getExampleFromSchema = (
response.ANY_ADDITIONAL_PROPERTY = getExampleFromSchema(
schema.additionalProperties,
options,
level + 1
level + 1,
undefined,
undefined,
resultCache
);
}
}
if (schema.anyOf !== undefined) {
Object.assign(response, getExampleFromSchema(schema.anyOf[0], options, level + 1));
Object.assign(
response,
getExampleFromSchema(
schema.anyOf[0],
options,
level + 1,
undefined,
undefined,
resultCache
)
);
} else if (schema.oneOf !== undefined) {
Object.assign(response, getExampleFromSchema(schema.oneOf[0], options, level + 1));
Object.assign(
response,
getExampleFromSchema(
schema.oneOf[0],
options,
level + 1,
undefined,
undefined,
resultCache
)
);
} else if (schema.allOf !== undefined) {
Object.assign(
response,
...schema.allOf
.map((item: Record<string, any>) =>
getExampleFromSchema(item, options, level + 1, schema)
getExampleFromSchema(
item,
options,
level + 1,
schema,
undefined,
resultCache
)
)
.filter((item: any) => item !== undefined)
);
@@ -335,7 +360,9 @@ const getExampleFromSchema = (
{ type: 'object', allOf: schema.items.allOf },
options,
level + 1,
schema
schema,
undefined,
resultCache
);
return cache(
@@ -346,7 +373,14 @@ const getExampleFromSchema = (
// For non-objects (like strings), collect all examples
const examples = schema.items.allOf
.map((item: Record<string, any>) =>
getExampleFromSchema(item, options, level + 1, schema)
getExampleFromSchema(
item,
options,
level + 1,
schema,
undefined,
resultCache
)
)
.filter((item: any) => item !== undefined);
@@ -368,7 +402,14 @@ const getExampleFromSchema = (
const schemas = schema.items[rule].slice(0, 1);
const exampleFromRule = schemas
.map((item: Record<string, any>) =>
getExampleFromSchema(item, options, level + 1, schema)
getExampleFromSchema(
item,
options,
level + 1,
schema,
undefined,
resultCache
)
)
.filter((item: any) => item !== undefined);
@@ -380,7 +421,14 @@ const getExampleFromSchema = (
}
if (schema.items?.type) {
const exampleFromSchema = getExampleFromSchema(schema.items, options, level + 1);
const exampleFromSchema = getExampleFromSchema(
schema.items,
options,
level + 1,
undefined,
undefined,
resultCache
);
return wrapItems ? [{ [itemsXmlTagName]: exampleFromSchema }] : [exampleFromSchema];
}
@@ -407,7 +455,14 @@ const getExampleFromSchema = (
const firstOneOfItem = discriminateSchema[0];
// Return an example for the first item
return getExampleFromSchema(firstOneOfItem, options, level + 1);
return getExampleFromSchema(
firstOneOfItem,
options,
level + 1,
undefined,
undefined,
resultCache
);
}
// Check if schema has the `allOf` key
@@ -417,7 +472,14 @@ const getExampleFromSchema = (
// Loop through all `allOf` schemas
schema.allOf.forEach((allOfItem: Record<string, any>) => {
// Return an example from the schema
const newExample = getExampleFromSchema(allOfItem, options, level + 1);
const newExample = getExampleFromSchema(
allOfItem,
options,
level + 1,
undefined,
undefined,
resultCache
);
// Merge or overwrite the example
example =