rpc4next 0.1.3 → 0.1.5

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 CHANGED
@@ -9,7 +9,7 @@ Inspired by Hono RPC and Pathpida, **rpc4next** automatically generates a type-s
9
9
  ## ✨ Features
10
10
 
11
11
  - ✅ 既存の `app/**/route.ts` および `app/**/page.tsx` を活用するため、新たなハンドラファイルの作成は不要
12
- - ✅ ルート、パラメータ、リクエストボディ、レスポンスの型安全なクライアント生成
12
+ - ✅ ルート、パラメータ、クエリパラメータ、 リクエストボディ、レスポンスの型安全なクライアント生成
13
13
  - ✅ 最小限のセットアップで、カスタムサーバー不要
14
14
  - ✅ 動的ルート(`[id]`、`[...slug]` など)に対応
15
15
  - ✅ CLI による自動クライアント用型定義生成
@@ -30,29 +30,37 @@ npm install rpc4next
30
30
  ### 2. Define API Routes in Next.js
31
31
 
32
32
  Next.js プロジェクト内の既存の `app/**/route.ts` と `app/**/page.tsx` ファイルをそのまま利用できます。
33
+ さらに、クエリパラメータ(searchParams)の型安全性を有効にするには、対象のファイル内で `Query` または `OptionalQuery` 型を定義し、`export` してください。
33
34
 
34
35
  ```ts
35
36
  // app/api/user/[id]/route.ts
36
37
  import { NextRequest, NextResponse } from "next/server";
37
38
 
39
+ // searchParams用の型定義
40
+ export type Query = {
41
+ q: string; // 必須
42
+ page?: number; // 任意
43
+ };
44
+
38
45
  export async function GET(
39
46
  req: NextRequest,
40
47
  segmentData: { params: Promise<{ id: string }> }
41
48
  ) {
42
49
  const { id } = await segmentData.params;
43
- // RPCとしてresponseの戻り値の推論が機能するのは、対象となる `route.ts` の HTTPメソッドハンドラ内で`NextResponse.json()` をしている物のみになります
44
- return NextResponse.json({ name: `User ${id}` });
50
+ const q = req.nextUrl.searchParams.get("q");
51
+ return NextResponse.json({ id, q });
45
52
  }
46
53
  ```
47
54
 
55
+ 🚩 Query or OptionalQuery 型を export することで、searchParams の型も自動的にクライアントに反映されます。
56
+
48
57
  - **RPCとしてresponseの戻り値の推論が機能するのは、対象となる `route.ts` の HTTPメソッドハンドラ内で`NextResponse.json()` をしている物のみになります**
49
58
 
50
59
  ---
51
60
 
52
61
  ### 3. Generate Type Definitions with CLI
53
62
 
54
- CLI を利用して、Next.js のルート構造から型安全な RPC クライアントの定義を自動生成します。
55
- 以下のコマンドを実行すると、`route.ts` と `page.tsx` ファイルの両方を走査し、型定義ファイル(outputPathに指定したファイル)が生成されます。
63
+ CLI を利用して、Next.js のルート構造から型安全な RPC クライアントの定義を自動生成します。
56
64
 
57
65
  ```bash
58
66
  npx rpc4next <baseDir> <outputPath>
@@ -64,14 +72,14 @@ npx rpc4next <baseDir> <outputPath>
64
72
  #### オプション
65
73
 
66
74
  - **ウォッチモード**
67
- ファイル変更を検知して自動的に再生成する場合は `--watch` オプションを付けます。
75
+ ファイル変更を検知して自動的に再生成する場合は `--watch` or `-w` オプションを付けます。
68
76
 
69
77
  ```bash
70
78
  npx rpc4next <baseDir> <outputPath> --watch
71
79
  ```
72
80
 
73
81
  - **パラメータ型ファイルの生成**
74
- 各ルートに対して個別のパラメータ型定義ファイルを生成する場合は、`--generate-params-types` オプションにファイル名を指定します。
82
+ 各ルートに対して個別のパラメータ型定義ファイルを生成する場合は、`--params-file` or `-p` オプションにファイル名を指定します。
75
83
 
76
84
  ```bash
77
85
  npx rpc4next <baseDir> <outputPath> --generate-params-types <paramsFileName>
@@ -104,17 +112,54 @@ export const rpc = createClient<PathStructure>();
104
112
  import { rpc } from "@/lib/rpcClient";
105
113
 
106
114
  export default async function Page() {
107
- const res = await rpc.api.user._id("123").$get();
115
+ const res = await rpc.api.user._id("123").$get({
116
+ query: { q: "hello", page: 1 },
117
+ });
108
118
  const json = await res.json();
109
- return <div>{json.name}</div>;
119
+ return <div>{json.q}</div>;
110
120
  }
