shokupan 0.10.0 → 0.10.2
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/index.cjs +320 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +320 -39
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './context';
|
|
2
2
|
export * from './middleware';
|
|
3
|
+
export * from './router';
|
|
3
4
|
export * from './shokupan';
|
|
4
5
|
export * from './util/decorators';
|
|
5
6
|
export * from './util/di';
|
|
@@ -7,6 +8,7 @@ export * from './util/request';
|
|
|
7
8
|
export * from './util/response';
|
|
8
9
|
export * from './util/symbol';
|
|
9
10
|
export * from './util/types';
|
|
11
|
+
export * from './plugins/application/api-explorer/plugin';
|
|
10
12
|
export * from './plugins/application/asyncapi/plugin';
|
|
11
13
|
export * from './plugins/application/auth';
|
|
12
14
|
export * from './plugins/application/cluster';
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { nanoid } from "nanoid";
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
import { inspect } from "node:util";
|
|
4
|
-
import { trace, SpanKind, SpanStatusCode, context } from "@opentelemetry/api";
|
|
5
|
-
import { dump } from "js-yaml";
|
|
6
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
4
|
import { RecordId, Surreal } from "surrealdb";
|
|
8
5
|
import { Eta } from "eta";
|
|
9
6
|
import { stat, readdir, readFile as readFile$1 } from "fs/promises";
|
|
10
7
|
import { resolve, join, sep, basename } from "path";
|
|
8
|
+
import { trace, SpanKind, SpanStatusCode, context } from "@opentelemetry/api";
|
|
9
|
+
import { dump } from "js-yaml";
|
|
10
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
11
11
|
import * as os from "node:os";
|
|
12
12
|
import os__default from "node:os";
|
|
13
|
-
import { dirname, join as join$1 } from "node:path";
|
|
14
|
-
import { fileURLToPath } from "node:url";
|
|
15
13
|
import renderToString from "preact-render-to-string";
|
|
16
14
|
import { jsxs, jsx, Fragment } from "preact/jsx-runtime";
|
|
15
|
+
import { dirname, join as join$1 } from "node:path";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
17
|
import cluster from "node:cluster";
|
|
18
18
|
import net from "node:net";
|
|
19
19
|
import { monitorEventLoopDelay } from "node:perf_hooks";
|
|
@@ -1317,40 +1317,6 @@ async function generateOpenApi(rootRouter, options = {}) {
|
|
|
1317
1317
|
"x-tagGroups": xTagGroups
|
|
1318
1318
|
};
|
|
1319
1319
|
}
|
|
1320
|
-
class RequestContextStore {
|
|
1321
|
-
request;
|
|
1322
|
-
span;
|
|
1323
|
-
}
|
|
1324
|
-
const asyncContext = new AsyncLocalStorage();
|
|
1325
|
-
class HttpError extends Error {
|
|
1326
|
-
status;
|
|
1327
|
-
constructor(message, status) {
|
|
1328
|
-
super(message);
|
|
1329
|
-
this.name = "HttpError";
|
|
1330
|
-
this.status = status;
|
|
1331
|
-
if (Error.captureStackTrace) {
|
|
1332
|
-
Error.captureStackTrace(this, HttpError);
|
|
1333
|
-
}
|
|
1334
|
-
}
|
|
1335
|
-
}
|
|
1336
|
-
function getErrorStatus(err) {
|
|
1337
|
-
if (!err || typeof err !== "object") {
|
|
1338
|
-
return 500;
|
|
1339
|
-
}
|
|
1340
|
-
if (typeof err.status === "number") {
|
|
1341
|
-
return err.status;
|
|
1342
|
-
}
|
|
1343
|
-
if (typeof err.statusCode === "number") {
|
|
1344
|
-
return err.statusCode;
|
|
1345
|
-
}
|
|
1346
|
-
return 500;
|
|
1347
|
-
}
|
|
1348
|
-
class EventError extends HttpError {
|
|
1349
|
-
constructor(message = "Event Error") {
|
|
1350
|
-
super(message, 500);
|
|
1351
|
-
this.name = "EventError";
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
1320
|
const eta = new Eta();
|
|
1355
1321
|
function serveStatic(config, prefix) {
|
|
1356
1322
|
const rootPath = resolve(config.root || ".");
|
|
@@ -1536,6 +1502,35 @@ function Inject(token) {
|
|
|
1536
1502
|
});
|
|
1537
1503
|
};
|
|
1538
1504
|
}
|
|
1505
|
+
class HttpError extends Error {
|
|
1506
|
+
status;
|
|
1507
|
+
constructor(message, status) {
|
|
1508
|
+
super(message);
|
|
1509
|
+
this.name = "HttpError";
|
|
1510
|
+
this.status = status;
|
|
1511
|
+
if (Error.captureStackTrace) {
|
|
1512
|
+
Error.captureStackTrace(this, HttpError);
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
function getErrorStatus(err) {
|
|
1517
|
+
if (!err || typeof err !== "object") {
|
|
1518
|
+
return 500;
|
|
1519
|
+
}
|
|
1520
|
+
if (typeof err.status === "number") {
|
|
1521
|
+
return err.status;
|
|
1522
|
+
}
|
|
1523
|
+
if (typeof err.statusCode === "number") {
|
|
1524
|
+
return err.statusCode;
|
|
1525
|
+
}
|
|
1526
|
+
return 500;
|
|
1527
|
+
}
|
|
1528
|
+
class EventError extends HttpError {
|
|
1529
|
+
constructor(message = "Event Error") {
|
|
1530
|
+
super(message, 500);
|
|
1531
|
+
this.name = "EventError";
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1539
1534
|
const tracer = trace.getTracer("shokupan.middleware");
|
|
1540
1535
|
function traceHandler(fn, name) {
|
|
1541
1536
|
return async function(...args) {
|
|
@@ -1725,6 +1720,8 @@ var RouteParamType = /* @__PURE__ */ ((RouteParamType2) => {
|
|
|
1725
1720
|
RouteParamType2["CONTEXT"] = "CONTEXT";
|
|
1726
1721
|
return RouteParamType2;
|
|
1727
1722
|
})(RouteParamType || {});
|
|
1723
|
+
const RouterRegistry = /* @__PURE__ */ new Map();
|
|
1724
|
+
const ShokupanApplicationTree = {};
|
|
1728
1725
|
class ShokupanRouter {
|
|
1729
1726
|
constructor(config) {
|
|
1730
1727
|
this.config = config;
|
|
@@ -2719,6 +2716,11 @@ class ShokupanRouter {
|
|
|
2719
2716
|
}
|
|
2720
2717
|
}
|
|
2721
2718
|
}
|
|
2719
|
+
class RequestContextStore {
|
|
2720
|
+
request;
|
|
2721
|
+
span;
|
|
2722
|
+
}
|
|
2723
|
+
const asyncContext = new AsyncLocalStorage();
|
|
2722
2724
|
class SystemCpuMonitor {
|
|
2723
2725
|
constructor(intervalMs = 1e3) {
|
|
2724
2726
|
this.intervalMs = intervalMs;
|
|
@@ -3523,6 +3525,281 @@ function Event(eventName) {
|
|
|
3523
3525
|
function RateLimit(options) {
|
|
3524
3526
|
return Use(RateLimitMiddleware(options));
|
|
3525
3527
|
}
|
|
3528
|
+
function ApiExplorerApp({ spec, asyncSpec, config }) {
|
|
3529
|
+
const hierarchy = /* @__PURE__ */ new Map();
|
|
3530
|
+
const addRoute = (groupKey, route) => {
|
|
3531
|
+
if (!hierarchy.has(groupKey)) {
|
|
3532
|
+
hierarchy.set(groupKey, []);
|
|
3533
|
+
}
|
|
3534
|
+
hierarchy.get(groupKey).push(route);
|
|
3535
|
+
};
|
|
3536
|
+
const getGroupKey = (op, source) => {
|
|
3537
|
+
if (op.tags && op.tags.length > 0) {
|
|
3538
|
+
const tag = typeof op.tags[0] === "string" ? op.tags[0] : op.tags[0].name;
|
|
3539
|
+
if (!tag.startsWith("/")) return tag;
|
|
3540
|
+
}
|
|
3541
|
+
if (source?.className) return source.className;
|
|
3542
|
+
if (source?.file) {
|
|
3543
|
+
const parts = source.file.split("/");
|
|
3544
|
+
const filename = parts[parts.length - 1].replace(/\.(ts|js)$/, "");
|
|
3545
|
+
return filename.split(/[-_]/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
3546
|
+
}
|
|
3547
|
+
if (op.tags && op.tags.length > 0) {
|
|
3548
|
+
const tag = typeof op.tags[0] === "string" ? op.tags[0] : op.tags[0].name;
|
|
3549
|
+
return tag;
|
|
3550
|
+
}
|
|
3551
|
+
return "Ungrouped";
|
|
3552
|
+
};
|
|
3553
|
+
const createSubgroups = (routes, depth = 0) => {
|
|
3554
|
+
if (routes.length < 3 || depth > 5) {
|
|
3555
|
+
return routes.map((route) => ({
|
|
3556
|
+
name: route.path,
|
|
3557
|
+
type: "route",
|
|
3558
|
+
path: route.path,
|
|
3559
|
+
routes: [route]
|
|
3560
|
+
}));
|
|
3561
|
+
}
|
|
3562
|
+
const pathSegments = routes.map((r) => {
|
|
3563
|
+
const cleaned = r.path.replace(/^\/|\/$/g, "");
|
|
3564
|
+
return cleaned.split("/");
|
|
3565
|
+
});
|
|
3566
|
+
const prefixGroups = /* @__PURE__ */ new Map();
|
|
3567
|
+
const ungrouped = [];
|
|
3568
|
+
routes.forEach((route, idx) => {
|
|
3569
|
+
const segments = pathSegments[idx];
|
|
3570
|
+
if (segments.length <= depth) {
|
|
3571
|
+
ungrouped.push(route);
|
|
3572
|
+
return;
|
|
3573
|
+
}
|
|
3574
|
+
const prefix = segments.slice(0, depth + 1).join("/");
|
|
3575
|
+
if (!prefixGroups.has(prefix)) {
|
|
3576
|
+
prefixGroups.set(prefix, []);
|
|
3577
|
+
}
|
|
3578
|
+
prefixGroups.get(prefix).push(route);
|
|
3579
|
+
});
|
|
3580
|
+
const result = [];
|
|
3581
|
+
prefixGroups.forEach((groupRoutes, prefix) => {
|
|
3582
|
+
if (groupRoutes.length >= 3) {
|
|
3583
|
+
const prefixName = prefix.split("/").pop() || prefix;
|
|
3584
|
+
result.push({
|
|
3585
|
+
name: prefixName,
|
|
3586
|
+
type: "subgroup",
|
|
3587
|
+
path: "/" + prefix,
|
|
3588
|
+
children: createSubgroups(groupRoutes, depth + 1)
|
|
3589
|
+
});
|
|
3590
|
+
} else {
|
|
3591
|
+
ungrouped.push(...groupRoutes);
|
|
3592
|
+
}
|
|
3593
|
+
});
|
|
3594
|
+
ungrouped.forEach((route) => {
|
|
3595
|
+
result.push({
|
|
3596
|
+
name: route.path,
|
|
3597
|
+
type: "route",
|
|
3598
|
+
path: route.path,
|
|
3599
|
+
routes: [route]
|
|
3600
|
+
});
|
|
3601
|
+
});
|
|
3602
|
+
result.sort((a, b) => {
|
|
3603
|
+
if (a.type === "subgroup" && b.type !== "subgroup") return -1;
|
|
3604
|
+
if (a.type !== "subgroup" && b.type === "subgroup") return 1;
|
|
3605
|
+
return a.name.localeCompare(b.name);
|
|
3606
|
+
});
|
|
3607
|
+
return result;
|
|
3608
|
+
};
|
|
3609
|
+
Object.entries(spec.paths || {}).forEach(([path, methods]) => {
|
|
3610
|
+
Object.entries(methods).forEach(([method, op]) => {
|
|
3611
|
+
if (!op.operationId) {
|
|
3612
|
+
op.operationId = `${method}-${path.replace(/\//g, "-").replace(/[{}:]/g, "")}`;
|
|
3613
|
+
}
|
|
3614
|
+
const route = { method, path, op };
|
|
3615
|
+
const source = op["x-shokupan-source"];
|
|
3616
|
+
const groupKey = getGroupKey(op, source);
|
|
3617
|
+
addRoute(groupKey, route);
|
|
3618
|
+
});
|
|
3619
|
+
});
|
|
3620
|
+
Object.entries(asyncSpec?.channels || {}).forEach(([name, ch]) => {
|
|
3621
|
+
const operations = [];
|
|
3622
|
+
if (ch.publish) operations.push({ method: "recv", op: ch.publish });
|
|
3623
|
+
if (ch.subscribe) operations.push({ method: "send", op: ch.subscribe });
|
|
3624
|
+
operations.forEach(({ method, op }) => {
|
|
3625
|
+
if (!op.operationId) op.operationId = `${method}-${name.replace(/[^a-zA-Z0-9]/g, "-")}`;
|
|
3626
|
+
const route = { method, path: name, op };
|
|
3627
|
+
const source = op["x-shokupan-source"] || op["x-source-info"];
|
|
3628
|
+
const groupKey = getGroupKey(op, source);
|
|
3629
|
+
addRoute(groupKey, route);
|
|
3630
|
+
});
|
|
3631
|
+
});
|
|
3632
|
+
const hierarchicalGroups = Array.from(hierarchy.entries()).map(([name, routes]) => {
|
|
3633
|
+
routes.sort((a, b) => a.path.localeCompare(b.path));
|
|
3634
|
+
const children = createSubgroups(routes);
|
|
3635
|
+
return {
|
|
3636
|
+
name,
|
|
3637
|
+
type: "group",
|
|
3638
|
+
children
|
|
3639
|
+
};
|
|
3640
|
+
}).sort((a, b) => {
|
|
3641
|
+
if (a.name === "Ungrouped") return 1;
|
|
3642
|
+
if (b.name === "Ungrouped") return -1;
|
|
3643
|
+
return a.name.localeCompare(b.name);
|
|
3644
|
+
});
|
|
3645
|
+
const allRoutes = Array.from(hierarchy.values()).flat();
|
|
3646
|
+
return /* @__PURE__ */ jsxs("html", { lang: "en", children: [
|
|
3647
|
+
/* @__PURE__ */ jsxs("head", { children: [
|
|
3648
|
+
/* @__PURE__ */ jsx("meta", { charSet: "UTF-8" }),
|
|
3649
|
+
/* @__PURE__ */ jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }),
|
|
3650
|
+
/* @__PURE__ */ jsx("title", { children: spec.info?.title || "API Explorer" }),
|
|
3651
|
+
/* @__PURE__ */ jsx("link", { rel: "stylesheet", href: "style.css" }),
|
|
3652
|
+
/* @__PURE__ */ jsx("link", { rel: "stylesheet", href: "theme.css" }),
|
|
3653
|
+
/* @__PURE__ */ jsx("script", { src: "https://cdn.jsdelivr.net/npm/marked@4.3.0/marked.min.js" }),
|
|
3654
|
+
/* @__PURE__ */ jsx("script", { src: "https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min/vs/loader.js" }),
|
|
3655
|
+
/* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: {
|
|
3656
|
+
__html: `
|
|
3657
|
+
(function() {
|
|
3658
|
+
if (!window.location.pathname.endsWith('/') && !window.location.pathname.split('/').pop().includes('.')) {
|
|
3659
|
+
var newUrl = window.location.pathname + '/' + window.location.search + window.location.hash;
|
|
3660
|
+
window.history.replaceState(null, null, newUrl);
|
|
3661
|
+
window.location.reload();
|
|
3662
|
+
}
|
|
3663
|
+
})();
|
|
3664
|
+
`
|
|
3665
|
+
} })
|
|
3666
|
+
] }),
|
|
3667
|
+
/* @__PURE__ */ jsxs("body", { class: "dark-theme", children: [
|
|
3668
|
+
/* @__PURE__ */ jsxs("div", { id: "app", children: [
|
|
3669
|
+
/* @__PURE__ */ jsx(Sidebar$1, { spec, hierarchicalGroups }),
|
|
3670
|
+
/* @__PURE__ */ jsx(MainContent$1, { allRoutes, config, spec })
|
|
3671
|
+
] }),
|
|
3672
|
+
/* @__PURE__ */ jsx("script", { src: "explorer-client.mjs", type: "module" })
|
|
3673
|
+
] })
|
|
3674
|
+
] });
|
|
3675
|
+
}
|
|
3676
|
+
function Sidebar$1({ spec, hierarchicalGroups }) {
|
|
3677
|
+
const renderNavNode = (node, depth = 0) => {
|
|
3678
|
+
if (node.type === "route") {
|
|
3679
|
+
const route = node.routes[0];
|
|
3680
|
+
const source = route.op["x-shokupan-source"] || route.op["x-source-info"];
|
|
3681
|
+
const isRuntime = route.op["x-source-info"]?.isRuntime;
|
|
3682
|
+
return /* @__PURE__ */ jsxs("div", { class: "nav-item-wrapper", style: `padding-left: ${depth * 12}px;`, children: [
|
|
3683
|
+
/* @__PURE__ */ jsxs(
|
|
3684
|
+
"a",
|
|
3685
|
+
{
|
|
3686
|
+
href: `#${route.op.operationId}`,
|
|
3687
|
+
class: "nav-item",
|
|
3688
|
+
"data-id": route.op.operationId,
|
|
3689
|
+
title: route.path,
|
|
3690
|
+
children: [
|
|
3691
|
+
/* @__PURE__ */ jsx("span", { class: `badge badge-${route.method.toUpperCase()}`, children: route.method.toUpperCase() }),
|
|
3692
|
+
/* @__PURE__ */ jsx("span", { class: "nav-label", children: node.name }),
|
|
3693
|
+
isRuntime && /* @__PURE__ */ jsx("span", { class: "nav-warning", title: "Static Analysis Failed", children: /* @__PURE__ */ jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", children: [
|
|
3694
|
+
/* @__PURE__ */ jsx("path", { d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }),
|
|
3695
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "9", x2: "12", y2: "13" }),
|
|
3696
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
|
|
3697
|
+
] }) })
|
|
3698
|
+
]
|
|
3699
|
+
},
|
|
3700
|
+
route.op.operationId
|
|
3701
|
+
),
|
|
3702
|
+
source?.file && /* @__PURE__ */ jsx(
|
|
3703
|
+
"a",
|
|
3704
|
+
{
|
|
3705
|
+
href: `vscode://file/${source.file}:${source.line || 1}`,
|
|
3706
|
+
class: "nav-source-link",
|
|
3707
|
+
title: `${source.file}:${source.line || 1}`,
|
|
3708
|
+
children: /* @__PURE__ */ jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
|
|
3709
|
+
/* @__PURE__ */ jsx("polyline", { points: "16 18 22 12 16 6" }),
|
|
3710
|
+
/* @__PURE__ */ jsx("polyline", { points: "8 6 2 12 8 18" })
|
|
3711
|
+
] })
|
|
3712
|
+
}
|
|
3713
|
+
)
|
|
3714
|
+
] });
|
|
3715
|
+
} else if (node.type === "subgroup") {
|
|
3716
|
+
return /* @__PURE__ */ jsxs("div", { class: "nav-subgroup collapsed", style: `padding-left: ${depth * 12}px;`, children: [
|
|
3717
|
+
/* @__PURE__ */ jsxs("div", { class: "nav-subgroup-title", children: [
|
|
3718
|
+
/* @__PURE__ */ jsx("span", { class: "chevron", children: /* @__PURE__ */ jsx("svg", { width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", children: /* @__PURE__ */ jsx("polyline", { points: "9 18 15 12 9 6" }) }) }),
|
|
3719
|
+
/* @__PURE__ */ jsx("span", { children: node.name })
|
|
3720
|
+
] }),
|
|
3721
|
+
/* @__PURE__ */ jsx("div", { class: "nav-subgroup-items", children: node.children?.map((child) => renderNavNode(child, depth + 1)) })
|
|
3722
|
+
] });
|
|
3723
|
+
}
|
|
3724
|
+
};
|
|
3725
|
+
return /* @__PURE__ */ jsxs("aside", { class: "sidebar", children: [
|
|
3726
|
+
/* @__PURE__ */ jsx("div", { class: "resize-handle" }),
|
|
3727
|
+
/* @__PURE__ */ jsxs("header", { class: "sidebar-header", children: [
|
|
3728
|
+
/* @__PURE__ */ jsx("button", { class: "toggle-sidebar", children: "☰" }),
|
|
3729
|
+
/* @__PURE__ */ jsx("h1", { children: spec.info?.title }),
|
|
3730
|
+
/* @__PURE__ */ jsx("div", { class: "version", children: spec.info?.version })
|
|
3731
|
+
] }),
|
|
3732
|
+
/* @__PURE__ */ jsx("div", { class: "sidebar-collapse-trigger", children: "➔" }),
|
|
3733
|
+
/* @__PURE__ */ jsx("nav", { class: "nav-groups", children: hierarchicalGroups.map((group) => /* @__PURE__ */ jsxs("div", { class: "nav-group collapsed", children: [
|
|
3734
|
+
/* @__PURE__ */ jsxs("div", { class: "nav-group-title", children: [
|
|
3735
|
+
/* @__PURE__ */ jsx("span", { class: "chevron", children: /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", children: /* @__PURE__ */ jsx("polyline", { points: "9 18 15 12 9 6" }) }) }),
|
|
3736
|
+
" ",
|
|
3737
|
+
group.name
|
|
3738
|
+
] }),
|
|
3739
|
+
/* @__PURE__ */ jsx("div", { class: "nav-items", children: group.children?.map((child) => renderNavNode(child, 0)) })
|
|
3740
|
+
] }, group.name)) })
|
|
3741
|
+
] });
|
|
3742
|
+
}
|
|
3743
|
+
function MainContent$1({ allRoutes, config, spec }) {
|
|
3744
|
+
const explorerData = JSON.stringify({
|
|
3745
|
+
routes: allRoutes,
|
|
3746
|
+
config,
|
|
3747
|
+
info: spec.info
|
|
3748
|
+
});
|
|
3749
|
+
const safeJson = explorerData.replace(/<\/script>/g, "<\\/script>");
|
|
3750
|
+
return /* @__PURE__ */ jsxs("main", { class: "content", id: "main-content", children: [
|
|
3751
|
+
/* @__PURE__ */ jsx("div", { id: "ide-container", children: /* @__PURE__ */ jsx("div", { class: "empty-state", children: "Select a request to view details" }) }),
|
|
3752
|
+
/* @__PURE__ */ jsx("script", { id: "explorer-data", type: "application/json", dangerouslySetInnerHTML: { __html: safeJson } })
|
|
3753
|
+
] });
|
|
3754
|
+
}
|
|
3755
|
+
class ApiExplorerPlugin extends ShokupanRouter {
|
|
3756
|
+
constructor(pluginOptions) {
|
|
3757
|
+
super({ renderer: renderToString });
|
|
3758
|
+
this.pluginOptions = pluginOptions;
|
|
3759
|
+
pluginOptions.path ??= "/explorer";
|
|
3760
|
+
const serveFile = async (ctx, file, type) => {
|
|
3761
|
+
const content = await readFile$1(join(__dirname, "static", file), "utf-8");
|
|
3762
|
+
ctx.set("Content-Type", type);
|
|
3763
|
+
return ctx.send(content);
|
|
3764
|
+
};
|
|
3765
|
+
const stripSourceCode = (spec) => {
|
|
3766
|
+
if (!spec || !spec.paths) return spec;
|
|
3767
|
+
Object.values(spec.paths).forEach((methods) => {
|
|
3768
|
+
Object.values(methods).forEach((op) => {
|
|
3769
|
+
if (op["x-source-info"]?.snippet) {
|
|
3770
|
+
delete op["x-source-info"].snippet;
|
|
3771
|
+
}
|
|
3772
|
+
if (op["x-shokupan-source"]?.code) {
|
|
3773
|
+
delete op["x-shokupan-source"].code;
|
|
3774
|
+
}
|
|
3775
|
+
});
|
|
3776
|
+
});
|
|
3777
|
+
return spec;
|
|
3778
|
+
};
|
|
3779
|
+
this.get("/style.css", (ctx) => serveFile(ctx, "style.css", "text/css"));
|
|
3780
|
+
this.get("/theme.css", (ctx) => serveFile(ctx, "theme.css", "text/css"));
|
|
3781
|
+
this.get("/explorer-client.mjs", (ctx) => serveFile(ctx, "explorer-client.mjs", "application/javascript"));
|
|
3782
|
+
this.get("/_source", async (ctx) => {
|
|
3783
|
+
const file = ctx.query["file"];
|
|
3784
|
+
if (!file) return ctx.text("Missing file parameter", 400);
|
|
3785
|
+
try {
|
|
3786
|
+
const content = await readFile$1(file, "utf-8");
|
|
3787
|
+
return ctx.text(content);
|
|
3788
|
+
} catch (err) {
|
|
3789
|
+
return ctx.text("File not found", 404);
|
|
3790
|
+
}
|
|
3791
|
+
});
|
|
3792
|
+
this.get("/openapi.json", async (ctx) => {
|
|
3793
|
+
const spec = this.root.openApiSpec ? structuredClone(this.root.openApiSpec) : await (this.root || this).generateApiSpec();
|
|
3794
|
+
return ctx.json(stripSourceCode(spec));
|
|
3795
|
+
});
|
|
3796
|
+
this.get("/", async (ctx) => {
|
|
3797
|
+
const spec = this.root.openApiSpec ? structuredClone(this.root.openApiSpec) : await (this.root || this).generateApiSpec();
|
|
3798
|
+
const asyncSpec = ctx.app.asyncApiSpec;
|
|
3799
|
+
return ctx.jsx(ApiExplorerApp({ spec: stripSourceCode(spec), asyncSpec }));
|
|
3800
|
+
});
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3526
3803
|
function AsyncApiApp({ spec, serverUrl, base, disableSourceView, navTree }) {
|
|
3527
3804
|
return /* @__PURE__ */ jsxs("html", { lang: "en", children: [
|
|
3528
3805
|
/* @__PURE__ */ jsxs("head", { children: [
|
|
@@ -6364,6 +6641,7 @@ export {
|
|
|
6364
6641
|
$url,
|
|
6365
6642
|
$ws,
|
|
6366
6643
|
All,
|
|
6644
|
+
ApiExplorerPlugin,
|
|
6367
6645
|
AsyncApiPlugin,
|
|
6368
6646
|
AuthPlugin,
|
|
6369
6647
|
Body,
|
|
@@ -6394,13 +6672,16 @@ export {
|
|
|
6394
6672
|
RateLimitMiddleware,
|
|
6395
6673
|
Req,
|
|
6396
6674
|
RouteParamType,
|
|
6675
|
+
RouterRegistry,
|
|
6397
6676
|
ScalarPlugin,
|
|
6398
6677
|
SecurityHeaders,
|
|
6399
6678
|
Session,
|
|
6400
6679
|
Shokupan,
|
|
6680
|
+
ShokupanApplicationTree,
|
|
6401
6681
|
ShokupanContext,
|
|
6402
6682
|
ShokupanRequest,
|
|
6403
6683
|
ShokupanResponse,
|
|
6684
|
+
ShokupanRouter,
|
|
6404
6685
|
Spec,
|
|
6405
6686
|
Use,
|
|
6406
6687
|
ValidationError,
|