shokupan 0.4.5 → 0.5.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/README.md +1 -1
- package/dist/analysis/openapi-analyzer.d.ts +0 -4
- package/dist/cli.cjs +1 -1
- package/dist/cli.js +1 -1
- package/dist/context.d.ts +3 -3
- package/dist/index.cjs +36 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +36 -38
- package/dist/index.js.map +1 -1
- package/dist/{openapi-analyzer-BtIaHIfe.js → openapi-analyzer-D7y6Qa38.js} +31 -34
- package/dist/openapi-analyzer-D7y6Qa38.js.map +1 -0
- package/dist/{openapi-analyzer-D9YB3IkV.cjs → openapi-analyzer-z-7AoFRC.cjs} +31 -34
- package/dist/openapi-analyzer-z-7AoFRC.cjs.map +1 -0
- package/dist/server-adapter-BWrEJbKL.js.map +1 -1
- package/dist/server-adapter-fVKP60e0.cjs.map +1 -1
- package/dist/shokupan.d.ts +6 -5
- package/dist/types.d.ts +2 -1
- package/package.json +1 -1
- package/dist/benchmarking/advanced-cases/elysia.d.ts +0 -1
- package/dist/benchmarking/advanced-cases/express.d.ts +0 -1
- package/dist/benchmarking/advanced-cases/fastify.d.ts +0 -1
- package/dist/benchmarking/advanced-cases/hapi.d.ts +0 -1
- package/dist/benchmarking/advanced-cases/hono.d.ts +0 -1
- package/dist/benchmarking/advanced-cases/koa.d.ts +0 -1
- package/dist/benchmarking/advanced-cases/nest.d.ts +0 -1
- package/dist/benchmarking/advanced-cases/shokupan.d.ts +0 -1
- package/dist/benchmarking/advanced-data.d.ts +0 -33
- package/dist/benchmarking/advanced-runner.d.ts +0 -1
- package/dist/benchmarking/advanced-worker.d.ts +0 -0
- package/dist/benchmarking/cases/elysia.d.ts +0 -1
- package/dist/benchmarking/cases/express.d.ts +0 -1
- package/dist/benchmarking/cases/fastify.d.ts +0 -1
- package/dist/benchmarking/cases/hapi.d.ts +0 -1
- package/dist/benchmarking/cases/hono.d.ts +0 -1
- package/dist/benchmarking/cases/koa.d.ts +0 -1
- package/dist/benchmarking/cases/nest.d.ts +0 -1
- package/dist/benchmarking/cases/shokupan.d.ts +0 -1
- package/dist/benchmarking/data.d.ts +0 -15
- package/dist/benchmarking/quick_bench.d.ts +0 -1
- package/dist/benchmarking/runner.d.ts +0 -1
- package/dist/benchmarking/worker.d.ts +0 -0
- package/dist/openapi-analyzer-BtIaHIfe.js.map +0 -1
- package/dist/openapi-analyzer-D9YB3IkV.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ Shokupan is designed to make building APIs delightful again. With zero-config de
|
|
|
31
31
|
> Bun and TypeScript are recommended for Shokupan, though it also supports Node.js and standard JavaScript.
|
|
32
32
|
|
|
33
33
|
```typescript
|
|
34
|
-
import { Shokupan } from 'shokupan';
|
|
34
|
+
import { Shokupan, ScalarPlugin } from 'shokupan';
|
|
35
35
|
const app = new Shokupan();
|
|
36
36
|
|
|
37
37
|
app.get('/', (ctx) => ({ message: 'Hello, World!' }));
|
|
@@ -130,10 +130,6 @@ export declare class OpenAPIAnalyzer {
|
|
|
130
130
|
* Generate OpenAPI specification
|
|
131
131
|
*/
|
|
132
132
|
generateOpenAPISpec(): any;
|
|
133
|
-
/**
|
|
134
|
-
* Convert a type string to an OpenAPI schema
|
|
135
|
-
*/
|
|
136
|
-
private typeToSchema;
|
|
137
133
|
}
|
|
138
134
|
/**
|
|
139
135
|
* Analyze a directory and generate OpenAPI spec
|
package/dist/cli.cjs
CHANGED
|
@@ -4,7 +4,7 @@ const p = require("@clack/prompts");
|
|
|
4
4
|
const fs = require("node:fs");
|
|
5
5
|
const path = require("node:path");
|
|
6
6
|
const promises = require("node:timers/promises");
|
|
7
|
-
const openapiAnalyzer = require("./openapi-analyzer-
|
|
7
|
+
const openapiAnalyzer = require("./openapi-analyzer-z-7AoFRC.cjs");
|
|
8
8
|
function _interopNamespaceDefault(e) {
|
|
9
9
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
10
10
|
if (e) {
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import * as p from "@clack/prompts";
|
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { setTimeout } from "node:timers/promises";
|
|
6
|
-
import { analyzeDirectory } from "./openapi-analyzer-
|
|
6
|
+
import { analyzeDirectory } from "./openapi-analyzer-D7y6Qa38.js";
|
|
7
7
|
const templates = {
|
|
8
8
|
controller: (name) => `import { Controller, Get, Ctx } from 'shokupan';
|
|
9
9
|
import { ShokupanContext } from 'shokupan';
|
package/dist/context.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export interface DebugCollector {
|
|
|
20
20
|
}
|
|
21
21
|
export declare class ShokupanContext<State extends Record<string, any> = Record<string, any>> {
|
|
22
22
|
readonly request: ShokupanRequest<any>;
|
|
23
|
-
readonly server?: Server
|
|
23
|
+
readonly server?: Server;
|
|
24
24
|
readonly app?: Shokupan;
|
|
25
25
|
readonly signal?: AbortSignal;
|
|
26
26
|
private _url;
|
|
@@ -31,7 +31,7 @@ export declare class ShokupanContext<State extends Record<string, any> = Record<
|
|
|
31
31
|
_debug?: DebugCollector;
|
|
32
32
|
_finalResponse?: Response;
|
|
33
33
|
_rawBody?: string | ArrayBuffer | Uint8Array;
|
|
34
|
-
constructor(request: ShokupanRequest<any>, server?: Server
|
|
34
|
+
constructor(request: ShokupanRequest<any>, server?: Server, state?: State, app?: Shokupan, signal?: AbortSignal, // Optional as it might not be provided in tests or simple creates
|
|
35
35
|
enableMiddlewareTracking?: boolean);
|
|
36
36
|
get url(): URL;
|
|
37
37
|
/**
|
|
@@ -53,7 +53,7 @@ export declare class ShokupanContext<State extends Record<string, any> = Record<
|
|
|
53
53
|
/**
|
|
54
54
|
* Client IP address
|
|
55
55
|
*/
|
|
56
|
-
get ip():
|
|
56
|
+
get ip(): Bun.SocketAddress;
|
|
57
57
|
/**
|
|
58
58
|
* Request hostname (e.g. "localhost")
|
|
59
59
|
*/
|
package/dist/index.cjs
CHANGED
|
@@ -16,7 +16,7 @@ const Ajv = require("ajv");
|
|
|
16
16
|
const addFormats = require("ajv-formats");
|
|
17
17
|
const classTransformer = require("class-transformer");
|
|
18
18
|
const classValidator = require("class-validator");
|
|
19
|
-
const openapiAnalyzer = require("./openapi-analyzer-
|
|
19
|
+
const openapiAnalyzer = require("./openapi-analyzer-z-7AoFRC.cjs");
|
|
20
20
|
const crypto = require("crypto");
|
|
21
21
|
const events = require("events");
|
|
22
22
|
function _interopNamespaceDefault(e) {
|
|
@@ -879,7 +879,7 @@ async function generateOpenApi(rootRouter, options = {}) {
|
|
|
879
879
|
const defaultTagName = options.defaultTag || "Application";
|
|
880
880
|
let astRoutes = [];
|
|
881
881
|
try {
|
|
882
|
-
const { OpenAPIAnalyzer } = await Promise.resolve().then(() => require("./openapi-analyzer-
|
|
882
|
+
const { OpenAPIAnalyzer } = await Promise.resolve().then(() => require("./openapi-analyzer-z-7AoFRC.cjs"));
|
|
883
883
|
const analyzer = new OpenAPIAnalyzer(process.cwd());
|
|
884
884
|
const { applications } = await analyzer.analyze();
|
|
885
885
|
const appMap = /* @__PURE__ */ new Map();
|
|
@@ -2092,34 +2092,36 @@ class ShokupanRouter {
|
|
|
2092
2092
|
if (ctx.app?.applicationConfig.enableMiddlewareTracking) {
|
|
2093
2093
|
const duration = performance.now() - startTime;
|
|
2094
2094
|
const config = ctx.app.applicationConfig;
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2095
|
+
Promise.resolve().then(async () => {
|
|
2096
|
+
try {
|
|
2097
|
+
const timestamp = Date.now();
|
|
2098
|
+
const key = `${timestamp}-${handler.name || "anonymous"}-${Math.random().toString(36).substring(7)}`;
|
|
2099
|
+
await datastore.set("middleware_tracking", key, {
|
|
2100
|
+
name: handler.name || "anonymous",
|
|
2101
|
+
path: ctx.path,
|
|
2102
|
+
timestamp,
|
|
2103
|
+
duration,
|
|
2104
|
+
file,
|
|
2105
|
+
line,
|
|
2106
|
+
error: error ? String(error) : void 0,
|
|
2107
|
+
metadata: {
|
|
2108
|
+
isBuiltin: handler.isBuiltin,
|
|
2109
|
+
pluginName: handler.pluginName
|
|
2110
|
+
}
|
|
2111
|
+
});
|
|
2112
|
+
const ttl = config.middlewareTrackingTTL ?? 864e5;
|
|
2113
|
+
const maxCapacity = config.middlewareTrackingMaxCapacity ?? 1e4;
|
|
2114
|
+
const cutoff = Date.now() - ttl;
|
|
2115
|
+
await datastore.query(`DELETE middleware_tracking WHERE timestamp < ${cutoff}`);
|
|
2116
|
+
const results = await datastore.query("SELECT count() FROM middleware_tracking GROUP ALL");
|
|
2117
|
+
if (results && results[0] && results[0].count > maxCapacity) {
|
|
2118
|
+
const toDelete = results[0].count - maxCapacity;
|
|
2119
|
+
await datastore.query(`DELETE middleware_tracking ORDER BY timestamp ASC LIMIT ${toDelete}`);
|
|
2109
2120
|
}
|
|
2110
|
-
})
|
|
2111
|
-
|
|
2112
|
-
const maxCapacity = config.middlewareTrackingMaxCapacity ?? 1e4;
|
|
2113
|
-
const cutoff = Date.now() - ttl;
|
|
2114
|
-
await datastore.query(`DELETE middleware_tracking WHERE timestamp < ${cutoff}`);
|
|
2115
|
-
const results = await datastore.query("SELECT count() FROM middleware_tracking GROUP ALL");
|
|
2116
|
-
if (results && results[0] && results[0].count > maxCapacity) {
|
|
2117
|
-
const toDelete = results[0].count - maxCapacity;
|
|
2118
|
-
await datastore.query(`DELETE middleware_tracking ORDER BY timestamp ASC LIMIT ${toDelete}`);
|
|
2121
|
+
} catch (datastoreError) {
|
|
2122
|
+
console.error("Failed to store middleware tracking:", datastoreError);
|
|
2119
2123
|
}
|
|
2120
|
-
}
|
|
2121
|
-
console.error("Failed to store middleware tracking:", datastoreError);
|
|
2122
|
-
}
|
|
2124
|
+
});
|
|
2123
2125
|
}
|
|
2124
2126
|
}
|
|
2125
2127
|
};
|
|
@@ -2472,7 +2474,7 @@ class Shokupan extends ShokupanRouter {
|
|
|
2472
2474
|
factory = createHttpServer();
|
|
2473
2475
|
}
|
|
2474
2476
|
const server = factory ? await factory(serveOptions) : Bun.serve(serveOptions);
|
|
2475
|
-
console.log(`Shokupan server listening on http://${
|
|
2477
|
+
console.log(`Shokupan server listening on http://${serveOptions.hostname}:${serveOptions.port}`);
|
|
2476
2478
|
return server;
|
|
2477
2479
|
}
|
|
2478
2480
|
[$dispatch](req) {
|
|
@@ -3278,8 +3280,8 @@ function validate(config) {
|
|
|
3278
3280
|
body = await safelyGetBody(ctx);
|
|
3279
3281
|
dataToValidate.body = body;
|
|
3280
3282
|
}
|
|
3281
|
-
if (ctx.app?.
|
|
3282
|
-
await ctx.app.
|
|
3283
|
+
if (ctx.app?.hasHook("beforeValidate")) {
|
|
3284
|
+
await ctx.app.executeHook("beforeValidate", ctx, dataToValidate);
|
|
3283
3285
|
}
|
|
3284
3286
|
if (validators.params) {
|
|
3285
3287
|
ctx.params = await validators.params(ctx.params);
|
|
@@ -3304,12 +3306,12 @@ function validate(config) {
|
|
|
3304
3306
|
});
|
|
3305
3307
|
ctx.body = validBody;
|
|
3306
3308
|
}
|
|
3307
|
-
if (ctx.app?.
|
|
3309
|
+
if (ctx.app?.hasHook("afterValidate")) {
|
|
3308
3310
|
const validatedData = { ...dataToValidate };
|
|
3309
3311
|
if (config.params) validatedData.params = ctx.params;
|
|
3310
3312
|
if (config.query) validatedData.query = validQuery;
|
|
3311
3313
|
if (config.body) validatedData.body = validBody;
|
|
3312
|
-
await ctx.app
|
|
3314
|
+
await ctx.app?.executeHook("afterValidate", ctx, validatedData);
|
|
3313
3315
|
}
|
|
3314
3316
|
return next();
|
|
3315
3317
|
};
|
|
@@ -3493,8 +3495,7 @@ class ScalarPlugin extends ShokupanRouter {
|
|
|
3493
3495
|
|
|
3494
3496
|
<body>
|
|
3495
3497
|
<div id="app"></div>
|
|
3496
|
-
|
|
3497
|
-
<script src="<%= it.path %>scalar.js"><\/script>
|
|
3498
|
+
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"><\/script>
|
|
3498
3499
|
<script>
|
|
3499
3500
|
Scalar.createApiReference('#app', [{ ...<%~ JSON.stringify(it.config.baseDocument) %>,
|
|
3500
3501
|
url: "<%= it.path %>openapi.json",
|
|
@@ -3505,9 +3506,6 @@ class ScalarPlugin extends ShokupanRouter {
|
|
|
3505
3506
|
|
|
3506
3507
|
</html>`, { path: path2, config: this.pluginOptions }));
|
|
3507
3508
|
});
|
|
3508
|
-
this.get("/scalar.js", (ctx) => {
|
|
3509
|
-
return ctx.file(__dirname + "/../../node_modules/@scalar/api-reference/dist/browser/standalone.js");
|
|
3510
|
-
});
|
|
3511
3509
|
this.get("/openapi.json", async (ctx) => {
|
|
3512
3510
|
let spec;
|
|
3513
3511
|
if (this.root.openApiSpec) {
|