111
121
  ```
112
122
 
113
123
  - エディタの補完機能により、利用可能なエンドポイントが自動的に表示されます。
114
- - リクエストの構造(params, searchParams)はサーバーコードから推論され、レスポンスも型安全に扱えます。
124
+ - リクエストの構造(params, query)はサーバーコードから推論され、レスポンスも型安全に扱えます。
115
125
 
116
126
  ---
117
127
 
128
+ ## ✅ さらに型安全にしたい場合 `honolike` + `createRouteHandler` による Next.js の型安全強化
129
+
130
+ さらに `honolike` をベースとした `createRouteHandler()` を組み合わせることで、
131
+
132
+ ### 📌 主なメリット
133
+
134
+ 1. **レスポンス型安全**
135
+
136
+ - ステータス、Content-Type、Body がすべて型で保証される
137
+ - クライアントは受け取るレスポンス型を完全に推論可能
138
+
139
+ 2. **クライアント側補完強化**
140
+
141
+ - `status`, `content-type`, `json()`, `text()` などが適切に補完される
142
+
143
+ 3. **サーバー側 params / query も型安全**
144
+ - `routeHandlerFactory()` を使えば、`params`, `query` も型推論可能
145
+
146
+ ---
147
+
148
+ ### ✅ 基本的な使い方
149
+
150
+ ```ts
151
+ const createRouteHandler = routeHandlerFactory((err, rc) =>
152
+ rc.text("error", { status: 400 })
153
+ );
154
+
155
+ const { POST } = createRouteHandler().post(
156
+ async (rc) => rc.json("json response"),
157
+ async (rc) => rc.text("plain text")
158
+ );
159
+ ```
160
+
161
+ これだけで、POST リクエストの返り値が、responseの内容(json,textなど)、status,contenttypeが型付けされるようになります。
162
+
118
163
  ## 🚧 Requirements
119
164
 
120
165
  - Next.js 14+ (App Router 使用)
@@ -125,5 +170,3 @@ export default async function Page() {
125
170
  ## 💼 License
126
171
 
127
172
  MIT
128
-
129
- ---
@@ -12,7 +12,7 @@ const cache_1 = require("./cache");
12
12
  const constants_1 = require("./constants");
13
13
  const scan_utils_1 = require("./scan-utils");
14
14
  const type_utils_1 = require("./type-utils");
15
- const constants_2 = require("../lib/constants");
15
+ const constants_2 = require("../../lib/constants");
16
16
  const endPointFileNames = new Set(constants_1.END_POINT_FILE_NAMES);
17
17
  const hasTargetFiles = (dirPath) => {
18
18
  // Return cached result if available
@@ -1,4 +1,4 @@
1
- import { HttpMethod } from "../lib/types";
1
+ import { HttpMethod } from "../../lib/types";
2
2
  export declare const createImportAlias: (type: string, key: string) => string;
3
3
  export declare const scanFile: <T extends string | undefined>(outputFile: string, inputFile: string, findCallBack: (fileContents: string) => T, typeCallBack: (type: NonNullable<T>, importAlias: string) => string) => {
4
4
  importName: string;
@@ -0,0 +1,2 @@
1
+ import type { END_POINT_FILE_NAMES } from "./constants";
2
+ export type EndPointFileNames = (typeof END_POINT_FILE_NAMES)[number];
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.generate = void 0;
7
7
  const fs_1 = __importDefault(require("fs"));
8
- const generate_path_structure_1 = require("./generate-path-structure");
8
+ const generate_path_structure_1 = require("./core/generate-path-structure");
9
9
  const generate = ({ baseDir, outputPath, paramsFileName, logger, }) => {
10
10
  logger.info("Generating...");
11
11
  const { pathStructure, paramsTypes } = (0, generate_path_structure_1.generatePages)(outputPath, baseDir);
@@ -1,5 +1,3 @@
1
- import type { END_POINT_FILE_NAMES } from "./constants";
2
- export type EndPointFileNames = (typeof END_POINT_FILE_NAMES)[number];
3
1
  export interface Logger {
4
2
  info: (msg: string) => void;
5
3
  success: (msg: string) => void;
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.setupWatcher = void 0;
7
7
  const chokidar_1 = __importDefault(require("chokidar"));
8
- const cache_1 = require("./cache");
8
+ const cache_1 = require("./core/cache");
9
9
  const debounce_1 = require("./debounce");
10
10
  const setupWatcher = (baseDir, onGenerate, logger) => {
11
11
  logger.info(`Watching ${baseDir}...`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rpc4next",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Inspired by Hono RPC and Pathpida, rpc4next brings a lightweight and intuitive RPC solution to Next.js, making server-client communication seamless",
5
5
  "author": "watanabe-1",
6
6
  "license": "MIT",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes