@btst/stack 1.6.0 → 1.8.0
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/api/index.cjs +7 -1
- package/dist/api/index.d.cts +2 -2
- package/dist/api/index.d.mts +2 -2
- package/dist/api/index.d.ts +2 -2
- package/dist/api/index.mjs +7 -1
- package/dist/client/index.cjs +6 -2
- package/dist/client/index.d.cts +2 -1
- package/dist/client/index.d.mts +2 -1
- package/dist/client/index.d.ts +2 -1
- package/dist/client/index.mjs +6 -2
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/packages/better-stack/src/plugins/open-api/api/generator.cjs +300 -0
- package/dist/packages/better-stack/src/plugins/open-api/api/generator.mjs +284 -0
- package/dist/packages/better-stack/src/plugins/open-api/api/plugin.cjs +115 -0
- package/dist/packages/better-stack/src/plugins/open-api/api/plugin.mjs +113 -0
- package/dist/packages/better-stack/src/plugins/open-api/db.cjs +7 -0
- package/dist/packages/better-stack/src/plugins/open-api/db.mjs +5 -0
- package/dist/packages/better-stack/src/plugins/open-api/logo.cjs +8 -0
- package/dist/packages/better-stack/src/plugins/open-api/logo.mjs +6 -0
- package/dist/packages/better-stack/src/plugins/route-docs/client/components/loading/docs-skeleton.cjs +43 -0
- package/dist/packages/better-stack/src/plugins/route-docs/client/components/loading/docs-skeleton.mjs +41 -0
- package/dist/packages/better-stack/src/plugins/route-docs/client/components/pages/docs-page.cjs +794 -0
- package/dist/packages/better-stack/src/plugins/route-docs/client/components/pages/docs-page.mjs +788 -0
- package/dist/packages/better-stack/src/plugins/route-docs/client/plugin.cjs +111 -0
- package/dist/packages/better-stack/src/plugins/route-docs/client/plugin.mjs +106 -0
- package/dist/packages/better-stack/src/plugins/route-docs/generator.cjs +244 -0
- package/dist/packages/better-stack/src/plugins/route-docs/generator.mjs +227 -0
- package/dist/packages/ui/src/components/sheet.cjs +25 -0
- package/dist/packages/ui/src/components/sheet.mjs +24 -1
- package/dist/plugins/api/index.d.cts +2 -2
- package/dist/plugins/api/index.d.mts +2 -2
- package/dist/plugins/api/index.d.ts +2 -2
- package/dist/plugins/blog/api/index.d.cts +1 -1
- package/dist/plugins/blog/api/index.d.mts +1 -1
- package/dist/plugins/blog/api/index.d.ts +1 -1
- package/dist/plugins/blog/client/hooks/index.d.cts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.mts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.ts +2 -2
- package/dist/plugins/blog/client/index.d.cts +1 -1
- package/dist/plugins/blog/client/index.d.mts +1 -1
- package/dist/plugins/blog/client/index.d.ts +1 -1
- package/dist/plugins/blog/query-keys.d.cts +2 -2
- package/dist/plugins/blog/query-keys.d.mts +2 -2
- package/dist/plugins/blog/query-keys.d.ts +2 -2
- package/dist/plugins/client/index.d.cts +2 -2
- package/dist/plugins/client/index.d.mts +2 -2
- package/dist/plugins/client/index.d.ts +2 -2
- package/dist/plugins/open-api/api/index.cjs +9 -0
- package/dist/plugins/open-api/api/index.d.cts +95 -0
- package/dist/plugins/open-api/api/index.d.mts +95 -0
- package/dist/plugins/open-api/api/index.d.ts +95 -0
- package/dist/plugins/open-api/api/index.mjs +2 -0
- package/dist/plugins/route-docs/client/index.cjs +10 -0
- package/dist/plugins/route-docs/client/index.d.cts +126 -0
- package/dist/plugins/route-docs/client/index.d.mts +126 -0
- package/dist/plugins/route-docs/client/index.d.ts +126 -0
- package/dist/plugins/route-docs/client/index.mjs +1 -0
- package/dist/plugins/route-docs/client.css +3 -0
- package/dist/plugins/route-docs/style.css +19 -0
- package/dist/shared/{stack.ByOugz9d.d.cts → stack.u9iYV6vt.d.cts} +28 -3
- package/dist/shared/{stack.ByOugz9d.d.mts → stack.u9iYV6vt.d.mts} +28 -3
- package/dist/shared/{stack.ByOugz9d.d.ts → stack.u9iYV6vt.d.ts} +28 -3
- package/package.json +28 -1
- package/src/api/index.ts +14 -2
- package/src/client/index.ts +11 -4
- package/src/plugins/open-api/api/generator.ts +433 -0
- package/src/plugins/open-api/api/index.ts +8 -0
- package/src/plugins/open-api/api/plugin.ts +243 -0
- package/src/plugins/open-api/db.ts +7 -0
- package/src/plugins/open-api/logo.ts +7 -0
- package/src/plugins/route-docs/client/components/loading/docs-skeleton.tsx +82 -0
- package/src/plugins/route-docs/client/components/loading/index.tsx +1 -0
- package/src/plugins/route-docs/client/components/pages/docs-page.tsx +1240 -0
- package/src/plugins/route-docs/client/index.ts +7 -0
- package/src/plugins/route-docs/client/plugin.tsx +187 -0
- package/src/plugins/route-docs/client.css +3 -0
- package/src/plugins/route-docs/generator.ts +385 -0
- package/src/plugins/route-docs/index.ts +12 -0
- package/src/plugins/route-docs/style.css +19 -0
- package/src/types.ts +34 -2
- package/dist/shared/{stack.CcI4sYJP.d.mts → stack.DLhzx1-D.d.cts} +1 -1
- package/dist/shared/{stack.CcI4sYJP.d.ts → stack.DLhzx1-D.d.mts} +1 -1
- package/dist/shared/{stack.CcI4sYJP.d.cts → stack.DLhzx1-D.d.ts} +1 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
const React = require('react');
|
|
5
|
+
const client = require('@btst/stack/plugins/client');
|
|
6
|
+
const yar = require('@btst/yar');
|
|
7
|
+
const generator = require('../generator.cjs');
|
|
8
|
+
|
|
9
|
+
const DocsPageComponent = React.lazy(
|
|
10
|
+
() => import('./components/pages/docs-page.cjs').then((m) => ({
|
|
11
|
+
default: m.DocsPageComponent
|
|
12
|
+
}))
|
|
13
|
+
);
|
|
14
|
+
const DocsPageSkeleton = React.lazy(
|
|
15
|
+
() => import('./components/loading/docs-skeleton.cjs').then((m) => ({
|
|
16
|
+
default: m.DocsPageSkeleton
|
|
17
|
+
}))
|
|
18
|
+
);
|
|
19
|
+
const ROUTE_DOCS_QUERY_KEY = ["route-docs", "schema"];
|
|
20
|
+
let moduleStoredContext = null;
|
|
21
|
+
function getStoredContext() {
|
|
22
|
+
return moduleStoredContext;
|
|
23
|
+
}
|
|
24
|
+
async function generateSchema() {
|
|
25
|
+
if (!moduleStoredContext) {
|
|
26
|
+
return {
|
|
27
|
+
plugins: [],
|
|
28
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29
|
+
allSitemapEntries: []
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const sitemapEntries = await generator.fetchAllSitemapEntries(moduleStoredContext);
|
|
34
|
+
return generator.generateRouteDocsSchema(moduleStoredContext, sitemapEntries);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.warn("Failed to generate route docs schema:", error);
|
|
37
|
+
return generator.generateRouteDocsSchema(moduleStoredContext, []);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function createDocsMeta(config) {
|
|
41
|
+
return () => {
|
|
42
|
+
const title = config.title || "Route Documentation";
|
|
43
|
+
return [
|
|
44
|
+
{ title },
|
|
45
|
+
{ name: "title", content: title },
|
|
46
|
+
{ name: "robots", content: "noindex" }
|
|
47
|
+
];
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function DocsErrorComponent() {
|
|
51
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center min-h-screen bg-background", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
52
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-semibold text-destructive mb-2", children: "Error Loading Documentation" }),
|
|
53
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: "An error occurred while loading the documentation." })
|
|
54
|
+
] }) });
|
|
55
|
+
}
|
|
56
|
+
function createRouteDocsLoader(config) {
|
|
57
|
+
return async () => {
|
|
58
|
+
if (typeof window === "undefined" && moduleStoredContext) {
|
|
59
|
+
const { queryClient } = config;
|
|
60
|
+
try {
|
|
61
|
+
const sitemapEntries = await generator.fetchAllSitemapEntries(moduleStoredContext);
|
|
62
|
+
const schema = generator.generateRouteDocsSchema(
|
|
63
|
+
moduleStoredContext,
|
|
64
|
+
sitemapEntries
|
|
65
|
+
);
|
|
66
|
+
queryClient.setQueryData(ROUTE_DOCS_QUERY_KEY, schema);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.warn("Failed to load route docs schema:", error);
|
|
69
|
+
queryClient.setQueryData(ROUTE_DOCS_QUERY_KEY, {
|
|
70
|
+
plugins: [],
|
|
71
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
72
|
+
allSitemapEntries: []
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const routeDocsClientPlugin = (config) => {
|
|
79
|
+
return client.defineClientPlugin({
|
|
80
|
+
name: "route-docs",
|
|
81
|
+
routes: (context) => {
|
|
82
|
+
moduleStoredContext = context || null;
|
|
83
|
+
return {
|
|
84
|
+
docs: yar.createRoute("/route-docs", () => {
|
|
85
|
+
return {
|
|
86
|
+
PageComponent: () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
87
|
+
DocsPageComponent,
|
|
88
|
+
{
|
|
89
|
+
title: config.title,
|
|
90
|
+
description: config.description,
|
|
91
|
+
siteBasePath: config.siteBasePath || "/pages"
|
|
92
|
+
}
|
|
93
|
+
),
|
|
94
|
+
LoadingComponent: () => /* @__PURE__ */ jsxRuntime.jsx(DocsPageSkeleton, {}),
|
|
95
|
+
ErrorComponent: () => /* @__PURE__ */ jsxRuntime.jsx(DocsErrorComponent, {}),
|
|
96
|
+
loader: createRouteDocsLoader(config),
|
|
97
|
+
meta: createDocsMeta(config)
|
|
98
|
+
};
|
|
99
|
+
})
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
sitemap: async () => {
|
|
103
|
+
return [];
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
exports.ROUTE_DOCS_QUERY_KEY = ROUTE_DOCS_QUERY_KEY;
|
|
109
|
+
exports.generateSchema = generateSchema;
|
|
110
|
+
exports.getStoredContext = getStoredContext;
|
|
111
|
+
exports.routeDocsClientPlugin = routeDocsClientPlugin;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { lazy } from 'react';
|
|
3
|
+
import { defineClientPlugin } from '@btst/stack/plugins/client';
|
|
4
|
+
import { createRoute } from '@btst/yar';
|
|
5
|
+
import { fetchAllSitemapEntries, generateRouteDocsSchema } from '../generator.mjs';
|
|
6
|
+
|
|
7
|
+
const DocsPageComponent = lazy(
|
|
8
|
+
() => import('./components/pages/docs-page.mjs').then((m) => ({
|
|
9
|
+
default: m.DocsPageComponent
|
|
10
|
+
}))
|
|
11
|
+
);
|
|
12
|
+
const DocsPageSkeleton = lazy(
|
|
13
|
+
() => import('./components/loading/docs-skeleton.mjs').then((m) => ({
|
|
14
|
+
default: m.DocsPageSkeleton
|
|
15
|
+
}))
|
|
16
|
+
);
|
|
17
|
+
const ROUTE_DOCS_QUERY_KEY = ["route-docs", "schema"];
|
|
18
|
+
let moduleStoredContext = null;
|
|
19
|
+
function getStoredContext() {
|
|
20
|
+
return moduleStoredContext;
|
|
21
|
+
}
|
|
22
|
+
async function generateSchema() {
|
|
23
|
+
if (!moduleStoredContext) {
|
|
24
|
+
return {
|
|
25
|
+
plugins: [],
|
|
26
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
27
|
+
allSitemapEntries: []
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const sitemapEntries = await fetchAllSitemapEntries(moduleStoredContext);
|
|
32
|
+
return generateRouteDocsSchema(moduleStoredContext, sitemapEntries);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.warn("Failed to generate route docs schema:", error);
|
|
35
|
+
return generateRouteDocsSchema(moduleStoredContext, []);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function createDocsMeta(config) {
|
|
39
|
+
return () => {
|
|
40
|
+
const title = config.title || "Route Documentation";
|
|
41
|
+
return [
|
|
42
|
+
{ title },
|
|
43
|
+
{ name: "title", content: title },
|
|
44
|
+
{ name: "robots", content: "noindex" }
|
|
45
|
+
];
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function DocsErrorComponent() {
|
|
49
|
+
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-screen bg-background", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
50
|
+
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold text-destructive mb-2", children: "Error Loading Documentation" }),
|
|
51
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "An error occurred while loading the documentation." })
|
|
52
|
+
] }) });
|
|
53
|
+
}
|
|
54
|
+
function createRouteDocsLoader(config) {
|
|
55
|
+
return async () => {
|
|
56
|
+
if (typeof window === "undefined" && moduleStoredContext) {
|
|
57
|
+
const { queryClient } = config;
|
|
58
|
+
try {
|
|
59
|
+
const sitemapEntries = await fetchAllSitemapEntries(moduleStoredContext);
|
|
60
|
+
const schema = generateRouteDocsSchema(
|
|
61
|
+
moduleStoredContext,
|
|
62
|
+
sitemapEntries
|
|
63
|
+
);
|
|
64
|
+
queryClient.setQueryData(ROUTE_DOCS_QUERY_KEY, schema);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.warn("Failed to load route docs schema:", error);
|
|
67
|
+
queryClient.setQueryData(ROUTE_DOCS_QUERY_KEY, {
|
|
68
|
+
plugins: [],
|
|
69
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
70
|
+
allSitemapEntries: []
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
const routeDocsClientPlugin = (config) => {
|
|
77
|
+
return defineClientPlugin({
|
|
78
|
+
name: "route-docs",
|
|
79
|
+
routes: (context) => {
|
|
80
|
+
moduleStoredContext = context || null;
|
|
81
|
+
return {
|
|
82
|
+
docs: createRoute("/route-docs", () => {
|
|
83
|
+
return {
|
|
84
|
+
PageComponent: () => /* @__PURE__ */ jsx(
|
|
85
|
+
DocsPageComponent,
|
|
86
|
+
{
|
|
87
|
+
title: config.title,
|
|
88
|
+
description: config.description,
|
|
89
|
+
siteBasePath: config.siteBasePath || "/pages"
|
|
90
|
+
}
|
|
91
|
+
),
|
|
92
|
+
LoadingComponent: () => /* @__PURE__ */ jsx(DocsPageSkeleton, {}),
|
|
93
|
+
ErrorComponent: () => /* @__PURE__ */ jsx(DocsErrorComponent, {}),
|
|
94
|
+
loader: createRouteDocsLoader(config),
|
|
95
|
+
meta: createDocsMeta(config)
|
|
96
|
+
};
|
|
97
|
+
})
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
sitemap: async () => {
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export { ROUTE_DOCS_QUERY_KEY, generateSchema, getStoredContext, routeDocsClientPlugin };
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const z = require('zod');
|
|
4
|
+
|
|
5
|
+
function _interopNamespaceCompat(e) {
|
|
6
|
+
if (e && typeof e === 'object' && 'default' in e) return e;
|
|
7
|
+
const n = Object.create(null);
|
|
8
|
+
if (e) {
|
|
9
|
+
for (const k in e) {
|
|
10
|
+
n[k] = e[k];
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
n.default = e;
|
|
14
|
+
return n;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const z__namespace = /*#__PURE__*/_interopNamespaceCompat(z);
|
|
18
|
+
|
|
19
|
+
function extractPathParams(path) {
|
|
20
|
+
const params = [];
|
|
21
|
+
const segments = path.split("/");
|
|
22
|
+
for (const segment of segments) {
|
|
23
|
+
if (segment.startsWith(":")) {
|
|
24
|
+
params.push(segment.slice(1));
|
|
25
|
+
} else if (segment.startsWith("*:")) {
|
|
26
|
+
params.push(segment.slice(2));
|
|
27
|
+
} else if (segment === "*") {
|
|
28
|
+
params.push("_");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return params;
|
|
32
|
+
}
|
|
33
|
+
function getTypeFromZodType(zodType) {
|
|
34
|
+
if (zodType instanceof z__namespace.ZodString) return "string";
|
|
35
|
+
if (zodType instanceof z__namespace.ZodNumber) return "number";
|
|
36
|
+
if (zodType instanceof z__namespace.ZodBoolean) return "boolean";
|
|
37
|
+
if (zodType instanceof z__namespace.ZodArray) return "array";
|
|
38
|
+
if (zodType instanceof z__namespace.ZodObject) return "object";
|
|
39
|
+
if (zodType instanceof z__namespace.ZodEnum) return "enum";
|
|
40
|
+
if (zodType instanceof z__namespace.ZodLiteral) return "literal";
|
|
41
|
+
if (zodType instanceof z__namespace.ZodUnion) return "union";
|
|
42
|
+
const type = zodType.type;
|
|
43
|
+
if (type === "string") return "string";
|
|
44
|
+
if (type === "number") return "number";
|
|
45
|
+
if (type === "boolean") return "boolean";
|
|
46
|
+
if (type === "array") return "array";
|
|
47
|
+
if (type === "object") return "object";
|
|
48
|
+
return "string";
|
|
49
|
+
}
|
|
50
|
+
function processZodType(zodType) {
|
|
51
|
+
if (zodType instanceof z__namespace.ZodOptional) {
|
|
52
|
+
const innerType = zodType._def?.innerType || zodType.unwrap?.();
|
|
53
|
+
if (innerType) {
|
|
54
|
+
return processZodType(innerType);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (zodType instanceof z__namespace.ZodNullable) {
|
|
58
|
+
const innerType = zodType._def?.innerType || zodType.unwrap?.();
|
|
59
|
+
if (innerType) {
|
|
60
|
+
const innerSchema = processZodType(innerType);
|
|
61
|
+
return {
|
|
62
|
+
...innerSchema,
|
|
63
|
+
nullable: true
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (zodType instanceof z__namespace.ZodDefault) {
|
|
68
|
+
const innerType = zodType._def?.innerType;
|
|
69
|
+
const defaultValue = zodType._def?.defaultValue?.();
|
|
70
|
+
if (innerType) {
|
|
71
|
+
const innerSchema = processZodType(innerType);
|
|
72
|
+
if (defaultValue !== void 0) {
|
|
73
|
+
return {
|
|
74
|
+
...innerSchema,
|
|
75
|
+
default: defaultValue
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
return innerSchema;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (zodType instanceof z__namespace.ZodObject) {
|
|
82
|
+
const shape = zodType.shape || zodType._def?.shape?.();
|
|
83
|
+
if (shape) {
|
|
84
|
+
const properties = {};
|
|
85
|
+
const required = [];
|
|
86
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
87
|
+
if (value instanceof z__namespace.ZodType) {
|
|
88
|
+
properties[key] = processZodType(value);
|
|
89
|
+
if (!(value instanceof z__namespace.ZodOptional)) {
|
|
90
|
+
required.push(key);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
type: "object",
|
|
96
|
+
properties,
|
|
97
|
+
...required.length > 0 ? { required } : {}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (zodType instanceof z__namespace.ZodArray) {
|
|
102
|
+
const elementType = zodType._def?.type || zodType.element;
|
|
103
|
+
return {
|
|
104
|
+
type: "array",
|
|
105
|
+
items: elementType ? processZodType(elementType) : { type: "string" }
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
if (zodType instanceof z__namespace.ZodEnum) {
|
|
109
|
+
const values = zodType._def?.values || zodType.options;
|
|
110
|
+
return {
|
|
111
|
+
type: "string",
|
|
112
|
+
enum: values
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
if (zodType instanceof z__namespace.ZodLiteral) {
|
|
116
|
+
const value = zodType._def?.value || zodType.value;
|
|
117
|
+
return {
|
|
118
|
+
type: typeof value,
|
|
119
|
+
const: value
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
if (zodType instanceof z__namespace.ZodUnion) {
|
|
123
|
+
const options = zodType._def?.options || zodType.options;
|
|
124
|
+
if (options && Array.isArray(options)) {
|
|
125
|
+
return {
|
|
126
|
+
oneOf: options.map((opt) => processZodType(opt))
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (zodType._def?.coerce) {
|
|
131
|
+
const innerType = zodType._def?.innerType;
|
|
132
|
+
if (innerType) {
|
|
133
|
+
return processZodType(innerType);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
type: getTypeFromZodType(zodType)
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function isStandardSchema(obj) {
|
|
141
|
+
return obj && typeof obj === "object" && "~standard" in obj;
|
|
142
|
+
}
|
|
143
|
+
function extractQueryParams(querySchema) {
|
|
144
|
+
const params = [];
|
|
145
|
+
if (!querySchema) return params;
|
|
146
|
+
if (querySchema instanceof z__namespace.ZodObject) {
|
|
147
|
+
const shape = querySchema.shape || querySchema._def?.shape?.();
|
|
148
|
+
if (shape) {
|
|
149
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
150
|
+
if (value instanceof z__namespace.ZodType) {
|
|
151
|
+
params.push({
|
|
152
|
+
name: key,
|
|
153
|
+
type: getTypeFromZodType(value),
|
|
154
|
+
required: !(value instanceof z__namespace.ZodOptional),
|
|
155
|
+
schema: processZodType(value)
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
} else if (isStandardSchema(querySchema)) {
|
|
161
|
+
const zodSchema = querySchema;
|
|
162
|
+
if (zodSchema instanceof z__namespace.ZodObject) {
|
|
163
|
+
return extractQueryParams(zodSchema);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return params;
|
|
167
|
+
}
|
|
168
|
+
async function fetchAllSitemapEntries(context) {
|
|
169
|
+
const allEntries = [];
|
|
170
|
+
for (const [pluginKey, plugin] of Object.entries(context.plugins)) {
|
|
171
|
+
if (pluginKey === "routeDocs" || plugin.name === "route-docs") {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
if (plugin.sitemap) {
|
|
175
|
+
try {
|
|
176
|
+
const entries = await plugin.sitemap();
|
|
177
|
+
for (const entry of entries) {
|
|
178
|
+
allEntries.push({
|
|
179
|
+
...entry,
|
|
180
|
+
pluginKey
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
} catch (error) {
|
|
184
|
+
console.warn(`Failed to fetch sitemap for plugin ${pluginKey}:`, error);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return allEntries;
|
|
189
|
+
}
|
|
190
|
+
function generateRouteDocsSchema(context, sitemapEntries = []) {
|
|
191
|
+
const documentedPlugins = [];
|
|
192
|
+
const sitemapByPlugin = {};
|
|
193
|
+
for (const entry of sitemapEntries) {
|
|
194
|
+
if (!sitemapByPlugin[entry.pluginKey]) {
|
|
195
|
+
sitemapByPlugin[entry.pluginKey] = [];
|
|
196
|
+
}
|
|
197
|
+
sitemapByPlugin[entry.pluginKey].push(entry);
|
|
198
|
+
}
|
|
199
|
+
for (const [pluginKey, plugin] of Object.entries(context.plugins)) {
|
|
200
|
+
if (pluginKey === "routeDocs" || plugin.name === "route-docs") {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
const pluginRoutes = plugin.routes(context);
|
|
204
|
+
const documentedRoutes = [];
|
|
205
|
+
for (const [routeKey, route] of Object.entries(pluginRoutes)) {
|
|
206
|
+
const r = route;
|
|
207
|
+
const path = r.path;
|
|
208
|
+
const routeOptions = r.options || {};
|
|
209
|
+
const routeMeta = r.meta;
|
|
210
|
+
if (!path) continue;
|
|
211
|
+
const pathParamNames = extractPathParams(path);
|
|
212
|
+
const pathParams = pathParamNames.map((name) => ({
|
|
213
|
+
name,
|
|
214
|
+
type: "string",
|
|
215
|
+
// Path params are always strings
|
|
216
|
+
required: true
|
|
217
|
+
}));
|
|
218
|
+
const queryParams = extractQueryParams(routeOptions.query);
|
|
219
|
+
documentedRoutes.push({
|
|
220
|
+
key: routeKey,
|
|
221
|
+
path,
|
|
222
|
+
pathParams,
|
|
223
|
+
queryParams,
|
|
224
|
+
meta: routeMeta
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
if (documentedRoutes.length > 0) {
|
|
228
|
+
documentedPlugins.push({
|
|
229
|
+
key: pluginKey,
|
|
230
|
+
name: plugin.name,
|
|
231
|
+
routes: documentedRoutes,
|
|
232
|
+
sitemapEntries: sitemapByPlugin[pluginKey] || []
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
plugins: documentedPlugins,
|
|
238
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
239
|
+
allSitemapEntries: sitemapEntries
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
exports.fetchAllSitemapEntries = fetchAllSitemapEntries;
|
|
244
|
+
exports.generateRouteDocsSchema = generateRouteDocsSchema;
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
|
|
3
|
+
function extractPathParams(path) {
|
|
4
|
+
const params = [];
|
|
5
|
+
const segments = path.split("/");
|
|
6
|
+
for (const segment of segments) {
|
|
7
|
+
if (segment.startsWith(":")) {
|
|
8
|
+
params.push(segment.slice(1));
|
|
9
|
+
} else if (segment.startsWith("*:")) {
|
|
10
|
+
params.push(segment.slice(2));
|
|
11
|
+
} else if (segment === "*") {
|
|
12
|
+
params.push("_");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return params;
|
|
16
|
+
}
|
|
17
|
+
function getTypeFromZodType(zodType) {
|
|
18
|
+
if (zodType instanceof z.ZodString) return "string";
|
|
19
|
+
if (zodType instanceof z.ZodNumber) return "number";
|
|
20
|
+
if (zodType instanceof z.ZodBoolean) return "boolean";
|
|
21
|
+
if (zodType instanceof z.ZodArray) return "array";
|
|
22
|
+
if (zodType instanceof z.ZodObject) return "object";
|
|
23
|
+
if (zodType instanceof z.ZodEnum) return "enum";
|
|
24
|
+
if (zodType instanceof z.ZodLiteral) return "literal";
|
|
25
|
+
if (zodType instanceof z.ZodUnion) return "union";
|
|
26
|
+
const type = zodType.type;
|
|
27
|
+
if (type === "string") return "string";
|
|
28
|
+
if (type === "number") return "number";
|
|
29
|
+
if (type === "boolean") return "boolean";
|
|
30
|
+
if (type === "array") return "array";
|
|
31
|
+
if (type === "object") return "object";
|
|
32
|
+
return "string";
|
|
33
|
+
}
|
|
34
|
+
function processZodType(zodType) {
|
|
35
|
+
if (zodType instanceof z.ZodOptional) {
|
|
36
|
+
const innerType = zodType._def?.innerType || zodType.unwrap?.();
|
|
37
|
+
if (innerType) {
|
|
38
|
+
return processZodType(innerType);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (zodType instanceof z.ZodNullable) {
|
|
42
|
+
const innerType = zodType._def?.innerType || zodType.unwrap?.();
|
|
43
|
+
if (innerType) {
|
|
44
|
+
const innerSchema = processZodType(innerType);
|
|
45
|
+
return {
|
|
46
|
+
...innerSchema,
|
|
47
|
+
nullable: true
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (zodType instanceof z.ZodDefault) {
|
|
52
|
+
const innerType = zodType._def?.innerType;
|
|
53
|
+
const defaultValue = zodType._def?.defaultValue?.();
|
|
54
|
+
if (innerType) {
|
|
55
|
+
const innerSchema = processZodType(innerType);
|
|
56
|
+
if (defaultValue !== void 0) {
|
|
57
|
+
return {
|
|
58
|
+
...innerSchema,
|
|
59
|
+
default: defaultValue
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return innerSchema;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (zodType instanceof z.ZodObject) {
|
|
66
|
+
const shape = zodType.shape || zodType._def?.shape?.();
|
|
67
|
+
if (shape) {
|
|
68
|
+
const properties = {};
|
|
69
|
+
const required = [];
|
|
70
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
71
|
+
if (value instanceof z.ZodType) {
|
|
72
|
+
properties[key] = processZodType(value);
|
|
73
|
+
if (!(value instanceof z.ZodOptional)) {
|
|
74
|
+
required.push(key);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
type: "object",
|
|
80
|
+
properties,
|
|
81
|
+
...required.length > 0 ? { required } : {}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (zodType instanceof z.ZodArray) {
|
|
86
|
+
const elementType = zodType._def?.type || zodType.element;
|
|
87
|
+
return {
|
|
88
|
+
type: "array",
|
|
89
|
+
items: elementType ? processZodType(elementType) : { type: "string" }
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (zodType instanceof z.ZodEnum) {
|
|
93
|
+
const values = zodType._def?.values || zodType.options;
|
|
94
|
+
return {
|
|
95
|
+
type: "string",
|
|
96
|
+
enum: values
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (zodType instanceof z.ZodLiteral) {
|
|
100
|
+
const value = zodType._def?.value || zodType.value;
|
|
101
|
+
return {
|
|
102
|
+
type: typeof value,
|
|
103
|
+
const: value
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
if (zodType instanceof z.ZodUnion) {
|
|
107
|
+
const options = zodType._def?.options || zodType.options;
|
|
108
|
+
if (options && Array.isArray(options)) {
|
|
109
|
+
return {
|
|
110
|
+
oneOf: options.map((opt) => processZodType(opt))
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (zodType._def?.coerce) {
|
|
115
|
+
const innerType = zodType._def?.innerType;
|
|
116
|
+
if (innerType) {
|
|
117
|
+
return processZodType(innerType);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
type: getTypeFromZodType(zodType)
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function isStandardSchema(obj) {
|
|
125
|
+
return obj && typeof obj === "object" && "~standard" in obj;
|
|
126
|
+
}
|
|
127
|
+
function extractQueryParams(querySchema) {
|
|
128
|
+
const params = [];
|
|
129
|
+
if (!querySchema) return params;
|
|
130
|
+
if (querySchema instanceof z.ZodObject) {
|
|
131
|
+
const shape = querySchema.shape || querySchema._def?.shape?.();
|
|
132
|
+
if (shape) {
|
|
133
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
134
|
+
if (value instanceof z.ZodType) {
|
|
135
|
+
params.push({
|
|
136
|
+
name: key,
|
|
137
|
+
type: getTypeFromZodType(value),
|
|
138
|
+
required: !(value instanceof z.ZodOptional),
|
|
139
|
+
schema: processZodType(value)
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
} else if (isStandardSchema(querySchema)) {
|
|
145
|
+
const zodSchema = querySchema;
|
|
146
|
+
if (zodSchema instanceof z.ZodObject) {
|
|
147
|
+
return extractQueryParams(zodSchema);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return params;
|
|
151
|
+
}
|
|
152
|
+
async function fetchAllSitemapEntries(context) {
|
|
153
|
+
const allEntries = [];
|
|
154
|
+
for (const [pluginKey, plugin] of Object.entries(context.plugins)) {
|
|
155
|
+
if (pluginKey === "routeDocs" || plugin.name === "route-docs") {
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (plugin.sitemap) {
|
|
159
|
+
try {
|
|
160
|
+
const entries = await plugin.sitemap();
|
|
161
|
+
for (const entry of entries) {
|
|
162
|
+
allEntries.push({
|
|
163
|
+
...entry,
|
|
164
|
+
pluginKey
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
} catch (error) {
|
|
168
|
+
console.warn(`Failed to fetch sitemap for plugin ${pluginKey}:`, error);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return allEntries;
|
|
173
|
+
}
|
|
174
|
+
function generateRouteDocsSchema(context, sitemapEntries = []) {
|
|
175
|
+
const documentedPlugins = [];
|
|
176
|
+
const sitemapByPlugin = {};
|
|
177
|
+
for (const entry of sitemapEntries) {
|
|
178
|
+
if (!sitemapByPlugin[entry.pluginKey]) {
|
|
179
|
+
sitemapByPlugin[entry.pluginKey] = [];
|
|
180
|
+
}
|
|
181
|
+
sitemapByPlugin[entry.pluginKey].push(entry);
|
|
182
|
+
}
|
|
183
|
+
for (const [pluginKey, plugin] of Object.entries(context.plugins)) {
|
|
184
|
+
if (pluginKey === "routeDocs" || plugin.name === "route-docs") {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
const pluginRoutes = plugin.routes(context);
|
|
188
|
+
const documentedRoutes = [];
|
|
189
|
+
for (const [routeKey, route] of Object.entries(pluginRoutes)) {
|
|
190
|
+
const r = route;
|
|
191
|
+
const path = r.path;
|
|
192
|
+
const routeOptions = r.options || {};
|
|
193
|
+
const routeMeta = r.meta;
|
|
194
|
+
if (!path) continue;
|
|
195
|
+
const pathParamNames = extractPathParams(path);
|
|
196
|
+
const pathParams = pathParamNames.map((name) => ({
|
|
197
|
+
name,
|
|
198
|
+
type: "string",
|
|
199
|
+
// Path params are always strings
|
|
200
|
+
required: true
|
|
201
|
+
}));
|
|
202
|
+
const queryParams = extractQueryParams(routeOptions.query);
|
|
203
|
+
documentedRoutes.push({
|
|
204
|
+
key: routeKey,
|
|
205
|
+
path,
|
|
206
|
+
pathParams,
|
|
207
|
+
queryParams,
|
|
208
|
+
meta: routeMeta
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
if (documentedRoutes.length > 0) {
|
|
212
|
+
documentedPlugins.push({
|
|
213
|
+
key: pluginKey,
|
|
214
|
+
name: plugin.name,
|
|
215
|
+
routes: documentedRoutes,
|
|
216
|
+
sitemapEntries: sitemapByPlugin[pluginKey] || []
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return {
|
|
221
|
+
plugins: documentedPlugins,
|
|
222
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
223
|
+
allSitemapEntries: sitemapEntries
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export { fetchAllSitemapEntries, generateRouteDocsSchema };
|