shokupan 0.4.5 → 0.6.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.
Files changed (57) hide show
  1. package/README.md +10 -9
  2. package/dist/analysis/openapi-analyzer.d.ts +0 -4
  3. package/dist/cli.cjs +1 -1
  4. package/dist/cli.js +1 -1
  5. package/dist/context.d.ts +30 -8
  6. package/dist/index.cjs +692 -461
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.js +635 -426
  9. package/dist/index.js.map +1 -1
  10. package/dist/json-parser-B3dnQmCC.js +35 -0
  11. package/dist/json-parser-B3dnQmCC.js.map +1 -0
  12. package/dist/json-parser-COdZ0fqY.cjs +35 -0
  13. package/dist/json-parser-COdZ0fqY.cjs.map +1 -0
  14. package/dist/{openapi-analyzer-D9YB3IkV.cjs → openapi-analyzer-Bei1sVWp.cjs} +63 -49
  15. package/dist/openapi-analyzer-Bei1sVWp.cjs.map +1 -0
  16. package/dist/{openapi-analyzer-BtIaHIfe.js → openapi-analyzer-Ce_7JxZh.js} +63 -49
  17. package/dist/openapi-analyzer-Ce_7JxZh.js.map +1 -0
  18. package/dist/plugins/scalar.d.ts +1 -1
  19. package/dist/router.d.ts +33 -22
  20. package/dist/{server-adapter-BWrEJbKL.js → server-adapter-0xH174zz.js} +4 -2
  21. package/dist/server-adapter-0xH174zz.js.map +1 -0
  22. package/dist/{server-adapter-fVKP60e0.cjs → server-adapter-DFhwlK8e.cjs} +4 -2
  23. package/dist/server-adapter-DFhwlK8e.cjs.map +1 -0
  24. package/dist/shokupan.d.ts +4 -8
  25. package/dist/types.d.ts +32 -3
  26. package/dist/util/datastore.d.ts +6 -0
  27. package/dist/util/json-parser.d.ts +12 -0
  28. package/dist/util/plugin-deps.d.ts +25 -0
  29. package/package.json +74 -14
  30. package/dist/benchmarking/advanced-cases/elysia.d.ts +0 -1
  31. package/dist/benchmarking/advanced-cases/express.d.ts +0 -1
  32. package/dist/benchmarking/advanced-cases/fastify.d.ts +0 -1
  33. package/dist/benchmarking/advanced-cases/hapi.d.ts +0 -1
  34. package/dist/benchmarking/advanced-cases/hono.d.ts +0 -1
  35. package/dist/benchmarking/advanced-cases/koa.d.ts +0 -1
  36. package/dist/benchmarking/advanced-cases/nest.d.ts +0 -1
  37. package/dist/benchmarking/advanced-cases/shokupan.d.ts +0 -1
  38. package/dist/benchmarking/advanced-data.d.ts +0 -33
  39. package/dist/benchmarking/advanced-runner.d.ts +0 -1
  40. package/dist/benchmarking/advanced-worker.d.ts +0 -0
  41. package/dist/benchmarking/cases/elysia.d.ts +0 -1
  42. package/dist/benchmarking/cases/express.d.ts +0 -1
  43. package/dist/benchmarking/cases/fastify.d.ts +0 -1
  44. package/dist/benchmarking/cases/hapi.d.ts +0 -1
  45. package/dist/benchmarking/cases/hono.d.ts +0 -1
  46. package/dist/benchmarking/cases/koa.d.ts +0 -1
  47. package/dist/benchmarking/cases/nest.d.ts +0 -1
  48. package/dist/benchmarking/cases/shokupan.d.ts +0 -1
  49. package/dist/benchmarking/data.d.ts +0 -15
  50. package/dist/benchmarking/quick_bench.d.ts +0 -1
  51. package/dist/benchmarking/runner.d.ts +0 -1
  52. package/dist/benchmarking/worker.d.ts +0 -0
  53. package/dist/buntest.d.ts +0 -1
  54. package/dist/openapi-analyzer-BtIaHIfe.js.map +0 -1
  55. package/dist/openapi-analyzer-D9YB3IkV.cjs.map +0 -1
  56. package/dist/server-adapter-BWrEJbKL.js.map +0 -1
  57. package/dist/server-adapter-fVKP60e0.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!' }));
