@lukoweb/apitogo 0.2.54 → 0.2.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/cli.js +2196 -1352
- package/dist/declarations/cli/platform/client/platform-api.d.ts +29 -0
- package/dist/declarations/cli/platform/helpers/platform-plan-catalog.d.ts +6 -0
- package/dist/declarations/config/validators/ZudokuConfig.d.ts +2 -0
- package/dist/declarations/lib/authentication/providers/openid.d.ts +2 -1
- package/dist/declarations/lib/plugins/markdown/index.d.ts +2 -1
- package/dist/flat-config.d.ts +1 -0
- package/docs/cli/commands.md +50 -32
- package/docs/cli/go-live.md +66 -93
- package/docs/cli/overview.md +18 -17
- package/docs/cli/setup.md +130 -141
- package/docs/cli/shape.md +94 -11
- package/docs/cli/walkthrough.md +1 -1
- package/docs/components/slot.mdx +116 -119
- package/docs/configuration/api-reference.md +98 -397
- package/docs/configuration/authentication.md +118 -159
- package/docs/configuration/footer.mdx +89 -118
- package/docs/configuration/make-config.mdx +2 -2
- package/docs/configuration/overview.md +97 -166
- package/docs/configuration/plans.md +100 -110
- package/docs/configuration/portal.md +116 -0
- package/docs/customization/colors-theme.mdx +255 -278
- package/docs/customization/fonts.md +105 -110
- package/docs/customization/landing-page.md +189 -188
- package/docs/deploy/apitogo.md +13 -17
- package/docs/deployment.md +15 -9
- package/docs/guides/stripe-setup.mdx +123 -0
- package/docs/markdown/frontmatter.md +172 -173
- package/docs/mcp/go-live.md +100 -100
- package/docs/mcp/overview.md +76 -76
- package/docs/quickstart.md +88 -72
- package/docs/writing.mdx +68 -72
- package/package.json +1 -1
- package/src/config/v2/docs-navigation.ts +7 -2
- package/src/config/v2/index.ts +1 -0
- package/src/config/v2/resolve.ts +28 -0
- package/src/config/v2/rules.ts +32 -1
- package/src/config/v2/schema.ts +9 -0
- package/src/config/v2/services.ts +90 -15
- package/src/config/v2/starter-landing.ts +41 -0
- package/src/config/v2/wrapper.ts +141 -7
- package/src/config/validators/ZudokuConfig.ts +794 -792
- package/src/lib/authentication/providers/openid.tsx +6 -1
- package/src/lib/plugins/markdown/index.tsx +86 -82
- package/src/vite/dev-server.ts +9 -1
- package/src/vite/dev-ssr-config.ts +32 -0
- package/src/vite/plugin-config.ts +4 -2
- package/src/vite/plugin-docs.ts +213 -205
- package/docs/concepts/auth-provider-api-identities.md +0 -105
- package/docs/configuration/ai-assistants.md +0 -65
- package/docs/configuration/api-catalog.md +0 -109
- package/docs/configuration/authentication-auth0.md +0 -181
- package/docs/configuration/authentication-azure-ad.md +0 -245
- package/docs/configuration/authentication-clerk.md +0 -117
- package/docs/configuration/authentication-firebase.md +0 -69
- package/docs/configuration/authentication-pingfederate.md +0 -143
- package/docs/configuration/authentication-supabase.md +0 -233
- package/docs/configuration/build-configuration.mdx +0 -147
- package/docs/configuration/docs.md +0 -282
- package/docs/configuration/llms.md +0 -90
- package/docs/configuration/manifest.md +0 -129
- package/docs/configuration/navigation.mdx +0 -415
- package/docs/configuration/protected-routes.md +0 -150
- package/docs/configuration/search.md +0 -164
- package/docs/configuration/sentry.mdx +0 -44
- package/docs/configuration/site.md +0 -124
- package/docs/configuration/slots.mdx +0 -125
- package/docs/configuration/vite-config.md +0 -18
- package/docs/custom-plugins.md +0 -285
- package/docs/deploy/apache-nginx.md +0 -41
- package/docs/deploy/cloudflare-pages.md +0 -74
- package/docs/deploy/direct-upload.md +0 -17
- package/docs/deploy/github-pages.md +0 -49
- package/docs/deploy/vercel.md +0 -101
- package/docs/extending/events.md +0 -124
- package/docs/guides/environment-variables.md +0 -94
- package/docs/guides/managing-api-keys-and-identities.md +0 -89
- package/docs/guides/navigation-rules.mdx +0 -203
- package/docs/guides/processors.mdx +0 -234
- package/docs/guides/transforming-examples.md +0 -156
- package/docs/guides/using-multiple-apis.md +0 -87
- package/docs/plugins.md +0 -24
|
@@ -90,6 +90,7 @@ export class OpenIDAuthenticationProvider
|
|
|
90
90
|
protected readonly redirectToAfterSignOut: string;
|
|
91
91
|
private readonly audience?: string;
|
|
92
92
|
private readonly scopes: string[];
|
|
93
|
+
private readonly tokenIdentity: boolean;
|
|
93
94
|
|
|
94
95
|
constructor({
|
|
95
96
|
issuer,
|
|
@@ -100,6 +101,7 @@ export class OpenIDAuthenticationProvider
|
|
|
100
101
|
redirectToAfterSignOut = "/",
|
|
101
102
|
basePath,
|
|
102
103
|
scopes,
|
|
104
|
+
tokenIdentity = true,
|
|
103
105
|
}: OpenIDAuthenticationConfig) {
|
|
104
106
|
super();
|
|
105
107
|
this.client = {
|
|
@@ -111,6 +113,7 @@ export class OpenIDAuthenticationProvider
|
|
|
111
113
|
// This is the callback URL for the OAuth provider. So it needs the base path.
|
|
112
114
|
this.callbackUrlPath = joinUrl(basePath, OPENID_CALLBACK_PATH);
|
|
113
115
|
this.scopes = scopes ?? ["openid", "profile", "email"];
|
|
116
|
+
this.tokenIdentity = tokenIdentity;
|
|
114
117
|
|
|
115
118
|
this.redirectToAfterSignUp = redirectToAfterSignUp;
|
|
116
119
|
this.redirectToAfterSignIn = redirectToAfterSignIn;
|
|
@@ -366,7 +369,9 @@ export class OpenIDAuthenticationProvider
|
|
|
366
369
|
* API behind the gateway's token check can be tried from the docs. A signed-out visitor gets no identity.
|
|
367
370
|
*/
|
|
368
371
|
getIdentities = async (): Promise<ApiIdentity[]> => {
|
|
369
|
-
|
|
372
|
+
// A gateway that checks keys, not tokens, answers the token with 401, so the option is not offered (API-129).
|
|
373
|
+
if (!this.tokenIdentity || !useAuthState.getState().isAuthenticated)
|
|
374
|
+
return [];
|
|
370
375
|
return [
|
|
371
376
|
{
|
|
372
377
|
id: "signed-in-user",
|
|
@@ -1,82 +1,86 @@
|
|
|
1
|
-
import type { MDXProps } from "mdx/types.js";
|
|
2
|
-
import type { JSX } from "react";
|
|
3
|
-
import type { ZudokuDocsConfig } from "../../../config/validators/ZudokuConfig.js";
|
|
4
|
-
import type { Toc } from "../../../vite/mdx/rehype-extract-toc-with-jsx.js";
|
|
5
|
-
import type { ApitogoPlugin } from "../../core/plugins.js";
|
|
6
|
-
|
|
7
|
-
export interface MarkdownPluginOptions extends ZudokuDocsConfig {
|
|
8
|
-
basePath: string;
|
|
9
|
-
fileImports: Record<string, () => Promise<MDXImport>>;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
1
|
+
import type { MDXProps } from "mdx/types.js";
|
|
2
|
+
import type { JSX } from "react";
|
|
3
|
+
import type { ZudokuDocsConfig } from "../../../config/validators/ZudokuConfig.js";
|
|
4
|
+
import type { Toc } from "../../../vite/mdx/rehype-extract-toc-with-jsx.js";
|
|
5
|
+
import type { ApitogoPlugin } from "../../core/plugins.js";
|
|
6
|
+
|
|
7
|
+
export interface MarkdownPluginOptions extends ZudokuDocsConfig {
|
|
8
|
+
basePath: string;
|
|
9
|
+
fileImports: Record<string, () => Promise<MDXImport>>;
|
|
10
|
+
/** Paths another page owns, such as the portal's home page at `/`: an index page keeps its own path but no alias there. */
|
|
11
|
+
reservedPaths?: string[];
|
|
12
|
+
}
|
|
13
|
+
export type MarkdownPluginDefaultOptions = Pick<
|
|
14
|
+
Frontmatter,
|
|
15
|
+
"toc" | "disablePager" | "showLastModified" | "suggestEdit" | "copyPage"
|
|
16
|
+
>;
|
|
17
|
+
|
|
18
|
+
export type Frontmatter = {
|
|
19
|
+
title?: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
category?: string;
|
|
22
|
+
draft?: boolean;
|
|
23
|
+
toc?: boolean;
|
|
24
|
+
disablePager?: boolean;
|
|
25
|
+
disable_pager?: boolean;
|
|
26
|
+
showLastModified?: boolean;
|
|
27
|
+
lastModifiedTime?: number;
|
|
28
|
+
suggestEdit?: { url: string; text?: string } | false;
|
|
29
|
+
copyPage?: boolean;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type MDXImport = {
|
|
33
|
+
tableOfContents: Toc;
|
|
34
|
+
frontmatter: Frontmatter;
|
|
35
|
+
excerpt?: string;
|
|
36
|
+
__filepath: string;
|
|
37
|
+
default: (props: MDXProps) => JSX.Element;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const INDEX_SUFFIX = "/index";
|
|
41
|
+
|
|
42
|
+
// `index.mdx` is the page of its folder: `/index` also answers at `/`, `/guides/index` at `/guides`.
|
|
43
|
+
// Without this the browser has no route for `/` (the pre-built index.html only hides that on first load).
|
|
44
|
+
// A path in `reserved` gets no alias: with a home page at `/`, `pages/index.md` took it over (API-129).
|
|
45
|
+
export const withIndexAliases = <T,>(
|
|
46
|
+
fileImports: Record<string, T>,
|
|
47
|
+
reserved: readonly string[] = [],
|
|
48
|
+
): [string, T][] => {
|
|
49
|
+
const entries = Object.entries(fileImports);
|
|
50
|
+
return entries.flatMap(([routePath, value]): [string, T][] => {
|
|
51
|
+
if (!routePath.endsWith(INDEX_SUFFIX)) return [[routePath, value]];
|
|
52
|
+
const alias = routePath.slice(0, -INDEX_SUFFIX.length) || "/";
|
|
53
|
+
return alias in fileImports || reserved.includes(alias)
|
|
54
|
+
? [[routePath, value]]
|
|
55
|
+
: [
|
|
56
|
+
[routePath, value],
|
|
57
|
+
[alias, value],
|
|
58
|
+
];
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const markdownPlugin = (
|
|
63
|
+
options: MarkdownPluginOptions,
|
|
64
|
+
): ApitogoPlugin => ({
|
|
65
|
+
getRoutes: () => {
|
|
66
|
+
return withIndexAliases(options.fileImports, options.reservedPaths).map(
|
|
67
|
+
([routePath, importPromise]) => ({
|
|
68
|
+
path: routePath,
|
|
69
|
+
lazy: async () => {
|
|
70
|
+
const { MdxPage } = await import("./MdxPage.js");
|
|
71
|
+
const { default: Component, ...props } = await importPromise();
|
|
72
|
+
return {
|
|
73
|
+
element: (
|
|
74
|
+
<MdxPage
|
|
75
|
+
basePath={options.basePath}
|
|
76
|
+
mdxComponent={Component}
|
|
77
|
+
{...props}
|
|
78
|
+
defaultOptions={options.defaultOptions}
|
|
79
|
+
/>
|
|
80
|
+
),
|
|
81
|
+
};
|
|
82
|
+
},
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
85
|
+
},
|
|
86
|
+
});
|
package/src/vite/dev-server.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { printDiagnosticsToConsole } from "../cli/common/output.js";
|
|
|
15
15
|
import { findAvailablePort } from "../cli/common/utils/ports.js";
|
|
16
16
|
import type { LoadedConfig } from "../config/config.js";
|
|
17
17
|
import { loadZudokuConfig } from "../config/loader.js";
|
|
18
|
+
import type { ZudokuConfig } from "../config/validators/ZudokuConfig.js";
|
|
18
19
|
import { createGraphQLServer } from "../lib/oas/graphql/index.js";
|
|
19
20
|
import {
|
|
20
21
|
getAppClientEntryPath,
|
|
@@ -22,6 +23,7 @@ import {
|
|
|
22
23
|
getViteConfig,
|
|
23
24
|
type ZudokuConfigEnv,
|
|
24
25
|
} from "./config.js";
|
|
26
|
+
import { SSR_CONFIG_MODULE_ID, withSsrGraphParts } from "./dev-ssr-config.js";
|
|
25
27
|
import { getDevHtml } from "./html.js";
|
|
26
28
|
import { buildPagefindDevIndex } from "./pagefind-dev-index.js";
|
|
27
29
|
import { ensurePagefindDevStub } from "./pagefind-dev-stub.js";
|
|
@@ -221,6 +223,10 @@ export class DevServer {
|
|
|
221
223
|
getAppServerEntryPath(),
|
|
222
224
|
);
|
|
223
225
|
|
|
226
|
+
const ssrConfig = await ssrEnvironment.runner.import<{
|
|
227
|
+
default: ZudokuConfig;
|
|
228
|
+
}>(SSR_CONFIG_MODULE_ID);
|
|
229
|
+
|
|
224
230
|
const hasBody = req.method !== "GET" && req.method !== "HEAD";
|
|
225
231
|
const request = new Request(
|
|
226
232
|
`${this.protocol}://${req.headers.host}${url}`,
|
|
@@ -237,7 +243,9 @@ export class DevServer {
|
|
|
237
243
|
const response = await entryServer.handleRequest({
|
|
238
244
|
template,
|
|
239
245
|
request,
|
|
240
|
-
routes: entryServer.getRoutesByConfig(
|
|
246
|
+
routes: entryServer.getRoutesByConfig(
|
|
247
|
+
withSsrGraphParts(currentConfig, ssrConfig.default),
|
|
248
|
+
),
|
|
241
249
|
basePath: currentConfig.basePath,
|
|
242
250
|
});
|
|
243
251
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ZudokuConfig } from "../config/validators/ZudokuConfig.js";
|
|
2
|
+
|
|
3
|
+
/** The config module the browser renders with; the dev server's SSR environment imports it too. */
|
|
4
|
+
export const SSR_CONFIG_MODULE_ID = "virtual:zudoku-config";
|
|
5
|
+
|
|
6
|
+
/** The config parts that hold modules of the config file's graph: plugin instances, custom-page elements, slots. */
|
|
7
|
+
type ConfigGraphParts = Pick<ZudokuConfig, "plugins" | "navigation" | "slots">;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The config the dev server renders a request with: the loaded config, with the plugins, navigation and slots of the
|
|
11
|
+
* SSR environment's own module graph.
|
|
12
|
+
*
|
|
13
|
+
* The loaded config is imported through Vite's `runnerImport`. Its module runner closes once the config file is
|
|
14
|
+
* evaluated and does not apply the React transform, but the config's plugins and components keep using it. A plugin
|
|
15
|
+
* page loaded with `lazy(() => import(...))`, such as the billing plugin's `/pricing`, then fails its server render
|
|
16
|
+
* with "Vite module runner has been closed", and a slot component (the portal footer) with "React is not defined".
|
|
17
|
+
* The browser falls back to client rendering after a hydration error. The SSR environment's copy of the config
|
|
18
|
+
* (`virtual:zudoku-config`, the module the browser renders with) imports the same file through the dev server's
|
|
19
|
+
* live runner and its plugins.
|
|
20
|
+
*/
|
|
21
|
+
export function withSsrGraphParts<T extends ConfigGraphParts>(
|
|
22
|
+
config: T,
|
|
23
|
+
ssrConfig: ConfigGraphParts | undefined,
|
|
24
|
+
): T {
|
|
25
|
+
if (!ssrConfig) return config;
|
|
26
|
+
return {
|
|
27
|
+
...config,
|
|
28
|
+
...(ssrConfig.plugins?.length ? { plugins: ssrConfig.plugins } : {}),
|
|
29
|
+
...(ssrConfig.navigation ? { navigation: ssrConfig.navigation } : {}),
|
|
30
|
+
...(ssrConfig.slots ? { slots: ssrConfig.slots } : {}),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -139,12 +139,14 @@ import { runPluginTransformConfig } from "@lukoweb/apitogo/plugins";
|
|
|
139
139
|
|
|
140
140
|
const embeddedConfig = ${serializeClientConfig(loadedConfig)};
|
|
141
141
|
|
|
142
|
-
// JSON embedding drops Symbol values (React element's
|
|
143
|
-
// navigation/plugins from the TSX module so custom-page elements
|
|
142
|
+
// JSON embedding drops Symbol values (React element's $typeof) and functions. Prefer live
|
|
143
|
+
// navigation/plugins/slots from the TSX module so custom-page elements and slot components (the
|
|
144
|
+
// portal footer, API-129) stay valid.
|
|
144
145
|
const config = await runPluginTransformConfig({
|
|
145
146
|
...embeddedConfig,
|
|
146
147
|
navigation: rawConfig?.navigation ?? embeddedConfig.navigation,
|
|
147
148
|
plugins: rawConfig?.plugins ?? embeddedConfig.plugins ?? [],
|
|
149
|
+
slots: rawConfig?.slots ?? embeddedConfig.slots,
|
|
148
150
|
__meta: ${JSON.stringify(clientMeta)},
|
|
149
151
|
});
|
|
150
152
|
export default config;
|