rpc4next 0.3.9 → 0.4.9

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 (34) hide show
  1. package/dist/index.js +1 -0
  2. package/dist/rpc/client/client-utils.d.ts +6 -0
  3. package/dist/rpc/client/client-utils.js +1 -1
  4. package/dist/rpc/client/http-method.d.ts +17 -1
  5. package/dist/rpc/client/http-method.js +1 -1
  6. package/dist/rpc/client/index.d.ts +1 -1
  7. package/dist/rpc/client/match.d.ts +12 -1
  8. package/dist/rpc/client/match.js +1 -1
  9. package/dist/rpc/client/rpc.js +1 -1
  10. package/dist/rpc/client/types.d.ts +37 -24
  11. package/dist/rpc/client/url.d.ts +118 -0
  12. package/dist/rpc/lib/content-type-types.d.ts +1 -1
  13. package/dist/rpc/lib/headers.d.ts +36 -0
  14. package/dist/rpc/lib/headers.js +1 -0
  15. package/dist/rpc/lib/http-request-headers-types.d.ts +11 -6
  16. package/dist/rpc/lib/http-response-headers-types.d.ts +28 -5
  17. package/dist/rpc/lib/search-params.d.ts +35 -0
  18. package/dist/rpc/lib/types.d.ts +1 -2
  19. package/dist/rpc/server/handler.d.ts +1 -1
  20. package/dist/rpc/server/route-context.js +1 -1
  21. package/dist/rpc/server/route-handler-factory.js +1 -1
  22. package/dist/rpc/server/route-types.d.ts +1 -1
  23. package/dist/rpc/server/types.d.ts +14 -9
  24. package/dist/rpc/server/validators/validator.d.ts +1 -1
  25. package/dist/rpc/server/validators/validator.js +1 -1
  26. package/dist/rpc/server/validators/zod/zod-validator.d.ts +2 -2
  27. package/package.json +44 -36
  28. package/LICENSE +0 -21
  29. package/README.md +0 -164
  30. package/dist/rpc/cli/index.js +0 -7
  31. package/dist/rpc/lib/constants.d.ts +0 -6
  32. package/dist/rpc/lib/constants.js +0 -1
  33. package/dist/rpc/server/server-utils.d.ts +0 -1
  34. /package/dist/rpc/{server/server-utils.js → lib/search-params.js} +0 -0
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Normalizes various `HeadersInit` formats into a plain object
3
+ * with lower-cased header names.
4
+ *
5
+ * This utility converts `Headers`, an array of `[key, value]` tuples,
6
+ * or a plain object into a `Record<string, string>`.
7
+ *
8
+ * All header names are converted to lowercase to ensure
9
+ * case-insensitive consistency when accessing header values.
10
+ *
11
+ * @param headers - A `HeadersInit` value (`Headers`, `[string, string][]`, or `Record<string, string>`).
12
+ * If `undefined`, an empty object is returned.
13
+ *
14
+ * @returns A plain object whose keys are lower-cased header names
15
+ * and whose values are header strings.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const headers = new Headers({
20
+ * "Content-Type": "application/json",
21
+ * "Authorization": "Bearer token",
22
+ * });
23
+ *
24
+ * const normalized = normalizeHeaders(headers);
25
+ * // {
26
+ * // "content-type": "application/json",
27
+ * // "authorization": "Bearer token"
28
+ * // }
29
+ * ```
30
+ *
31
+ * @remarks
32
+ * - If duplicate header names exist (ignoring case),
33
+ * the last encountered value will overwrite previous ones.
34
+ * - This function does not merge multiple values for the same header.
35
+ */
36
+ export declare const normalizeHeaders: (headers?: HeadersInit) => Record<string, string>;
@@ -0,0 +1 @@
1
+ const n=t=>{const r={};return t?t instanceof Headers?(t.forEach((o,e)=>{r[e.toLowerCase()]=o}),r):Array.isArray(t)?(t.forEach(([o,e])=>{r[o.toLowerCase()]=e}),r):(Object.entries(t).forEach(([o,e])=>{r[o.toLowerCase()]=e}),r):r};export{n as normalizeHeaders};
@@ -6,6 +6,7 @@ import type { ContentType } from "../server";
6
6
  export type HttpRequestHeaders = Partial<{
7
7
  Accept: string;
8
8
  "Accept-Charset": string;
9
+ "Accept-Datetime": string;
9
10
  "Accept-Encoding": string;
10
11
  "Accept-Language": string;
11
12
  Authorization: string;
@@ -26,24 +27,28 @@ export type HttpRequestHeaders = Partial<{
26
27
  "If-Unmodified-Since": string;
27
28
  "Max-Forwards": string;
28
29
  Origin: string;
29
- Pragma: string;
30
30
  Range: string;
31
31
  Referer: string;
32
32
  TE: string;
33
33
  Trailer: string;
34
34
  "Transfer-Encoding": string;
35
35
  Upgrade: string;
36
+ "Upgrade-Insecure-Requests": string;
36
37
  "User-Agent": string;
37
38
  Via: string;
38
- Warning: string;
39
39
  "Access-Control-Request-Method": string;
40
40
  "Access-Control-Request-Headers": string;
41
- DNT: string;
42
41
  "Sec-Fetch-Dest": string;
43
42
  "Sec-Fetch-Mode": string;
44
43
  "Sec-Fetch-Site": string;
45
44
  "Sec-Fetch-User": string;
46
- "Sec-CH-UA": string;
47
- "Sec-CH-UA-Platform": string;
48
- "Sec-CH-UA-Mobile": string;
45
+ "Sec-Purpose": string;
46
+ "Device-Memory": string;
47
+ Priority: string;
48
+ "Origin-Agent-Cluster": string;
49
+ "Service-Worker": string;
50
+ "Service-Worker-Allowed": string;
51
+ "Service-Worker-Navigation-Preload": string;
52
+ "Set-Login": string;
53
+ SourceMap: string;
49
54
  }>;
@@ -10,26 +10,29 @@ export type HttpResponseHeaders<TContentType extends ContentType> = Partial<{
10
10
  Expires: string;
11
11
  ETag: string;
12
12
  "Last-Modified": string;
13
+ Age: string;
13
14
  "Content-Type": TContentType;
14
15
  "Content-Length": string;
15
16
  "Content-Encoding": string;
16
17
  "Content-Language": string;
17
18
  "Content-Location": string;
18
19
  "Content-Disposition": string;
20
+ "Content-Range": string;
21
+ "Content-Digest": string;
22
+ "Content-Security-Policy": string;
23
+ "Content-Security-Policy-Report-Only": string;
19
24
  "Access-Control-Allow-Origin": string;
20
25
  "Access-Control-Allow-Credentials": string;
21
26
  "Access-Control-Allow-Headers": string;
22
27
  "Access-Control-Allow-Methods": string;
23
28
  "Access-Control-Expose-Headers": string;
29
+ "Access-Control-Max-Age": string;
24
30
  "WWW-Authenticate": string;
25
- Authorization: string;
31
+ "Proxy-Authenticate": string;
26
32
  "Strict-Transport-Security": string;
27
- "Content-Security-Policy": string;
28
33
  "X-Content-Type-Options": string;
29
34
  "X-Frame-Options": string;
30
- "X-XSS-Protection": string;
31
35
  "Referrer-Policy": string;
32
- "Permissions-Policy": string;
33
36
  "Cross-Origin-Opener-Policy": string;
34
37
  "Cross-Origin-Embedder-Policy": string;
35
38
  "Cross-Origin-Resource-Policy": string;
@@ -40,7 +43,27 @@ export type HttpResponseHeaders<TContentType extends ContentType> = Partial<{
40
43
  "Transfer-Encoding": string;
41
44
  Upgrade: string;
42
45
  Vary: string;
46
+ Trailer: string;
47
+ "Upgrade-Insecure-Requests": string;
43
48
  Date: string;
44
49
  Server: string;
45
- "X-Powered-By": string;
50
+ "Accept-CH": string;
51
+ "Accept-Patch": string;
52
+ "Accept-Post": string;
53
+ "Accept-Ranges": string;
54
+ Allow: string;
55
+ "Alt-Svc": string;
56
+ "Alt-Used": string;
57
+ "Clear-Site-Data": string;
58
+ Link: string;
59
+ "Origin-Agent-Cluster": string;
60
+ "Preference-Applied": string;
61
+ Priority: string;
62
+ "Reporting-Endpoints": string;
63
+ "Retry-After": string;
64
+ "Server-Timing": string;
65
+ SourceMap: string;
66
+ "Timing-Allow-Origin": string;
67
+ "Want-Content-Digest": string;
68
+ "Want-Repr-Digest": string;
46
69
  }>;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Converts a `URLSearchParams` instance into a plain object.
3
+ *
4
+ * This utility aggregates query parameters into an object where:
5
+ * - The first occurrence of a key becomes a `string`
6
+ * - If the same key appears multiple times, the value becomes a `string[]`
7
+ *
8
+ * The returned object is cast to the generic type `T`. This is a **type-level**
9
+ * convenience: the runtime output only contains `string` or `string[]` values
10
+ * (no `undefined` keys are produced).
11
+ *
12
+ * @typeParam T - The desired return shape. Must be a record of `string` keys
13
+ * with values `string | string[] | undefined`. Note: `undefined` is allowed in
14
+ * the type to support downstream optional fields, but is not produced at runtime.
15
+ *
16
+ * @param searchParams - The `URLSearchParams` to convert.
17
+ * @returns A plain object containing the query parameters.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * const sp = new URLSearchParams("q=chatgpt&tag=a&tag=b");
22
+ * const obj = searchParamsToObject(sp);
23
+ * // => { q: "chatgpt", tag: ["a", "b"] }
24
+ * ```
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * type Params = { q?: string; tag?: string[] };
29
+ * const sp = new URLSearchParams("q=hello&tag=a&tag=b");
30
+ * const obj = searchParamsToObject<Params>(sp);
31
+ * // obj.q is typed as string | undefined
32
+ * // obj.tag is typed as string[] | undefined
33
+ * ```
34
+ */
35
+ export declare const searchParamsToObject: <T extends Record<string, string | string[] | undefined>>(searchParams: URLSearchParams) => T;
@@ -1,2 +1 @@
1
- import type { HTTP_METHODS } from "./constants";
2
- export type HttpMethod = (typeof HTTP_METHODS)[number];
1
+ export type { HttpMethod } from "rpc4next-shared";
@@ -1,4 +1,4 @@
1
1
  import type { ValidationSchema, RouteResponse, Handler } from "./route-types";
2
2
  import type { Params, Query } from "./types";
3
- import type { HttpMethod } from "../lib/types";
3
+ import type { HttpMethod } from "rpc4next-shared";
4
4
  export declare const createHandler: <THttpMethod extends HttpMethod, TParams extends Params, TQuery extends Query, TValidationSchema extends ValidationSchema>() => <TRouteResponse extends RouteResponse>(handler: Handler<THttpMethod, TParams, TQuery, TValidationSchema, TRouteResponse>) => Handler<THttpMethod, TParams, TQuery, TValidationSchema, TRouteResponse>;
@@ -1 +1 @@
1
- import{NextResponse as a}from"next/server";import{searchParamsToObject as p}from"./server-utils";const d=(s,o)=>{const n={};return{req:Object.assign(s,{query:()=>p(s.nextUrl.searchParams),params:()=>o.params,valid:t=>n[t],addValidatedData:(t,e)=>{n[t]=e}}),body:(t,e)=>new a(t,e),json:(t,e)=>a.json(t,e),text:(t,e)=>new a(t,{...e,headers:{"Content-Type":"text/plain",...e?.headers}}),redirect:(t,e)=>a.redirect(t,e)}};export{d as createRouteContext};
1
+ import{NextResponse as n}from"next/server";import{normalizeHeaders as T}from"../lib/headers";import{searchParamsToObject as i}from"../lib/search-params";const p=t=>typeof t=="number"&&!Number.isNaN(t),o=t=>{if(!t)return t;if(p(t))return{status:t};const r=t.headers??T(t.headersInit),{headers:d,headersInit:a,...e}=t;return{...e,headers:r}},S=(t,r)=>{const d={};return{req:Object.assign(t,{query:()=>i(t.nextUrl.searchParams),params:()=>r.params,valid:a=>d[a],addValidatedData:(a,e)=>{d[a]=e}}),body:(a,e)=>new n(a,o(e)),json:(a,e)=>n.json(a,o(e)),text:(a,e)=>{const s=o(e);return new n(a,{...s,headers:{...s?.headers,"Content-Type":"text/plain"}})},redirect:(a,e)=>{const s=p(e)?e:o(e);return n.redirect(a,s)}}};export{S as createRouteContext};
@@ -1,4 +1,4 @@
1
1
  /*!
2
2
  * Inspired by Hono (https://github.com/honojs/hono),
3
3
  * particularly its routing design and handler interface.
4
- */import{createRouteContext as d}from"./route-context";const i=(o,e)=>async(n,s)=>{const a=d(n,s);try{for(const t of o){const r=await t(a);if(r instanceof Response)return r}throw new Error("No handler returned a response")}catch(t){return await e(t,a)}},T=o=>()=>{const e=n=>(...s)=>{const t=i(s,o??((r,p)=>{throw r}));return{[n]:t}};return{get:e("GET"),post:e("POST"),put:e("PUT"),delete:e("DELETE"),patch:e("PATCH"),head:e("HEAD"),options:e("OPTIONS")}};export{T as routeHandlerFactory};
4
+ */import{createRouteContext as d}from"./route-context";const i=(o,e)=>async(n,s)=>{const a=d(n,s);try{for(const r of o){const t=await r(a);if(t instanceof Response)return t}throw new Error("No handler returned a response")}catch(r){return await e(r,a)}},T=o=>()=>{const e=n=>((...s)=>{const r=i(s,o??((t,p)=>{throw t}));return{[n]:r}});return{get:e("GET"),post:e("POST"),put:e("PUT"),delete:e("DELETE"),patch:e("PATCH"),head:e("HEAD"),options:e("OPTIONS")}};export{T as routeHandlerFactory};
@@ -7,8 +7,8 @@
7
7
  * Hono is licensed under the MIT License.
8
8
  */
9
9
  import type { TypedNextResponse, Query, RouteContext, Params } from "./types";
10
- import type { HttpMethod } from "../lib/types";
11
10
  import type { NextRequest } from "next/server";
11
+ import type { HttpMethod } from "rpc4next-shared";
12
12
  export type RouteResponse = TypedNextResponse | Promise<TypedNextResponse | void>;
13
13
  export type RequiredRouteResponse = TypedNextResponse | Promise<TypedNextResponse>;
14
14
  export interface RouteBindings {
@@ -2,8 +2,8 @@ import type { ValidationSchema } from "./route-types";
2
2
  import type { ContentType } from "../lib/content-type-types";
3
3
  import type { HttpResponseHeaders } from "../lib/http-response-headers-types";
4
4
  import type { HttpStatusCode, RedirectionHttpStatusCode, SuccessfulHttpStatusCode } from "../lib/http-status-code-types";
5
- import type { HttpMethod } from "../lib/types";
6
5
  import type { NextResponse, NextRequest } from "next/server";
6
+ import type { HttpMethod } from "rpc4next-shared";
7
7
  /**
8
8
  * Represents the result of an HTTP response status check.
9
9
  *
@@ -28,10 +28,15 @@ type HttpStatus<T extends HttpStatusCode> = T extends SuccessfulHttpStatusCode ?
28
28
  * @template TStatus - The HTTP status code.
29
29
  * @template TContentType - The content type of the response.
30
30
  */
31
- export interface TypedResponseInit<TStatus extends HttpStatusCode, TContentType extends ContentType> extends ResponseInit {
32
- headers?: HttpResponseHeaders<TContentType> | HeadersInit;
31
+ export type TypedResponseInit<TStatus extends HttpStatusCode, TContentType extends ContentType> = ({
32
+ headers?: HttpResponseHeaders<TContentType> & Record<string, string>;
33
+ headersInit?: never;
34
+ } & Omit<ResponseInit, "headers">) | (({
35
+ headers?: never;
36
+ headersInit?: HeadersInit;
37
+ } & Omit<ResponseInit, "headers">) & {
33
38
  status?: TStatus;
34
- }
39
+ });
35
40
  /**
36
41
  * A strongly typed wrapper around the standard Next.js `NextResponse` object,
37
42
  * with additional type information for status code, content type, and response body.
@@ -118,7 +123,7 @@ export interface RouteContext<TParams = Params, TQuery = Query, TValidationSchem
118
123
  * @param init - Optional response init.
119
124
  * @returns A typed response.
120
125
  */
121
- body: <TData extends BodyInit | null, TContentType extends ContentType, TStatus extends HttpStatusCode = 200>(data: TData, init?: TypedResponseInit<TStatus, TContentType>) => TypedNextResponse<TData, TStatus, TContentType>;
126
+ body: <TData extends BodyInit | null, TContentType extends ContentType, TStatus extends HttpStatusCode = 200>(data: TData, init?: TStatus | TypedResponseInit<TStatus, TContentType>) => TypedNextResponse<TData, TStatus, TContentType>;
122
127
  /**
123
128
  * Creates a typed JSON response using `NextResponse.json(...)`.
124
129
  *
@@ -126,7 +131,7 @@ export interface RouteContext<TParams = Params, TQuery = Query, TValidationSchem
126
131
  * @param init - Optional response init.
127
132
  * @returns A JSON response.
128
133
  */
129
- json: <TData, TStatus extends HttpStatusCode = 200>(data: TData, init?: TypedResponseInit<TStatus, "application/json">) => TypedNextResponse<TData, TStatus, "application/json">;
134
+ json: <TData, TStatus extends HttpStatusCode = 200>(data: TData, init?: TStatus | TypedResponseInit<TStatus, "application/json">) => TypedNextResponse<TData, TStatus, "application/json">;
130
135
  /**
131
136
  * Creates a plain text response with `Content-Type: text/plain`.
132
137
  * Internally uses `new NextResponse(...)` with headers.
@@ -135,16 +140,16 @@ export interface RouteContext<TParams = Params, TQuery = Query, TValidationSchem
135
140
  * @param init - Optional response init.
136
141
  * @returns A plain text response.
137
142
  */
138
- text: <TData extends string, TStatus extends HttpStatusCode = 200>(data: TData, init?: TypedResponseInit<TStatus, "text/plain">) => TypedNextResponse<TData, TStatus, "text/plain">;
143
+ text: <TData extends string, TStatus extends HttpStatusCode = 200>(data: TData, init?: TStatus | TypedResponseInit<TStatus, "text/plain">) => TypedNextResponse<TData, TStatus, "text/plain">;
139
144
  /**
140
145
  * Issues a redirect response.
141
146
  * Internally wraps `NextResponse.redirect(...)`.
142
147
  *
143
148
  * @param url - The URL to redirect to.
144
- * @param init - Optional redirect status code (default: 302).
149
+ * @param init - Optional redirect status code (default: 307).
145
150
  * @returns A redirect response.
146
151
  */
147
- redirect: <TStatus extends RedirectionHttpStatusCode = 302>(url: string, init?: TStatus | TypedResponseInit<TStatus, "">) => TypedNextResponse<undefined, TStatus, "">;
152
+ redirect: <TStatus extends RedirectionHttpStatusCode = 307>(url: string, init?: TStatus | TypedResponseInit<TStatus, "">) => TypedNextResponse<undefined, TStatus, "">;
148
153
  }
149
154
  declare const __validatedBrand: unique symbol;
150
155
  export type ValidatedData = {
@@ -6,7 +6,7 @@
6
6
  * Original copyright belongs to Yusuke Wada and the Hono project contributors.
7
7
  * Hono is licensed under the MIT License.
8
8
  */
9
- import type { HttpMethod } from "../../lib/types";
10
9
  import type { ValidationSchema } from "../route-types";
11
10
  import type { Params, Query, RouteContext, TypedNextResponse, ValidatedData, ValidationTarget } from "../types";
11
+ import type { HttpMethod } from "rpc4next-shared";
12
12
  export declare const validator: <THttpMethod extends HttpMethod, TValidationTarget extends ValidationTarget<THttpMethod>, TParams extends Params, TQuery extends Query, TValidationSchema extends ValidationSchema>() => <TTypedNextResponse extends TypedNextResponse>(target: TValidationTarget, validateHandler: (value: object, routeContext: RouteContext<TParams, TQuery, TValidationSchema>) => Promise<ValidatedData | TTypedNextResponse>) => import("../route-types").Handler<THttpMethod, TParams, TQuery, TValidationSchema, Promise<TTypedNextResponse | undefined>>;
@@ -5,4 +5,4 @@
5
5
  * This code has been adapted and modified for this project.
6
6
  * Original copyright belongs to Yusuke Wada and the Hono project contributors.
7
7
  * Hono is licensed under the MIT License.
8
- */import{createHandler as i}from"../handler";import{getCookiesObject as n,getHeadersObject as s}from"./validator-utils";const T=()=>(e,r)=>i()(async t=>{const o=await(async()=>{if(e==="params")return await t.req.params();if(e==="query")return t.req.query();if(e==="json")return t.req.json();if(e==="headers")return await s();if(e==="cookies")return await n();throw new Error(`Unexpected target: ${e}`)})(),a=await r(o,t);if(a instanceof Response)return a;t.req.addValidatedData(e,a)});export{T as validator};
8
+ */import{createHandler as n}from"../handler";import{getCookiesObject as i,getHeadersObject as s}from"./validator-utils";const T=()=>(e,r)=>n()(async t=>{const o=await(async()=>{if(e==="params")return await t.req.params();if(e==="query")return t.req.query();if(e==="json")return t.req.json();if(e==="headers")return await s();if(e==="cookies")return await i();throw new Error(`Unexpected target: ${e}`)})(),a=await r(o,t);if(a instanceof Response)return a;t.req.addValidatedData(e,a)});export{T as validator};
@@ -6,11 +6,11 @@
6
6
  * Original copyright belongs to Yusuke Wada and the Hono project contributors.
7
7
  * Hono is licensed under the MIT License.
8
8
  */
9
- import type { HttpMethod } from "../../../lib/types";
10
9
  import type { ValidationSchema } from "../../route-types";
11
10
  import type { RouteContext, Params, Query, TypedNextResponse, ConditionalValidationInput, ValidationTarget } from "../../types";
11
+ import type { HttpMethod } from "rpc4next-shared";
12
12
  import type { z, ZodSchema } from "zod";
13
13
  export declare const zValidator: <THttpMethod extends HttpMethod, TValidationTarget extends ValidationTarget<THttpMethod>, TSchema extends ZodSchema<any>, TParams extends ConditionalValidationInput<TValidationTarget, "params", TValidationSchema, Params> & Params, TQuery extends ConditionalValidationInput<TValidationTarget, "query", TValidationSchema, Query> & Query, TInput = z.input<TSchema>, TOutput = z.output<TSchema>, TValidationSchema extends ValidationSchema = {
14
14
  input: Record<TValidationTarget, TInput>;
15
15
  output: Record<TValidationTarget, TOutput>;
16
- }, THookReturn extends TypedNextResponse | void = TypedNextResponse<z.SafeParseError<TInput>, 400, "application/json"> | void>(target: TValidationTarget, schema: TSchema, hook?: (result: z.SafeParseReturnType<TInput, TOutput>, routeContext: RouteContext<TParams, TQuery, TValidationSchema>) => THookReturn) => import("../../route-types").Handler<THttpMethod, TParams, TQuery, TValidationSchema, Promise<Exclude<THookReturn, void> | undefined>>;
16
+ }, THookReturn extends TypedNextResponse | void = TypedNextResponse<z.ZodSafeParseError<TInput>, 400, "application/json"> | void>(target: TValidationTarget, schema: TSchema, hook?: (result: z.ZodSafeParseResult<TOutput>, routeContext: RouteContext<TParams, TQuery, TValidationSchema>) => THookReturn) => import("../../route-types").Handler<THttpMethod, TParams, TQuery, TValidationSchema, Promise<Exclude<THookReturn, void> | undefined>>;
package/package.json CHANGED
@@ -1,22 +1,24 @@
1
1
  {
2
2
  "name": "rpc4next",
3
- "version": "0.3.9",
4
3
  "description": "Inspired by Hono RPC and Pathpida, rpc4next brings a lightweight and intuitive RPC solution to Next.js, making server-client communication seamless",
5
4
  "author": "watanabe-1",
6
5
  "license": "MIT",
7
6
  "repository": {
8
7
  "type": "git",
9
- "url": "https://github.com/watanabe-1/rpc4next"
8
+ "url": "git+https://github.com/watanabe-1/rpc4next.git",
9
+ "directory": "packages/rpc4next"
10
10
  },
11
11
  "homepage": "https://github.com/watanabe-1/rpc4next#readme",
12
12
  "bugs": {
13
13
  "url": "https://github.com/watanabe-1/rpc4next/issues"
14
14
  },
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
15
18
  "keywords": [
16
19
  "next.js",
17
20
  "rpc",
18
- "typescript",
19
- "cli"
21
+ "typescript"
20
22
  ],
21
23
  "type": "module",
22
24
  "module": "dist/index.js",
@@ -24,10 +26,17 @@
24
26
  "files": [
25
27
  "dist"
26
28
  ],
27
- "bin": {
28
- "rpc4next": "dist/rpc/cli/index.js"
29
- },
30
29
  "exports": {
30
+ ".": {
31
+ "import": {
32
+ "types": "./dist/index.d.ts",
33
+ "default": "./dist/index.js"
34
+ },
35
+ "default": {
36
+ "types": "./dist/index.d.ts",
37
+ "default": "./dist/index.js"
38
+ }
39
+ },
31
40
  "./client": {
32
41
  "import": {
33
42
  "types": "./dist/rpc/client/index.d.ts",
@@ -57,46 +66,45 @@
57
66
  "types": "./dist/rpc/server/validators/zod/index.d.ts",
58
67
  "default": "./dist/rpc/server/validators/zod/index.js"
59
68
  }
69
+ },
70
+ "./lib/constants": {
71
+ "import": {
72
+ "types": "./dist/rpc/lib/constants.d.ts",
73
+ "default": "./dist/rpc/lib/constants.js"
74
+ },
75
+ "default": {
76
+ "types": "./dist/rpc/lib/constants.d.ts",
77
+ "default": "./dist/rpc/lib/constants.js"
78
+ }
79
+ },
80
+ "./lib/types": {
81
+ "import": {
82
+ "types": "./dist/rpc/lib/types.d.ts",
83
+ "default": "./dist/rpc/lib/types.js"
84
+ },
85
+ "default": {
86
+ "types": "./dist/rpc/lib/types.d.ts",
87
+ "default": "./dist/rpc/lib/types.js"
88
+ }
60
89
  }
61
90
  },
62
91
  "scripts": {
63
92
  "build": "bun run clean && bun build.ts && bun run build:types",
64
- "build:types": "tsc -p tsconfig.build-types.json",
65
- "clean": "bun -e \"require('fs').rmSync('dist', { recursive: true, force: true })\"",
93
+ "build:types": "tsc -b --force tsconfig.build-types.json",
94
+ "clean": "bun -e \"const fs=require('fs'); fs.rmSync('dist',{recursive:true,force:true}); fs.rmSync('tsconfig.build-types.tsbuildinfo',{force:true}); fs.rmSync('tsconfig.tsbuildinfo',{force:true});\"",
66
95
  "test": "vitest run",
67
96
  "test:coverage": "vitest run --coverage.enabled true",
68
97
  "test:ui": "vitest --ui --coverage.enabled true",
69
98
  "test:watch": "vitest --watch",
70
- "lint": "eslint \"**/*.ts\"",
71
- "lint:fix": "eslint \"**/*.ts\" --fix",
72
- "typecheck": "tsc --noEmit"
99
+ "lint": "eslint \"src/**/*.ts\"",
100
+ "lint:fix": "eslint \"src/**/*.ts\" --fix",
101
+ "typecheck": "tsc -b tsconfig.build.json --noEmit"
73
102
  },
74
103
  "dependencies": {
75
- "chalk": "^5.4.1",
76
- "chokidar": "^4.0.3",
77
- "commander": "^13.1.0"
78
- },
79
- "devDependencies": {
80
- "@types/node": "^22.15.2",
81
- "@vitest/coverage-v8": "^3.1.2",
82
- "@vitest/eslint-plugin": "^1.1.43",
83
- "@vitest/ui": "^3.1.2",
84
- "esbuild": "^0.25.3",
85
- "eslint": "^9.25.1",
86
- "eslint-config-prettier": "^10.1.2",
87
- "eslint-plugin-import": "^2.31.0",
88
- "eslint-plugin-unused-imports": "^4.1.4",
89
- "mock-fs": "^5.5.0",
90
- "msw": "^2.7.5",
91
- "next": "15.3.1",
92
- "prettier": "^3.5.3",
93
- "ts-node": "^10.9.2",
94
- "typescript": "^5.8.3",
95
- "typescript-eslint": "^8.31.0",
96
- "vitest": "^3.1.2",
97
- "zod": "^3.24.3"
104
+ "rpc4next-shared": "workspace:*"
98
105
  },
99
106
  "peerDependencies": {
100
107
  "next": "^14.0.0 || ^15.0.0"
101
- }
108
+ },
109
+ "version": "0.4.9"
102
110
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 watanabe-1
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/README.md DELETED
@@ -1,164 +0,0 @@
1
- # rpc4next
2
-
3
- Lightweight, type-safe RPC system for Next.js App Router projects.
4
-
5
- Inspired by Hono RPC and Pathpida, **rpc4next** automatically generates a type-safe client for your existing `route.ts` **and** `page.tsx` files, enabling seamless server-client communication with full type inference.
6
-
7
- ---
8
-
9
- ## ✨ Features
10
-
11
- - ✅ ルート、パラメータ、クエリパラメータ、 リクエストボディ、レスポンスの型安全なクライアント生成
12
- - ✅ 既存の `app/**/route.ts` および `app/**/page.tsx` を活用するため、新たなハンドラファイルの作成は不要
13
- - ✅ 最小限のセットアップで、カスタムサーバー不要
14
- - ✅ 動的ルート(`[id]`、`[...slug]` など)に対応
15
- - ✅ CLI による自動クライアント用型定義生成
16
-
17
- ---
18
-
19
- ## 🚀 Getting Started
20
-
21
- ### 1. Install rpc4next
22
-
23
- ```bash
24
- npm install rpc4next
25
- ```
26
-
27
- ### 2. Define API Routes in Next.js
28
-
29
- Next.js プロジェクト内の既存の `app/**/route.ts` と `app/**/page.tsx` ファイルをそのまま利用できます。
30
- さらに、クエリパラメータ(searchParams)の型安全性を有効にするには、対象のファイル内で `Query` または `OptionalQuery` 型を定義し、`export` してください。
31
-
32
- ```ts
33
- // app/api/user/[id]/route.ts
34
- import { NextRequest, NextResponse } from "next/server";
35
-
36
- // searchParams用の型定義
37
- export type Query = {
38
- q: string; // 必須
39
- page?: number; // 任意
40
- };
41
-
42
- export async function GET(
43
- req: NextRequest,
44
- segmentData: { params: Promise<{ id: string }> }
45
- ) {
46
- const { id } = await segmentData.params;
47
- const q = req.nextUrl.searchParams.get("q");
48
- return NextResponse.json({ id, q });
49
- }
50
- ```
51
-
52
- 🚩 Query or OptionalQuery 型を export することで、searchParams の型も自動的にクライアントに反映されます。
53
-
54
- - **RPCとしてresponseの戻り値の推論が機能するのは、対象となる `route.ts` の HTTPメソッドハンドラ内で`NextResponse.json()` をしている関数のみになります**
55
-
56
- ---
57
-
58
- ### 3. Generate Type Definitions with CLI
59
-
60
- CLI を利用して、Next.js のルート構造から型安全な RPC クライアントの定義を自動生成します。
61
-
62
- ```bash
63
- npx rpc4next <baseDir> <outputPath>
64
- ```
65
-
66
- - `<baseDir>`: Next.js の Appルータが配置されたベースディレクトリ
67
- - `<outputPath>`: 生成された型定義ファイルの出力先
68
-
69
- #### オプション
70
-
71
- - **ウォッチモード**
72
- ファイル変更を検知して自動的に再生成する場合は `--watch` or `-w` オプションを付けます。
73
-
74
- ```bash
75
- npx rpc4next <baseDir> <outputPath> --watch
76
- ```
77
-
78
- - **パラメータ型ファイルの生成**
79
- 各ルートに対して個別のパラメータ型定義ファイルを生成する場合は、`--params-file` or `-p` オプションにファイル名を指定します。
80
-
81
- ```bash
82
- npx rpc4next <baseDir> <outputPath> --generate-params-types <paramsFileName>
83
- ```
84
-
85
- ---
86
-
87
- ### 4. Create Your RPC Client
88
-
89
- 生成された型定義ファイルを基に、RPC クライアントを作成します。
90
-
91
- ```ts
92
- // lib/rpcClient.ts
93
- import { createClient } from "rpc4next/client";
94
- import type { PathStructure } from "あなたが生成した型定義ファイル";
95
-
96
- export const rpc = createClient<PathStructure>();
97
- ```
98
-
99
- ---
100
-
101
- ### 5. Use It in Your Components
102
-
103
- コンポーネント内で生成された RPC クライアントを使用します。
104
-
105
- ```tsx
106
- // app/page.tsx
107
- import { rpc } from "@/lib/rpcClient";
108
-
109
- export default async function Page() {
110
- const res = await rpc.api.user._id("123").$get({
111
- query: { q: "hello", page: 1 },
112
- });
113
- const json = await res.json();
114
- return <div>{json.q}</div>;
115
- }
116
- ```
117
-
118
- - エディタの補完機能により、利用可能なエンドポイントが自動的に表示されます。
119
- - リクエストの構造(params, query)はサーバーコードから推論され、レスポンスも型安全に扱えます。
120
-
121
- ---
122
-
123
- ## ✅ さらに型安全にしたい場合 `honolike` + `createRouteHandler` による Next.js の型安全強化
124
-
125
- さらに `honolike` をベースとした `createRouteHandler()` を組み合わせることで、
126
-
127
- ### 📌 主なメリット
128
-
129
- 1. **レスポンス型安全**
130
-
131
- - ステータス、Content-Type、Body がすべて型で保証される
132
- - クライアントは受け取るレスポンス型を完全に推論可能
133
-
134
- 2. **クライアント側補完強化**
135
-
136
- - `status`, `content-type`, `json()`, `text()` などが適切に補完される
137
-
138
- 3. **サーバー側 params / query も型安全**
139
- - `routeHandlerFactory()` を使えば、`params`, `query` も型推論可能
140
-
141
- ---
142
-
143
- ### ✅ 基本的な使い方
144
-
145
- ```ts
146
- const createRouteHandler = routeHandlerFactory((err, rc) =>
147
- rc.text("error", { status: 400 })
148
- );
149
-
150
- const { POST } = createRouteHandler().post(async (rc) => rc.text("plain text"));
151
- ```
152
-
153
- これだけで、POST リクエストの返り値が、responseの内容(json,textなど)、status,contenttypeが型付けされるようになります。
154
-
155
- ## 🚧 Requirements
156
-
157
- - Next.js 14+ (App Router 使用)
158
- - Node.js 18+
159
-
160
- ---
161
-
162
- ## 💼 License
163
-
164
- MIT