@@ -75,6 +75,7 @@ That's it! Your server is running at `http://localhost:3000` 🎉
75
75
  - [Using Express Middleware](#using-express-middleware)
76
76
  - [Testing](#testing)
77
77
  - [Deployment](#deployment)
78
+ - [Production Best Practices](https://knackstedt.github.io/shokupan/guides/production/) 📚
78
79
  - [CLI Tools](#cli-tools)
79
80
  - [API Reference](#api-reference)
80
81
  - [Roadmap](#-roadmap)
@@ -929,7 +930,7 @@ This works great when combined with the Debug Dashboard.
929
930
  A visual dashboard to inspect your application, view metrics, analyze the middleware graph, and replay failed requests.
930
931
 
931
932
  ```typescript
932
- import { DebugDashboard } from 'shokupan/plugins/debugview';
933
+ import { DebugDashboard } from 'shokupan';
933
934
 
934
935
  // Mount the dashboard
935
936
  app.mount('/debug', new DebugDashboard({
@@ -1057,8 +1058,8 @@ router.get('/wines/white', async (ctx) => {
1057
1058
  router.get('/wines/all', async (ctx) => {
1058
1059
  // Make parallel sub-requests
1059
1060
  const [redResponse, whiteResponse] = await Promise.all([
1060
- router.subRequest('/wines/red'),
1061
- router.subRequest('/wines/white')
1061
+ router.internalRequest('/wines/red'),
1062
+ router.internalRequest('/wines/white')
1062
1063
  ]);
1063
1064
 
1064
1065
  const red = await redResponse.json();
@@ -1559,7 +1560,7 @@ describe('My App', () => {
1559
1560
  app.get('/', () => ({ message: 'Hello' }));
1560
1561
 
1561
1562
  // Process a request without starting the server
1562
- const res = await app.processRequest({
1563
+ const res = await app.testRequest({
1563
1564
  method: 'GET',
1564
1565
  path: '/'
1565
1566
  });
@@ -1703,8 +1704,8 @@ const app = new Shokupan(config?: ShokupanConfig);
1703
1704
  - `mount(path, controller)` - Mount controller or router
1704
1705
  - `static(path, options)` - Serve static files
1705
1706
  - `listen(port?)` - Start server
1706
- - `processRequest(options)` - Process request (testing)
1707
- - `subRequest(options)` - Make sub-request
1707
+ - `testRequest(options)` - Process request (for testing purposes)
1708
+ - `internalRequest(options)` - Make sub-request
1708
1709
  - `computeOpenAPISpec(base)` - Generate OpenAPI spec
1709
1710
 
1710
1711
  ### ShokupanRouter Class
@@ -1737,8 +1738,8 @@ const router = new ShokupanRouter(config?: ShokupanRouteConfig);
1737
1738
  - `head(path, spec?, ...handlers)` - Add HEAD route
1738
1739
  - `mount(path, controller)` - Mount controller or router
1739
1740
  - `static(path, options)` - Serve static files
1740
- - `processRequest(options)` - Process request (testing)
1741
- - `subRequest(options)` - Make sub-request
1741
+ - `testRequest(options)` - Process request (for testing purposes)
1742
+ - `internalRequest(options)` - Make sub-request
1742
1743
 
1743
1744
 
1744
1745
  ### ShokupanContext
@@ -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-D9YB3IkV.cjs");
7
+ const openapiAnalyzer = require("./openapi-analyzer-Bei1sVWp.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-BtIaHIfe.js";
6
+ import { analyzeDirectory } from "./openapi-analyzer-Ce_7JxZh.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,10 +20,9 @@ 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<any>;
23
+ readonly server?: Server;
24
24
  readonly app?: Shokupan;
25
25
  readonly signal?: AbortSignal;
26
- private _url;
27
26
  params: Record<string, string>;
28
27
  state: State;
29
28
  handlerStack: HandlerStackItem[];
@@ -31,7 +30,17 @@ export declare class ShokupanContext<State extends Record<string, any> = Record<
31
30
  _debug?: DebugCollector;
32
31
  _finalResponse?: Response;
33
32
  _rawBody?: string | ArrayBuffer | Uint8Array;
34
- constructor(request: ShokupanRequest<any>, server?: Server<any>, state?: State, app?: Shokupan, signal?: AbortSignal, // Optional as it might not be provided in tests or simple creates
33
+ private _url?;
34
+ private _cachedBody?;
35
+ private _bodyType?;
36
+ private _bodyParsed;
37
+ _bodyParseError?: Error;
38
+ private _cachedHostname?;
39
+ private _cachedProtocol?;
40
+ private _cachedHost?;
41
+ private _cachedOrigin?;
42
+ private _cachedQuery?;
43
+ 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
44
  enableMiddlewareTracking?: boolean);
36
45
  get url(): URL;
37
46
  /**
@@ -53,7 +62,7 @@ export declare class ShokupanContext<State extends Record<string, any> = Record<
53
62
  /**
54
63
  * Client IP address
55
64
  */
56
- get ip(): any;
65
+ get ip(): Bun.SocketAddress;
57
66
  /**
58
67
  * Request hostname (e.g. "localhost")
59
68
  */
@@ -101,6 +110,23 @@ export declare class ShokupanContext<State extends Record<string, any> = Record<
101
110
  */
102
111
  setCookie(name: string, value: string, options?: CookieOptions): this;
103
112
  private mergeHeaders;
113
+ /**
114
+ * Read request body with caching to avoid double parsing.
115
+ * The body is only parsed once and cached for subsequent reads.
116
+ */
117
+ body<T = any>(): Promise<T>;
118
+ /**
119
+ * Pre-parse the request body before handler execution.
120
+ * This improves performance and enables Node.js compatibility for large payloads.
121
+ * Errors are deferred until the body is actually accessed in the handler.
122
+ */
123
+ parseBody(): Promise<void>;
124
+ /**
125
+ * Read raw body from ReadableStream efficiently.
126
+ * This is much faster than request.text() for large payloads.
127
+ * Also handles the case where body is already a string (e.g., in tests).
128
+ */
129
+ private readRawBody;
104
130
  /**
105
131
  * Send a response
106
132
  * @param body Response body
@@ -108,10 +134,6 @@ export declare class ShokupanContext<State extends Record<string, any> = Record<
108
134
  * @returns Response
109
135
  */
110
136
  send(body?: BodyInit, options?: ResponseInit): Response;
111
- /**
112
- * Read request body
113
- */
114
- body<T = any>(): Promise<T>;
115
137
  /**
116
138
  * Respond with a JSON object
117
139
  */