rpc4next 0.3.9 → 0.4.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 CHANGED
@@ -27,7 +27,7 @@ npm install rpc4next
27
27
  ### 2. Define API Routes in Next.js
28
28
 
29
29
  Next.js プロジェクト内の既存の `app/**/route.ts` と `app/**/page.tsx` ファイルをそのまま利用できます。
30
- さらに、クエリパラメータ(searchParams)の型安全性を有効にするには、対象のファイル内で `Query` または `OptionalQuery` 型を定義し、`export` してください。
30
+ さらに、クエリパラメータ(searchParams)の型安全性を有効にするには、対象のファイル内で `Query` 型を定義し、`export` してください。
31
31
 
32
32
  ```ts
33
33
  // app/api/user/[id]/route.ts
@@ -49,7 +49,7 @@ export async function GET(
49
49
  }
50
50
  ```
51
51
 
52
- 🚩 Query or OptionalQuery 型を export することで、searchParams の型も自動的にクライアントに反映されます。
52
+ 🚩 Query 型を export することで、searchParams の型も自動的にクライアントに反映されます。
53
53
 
54
54
  - **RPCとしてresponseの戻り値の推論が機能するのは、対象となる `route.ts` の HTTPメソッドハンドラ内で`NextResponse.json()` をしている関数のみになります**
55
55
 
@@ -120,9 +120,7 @@ export default async function Page() {
120
120
 
121
121
  ---
122
122
 
123
- ## ✅ さらに型安全にしたい場合 `honolike` + `createRouteHandler` による Next.js の型安全強化
124
-
125
- さらに `honolike` をベースとした `createRouteHandler()` を組み合わせることで、
123
+ ## ✅ さらに型安全にしたい場合 `createRouteHandler` による Next.js の型安全強化
126
124
 
127
125
  ### 📌 主なメリット
128
126
 
@@ -136,7 +134,8 @@ export default async function Page() {
136
134
  - `status`, `content-type`, `json()`, `text()` などが適切に補完される
137
135
 
138
136
  3. **サーバー側 params / query も型安全**
139
- - `routeHandlerFactory()` を使えば、`params`, `query` も型推論可能
137
+ - `createRouteHandler()` + `zValidator()` を使えば、`params`, `query`, `headers`, `cookies`, `json` も型推論・バリデーション可能
138
+ - `createRouteHandler()` + `zValidator()` を使えば、`Query` 型もexportする必要なし
140
139
 
141
140
  ---
142
141
 
@@ -150,7 +149,164 @@ const createRouteHandler = routeHandlerFactory((err, rc) =>
150
149
  const { POST } = createRouteHandler().post(async (rc) => rc.text("plain text"));
151
150
  ```
152
151
 
153
- これだけで、POST リクエストの返り値が、responseの内容(json,textなど)status,contenttypeが型付けされるようになります。
152
+ これだけで、POSTリクエストの返り値に、レスポンスの内容 (`json`, `text`など)、`status`, `content-type` が型付けされるようになります。
153
+
154
+ ---
155
+
156
+ ### 👤 サーバー側でのより型安全なルート作成
157
+
158
+ `createRouteHandler()` と `zValidator()` を使うことで、各リクエストパーツに対して **型安全なバリデーション** をかけられます。
159
+
160
+ #### シンプルな例
161
+
162
+ ```ts
163
+ import { createRouteHandler } from "@/path/to/createRouteHandler";
164
+ import { zValidator } from "@/path/to/zValidator";
165
+ import { z } from "zod";
166
+
167
+ // Zodスキーマを定義
168
+ const paramsSchema = z.object({
169
+ userId: z.string(),
170
+ });
171
+
172
+ // バリデーション付きルートハンドラを作成
173
+ export const { GET } = createRouteHandler<{
174
+ params: z.infer<typeof paramsSchema>;
175
+ }>().get(
176
+ zValidator("params", paramsSchema), // paramsを検証
177
+ async (rc) => {
178
+ const params = rc.req.valid("params"); // バリデーション済みparamsを取得
179
+ return rc.json({ message: `User ID is ${params.userId}` });
180
+ }
181
+ );
182
+ ```
183
+
184
+ ## ✅ サポートされているバリデーションターゲット
185
+
186
+ サーバー側では,次のリクエスト部分を型安全に検証できます:
187
+
188
+ | ターゲット | 説明 |
189
+ | :--------- | :-------------------------------------------------- |
190
+ | `params` | URLパラメータ ( `/user/:id` の `id`など) |
191
+ | `query` | クエリパラメータ (`?q=xxx&page=1`など) |
192
+ | `headers` | リクエストヘッダー |
193
+ | `cookies` | クッキー |
194
+ | `json` | リクエストボディ (Content-Type: `application/json`) |
195
+
196
+ ---
197
+
198
+ ### 🔥 複数ターゲットを同時に検証する例
199
+
200
+ ```ts
201
+ import { createRouteHandler } from "@/path/to/createRouteHandler";
202
+ import { zValidator } from "@/path/to/zValidator";
203
+ import { z } from "zod";
204
+
205
+ const querySchema = z.object({
206
+ page: z.string().regex(/^\d+$/),
207
+ });
208
+
209
+ const jsonSchema = z.object({
210
+ name: z.string(),
211
+ age: z.number(),
212
+ });
213
+
214
+ export const { POST } = createRouteHandler<{
215
+ query: z.infer<typeof querySchema>;
216
+ }>().post(
217
+ zValidator("query", querySchema),
218
+ zValidator("json", jsonSchema),
219
+ async (rc) => {
220
+ const query = rc.req.valid("query");
221
+ const body = rc.req.valid("json");
222
+ return rc.json({ query, body });
223
+ }
224
+ );
225
+ ```
226
+
227
+ - `query`と`json`を別々のスキーマで検証
228
+ - **成功時は型安全に取得可能** (`rc.req.valid('query')`, `rc.req.valid('json')`)
229
+
230
+ ---
231
+
232
+ これにより,クライアント側とサーバー側が、全面的に**型でつながる**ので,ミスを何次も防げ,開発体験を大幅に向上できます。
233
+
234
+ ---
235
+
236
+ ### ⚡ バリデーション失敗時のカスタムエラーハンドリング
237
+
238
+ - デフォルトでは、バリデーション失敗時に自動で `400 Bad Request` を返します。
239
+ - 必要に応じて、**カスタムフック**でエラー対応を制御できます。
240
+
241
+ ```ts
242
+ zValidator("params", paramsSchema, (result, rc) => {
243
+ if (!result.success) {
244
+ return rc.json({ error: result.error.errors }, { status: 422 });
245
+ }
246
+ });
247
+ ```
248
+
249
+ > (フック内でレスポンスを返さない場合は、通常通り例外がスローされます)
250
+
251
+ ---
252
+
253
+ ## 📡 クライアント側での使い方
254
+
255
+ `rpc4next`で作成したクライアントは、`createRouteHandler` と `zValidator` で作成したルートハンドラの内容にしたがって **params, query, headers, cookies, json** を型安全に送信できます。
256
+
257
+ 例:
258
+
259
+ ```ts
260
+ import { createRpcClient } from "@/path/to/rpc-client";
261
+ import type { PathStructure } from "@/path/to/generated-types";
262
+
263
+ const client = createRpcClient<PathStructure>("http://localhost:3000");
264
+
265
+ async function callUserApi() {
266
+ const res = await client.api.menu.test.$post({
267
+ body: { json: { age: 20, name: "foo" } },
268
+ url: { query: { page: "1" } },
269
+ });
270
+
271
+ if (res.ok) {
272
+ const json = await res.json();
273
+
274
+ // ✅ 正常時は次の型が推論されます
275
+ // const json: {
276
+ // query: {
277
+ // page: string;
278
+ // };
279
+ // body: {
280
+ // name: string;
281
+ // age: number;
282
+ // };
283
+ // }
284
+ } else {
285
+ const error = await res.json();
286
+
287
+ // ⚠️ バリデーションエラー時は次の型が推論されます
288
+ // const error:
289
+ // | SafeParseError<{
290
+ // page: string;
291
+ // }>
292
+ // | SafeParseError<{
293
+ // name: string;
294
+ // age: number;
295
+ // }>;
296
+ }
297
+ }
298
+ ```
299
+
300
+ - エディタの補完機能により、送信できるターゲットが明示されます
301
+ - サーバー側の型定義に基づいて、**型のズレを防止**できます
302
+
303
+ ---
304
+
305
+ これらのように、リクエスト時にはさまざまなターゲット (`params`, `query`, `headers`, `cookies`, `json`) を送信できます。
306
+
307
+ さらに、サーバー側では、これらを**個別に型付け、バリデーション**できます。
308
+
309
+ ---
154
310
 
155
311
  ## 🚧 Requirements
156
312
 
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import{Command as Wt}from"commander";import $t from"path";var R=["page.tsx","route.ts"],w=0,$=1,Y=1,M=20,W="\u2192";import U from"path";var et=(t,r)=>{let e=_(U.relative(U.dirname(t),r)).replace(/\.tsx?$/,"");return e.startsWith("../")||(e="./"+e),e},_=t=>t.replace(/\\/g,"/"),C=t=>U.relative(process.cwd(),t);import Pt from"fs";import Yt from"path";var rt=["Query","OptionalQuery"],O=" ",E=`
3
- `,S=";",H=";",j="Endpoint",X="QueryKey",K="OptionalQueryKey",Q="ParamsKey",ot=[j,K,Q,X],nt="rpc4next/client";import Tt from"fs";import b from"path";import G from"path";var g=new Map,N=new Map,st=(t,r)=>{let e=G.resolve(r);[...t.keys()].forEach(o=>{let n=G.resolve(o);(n===e||e.startsWith(n+G.sep))&&t.delete(o)})},it=t=>{st(g,t)},at=t=>{st(N,t)};import vt from"fs";import bt from"crypto";var pt=(t,r)=>{let e=bt.createHash("md5").update(`${t}::${r}`).digest("hex").slice(0,16);return`${r}_${e}`};var I=(t,r)=>!t||!r?"":`Record<${t}, ${r}>`,L=t=>t.length===0||t.some(({name:r,type:e})=>!r||!e)?"":`{ ${t.map(({name:r,type:e})=>`"${r}": ${e}`).join(`${H} `)}${t.length>1?H:""} }`,D=(t,r,e)=>!t||!r?"":e?`import type { ${t} as ${e} } from "${r}"${S}`:`import type { ${t} } from "${r}"${S}`;var ct=(t,r,e,o)=>{let n=vt.readFileSync(r,"utf8"),i=e(n);if(!i)return;let s=et(t,r),p=pt(s,i);return{importName:p,importPath:s,importStatement:D(i,s,p),type:o(i,p)}},mt=(t,r)=>ct(t,r,e=>rt.find(o=>new RegExp(`export (interface ${o} ?{|type ${o} ?=)`).test(e)),(e,o)=>e==="Query"?I(X,o):I(K,o)),lt=(t,r,e)=>ct(t,r,o=>[e].find(n=>new RegExp(`export (async )?(function ${n} ?\\(|const ${n} ?=|\\{[^}]*\\b${n}\\b[^}]*\\} ?=|const \\{[^}]*\\b${n}\\b[^}]*\\} ?=|\\{[^}]*\\b${n}\\b[^}]*\\} from)`).test(o)),(o,n)=>L([{name:`$${o.toLowerCase()}`,type:`typeof ${n}`}]));var Ft=["GET","HEAD","OPTIONS","POST","PUT","DELETE","PATCH"],ut="_____",ft="___",Et="_",k=Ft.filter(t=>t!=="OPTIONS"),oe=k.map(t=>`$${t.toLowerCase()}`);var ht=new Set(R),gt=t=>{if(g.has(t))return g.get(t);let r=Tt.readdirSync(t,{withFileTypes:!0});for(let e of r){let{name:o}=e,n=b.join(t,o);if(o==="node_modules"||o.startsWith("_")||o.startsWith("(.)")||o.startsWith("(..)")||o.startsWith("(...)"))return g.set(t,!1),!1;if(e.isFile()&&ht.has(o))return g.set(t,!0),!0;if(e.isDirectory()&&gt(n))return g.set(t,!0),!0}return g.set(t,!1),!1},wt=(t,{isDynamic:r,isCatchAll:e,isOptionalCatchAll:o})=>{let n=t;return r&&(n=n.replace(/^\[+|\]+$/g,"")),(e||o)&&(n=n.replace(/^\.{3}/,"")),{paramName:n,keyName:`${o?ut:e?ft:r?Et:""}${n}`}},V=(t,r,e="",o=[])=>{if(N.has(r))return N.get(r);let n=e,i=e+O,s=[],p=[],a=[],m=[],c=[...o],x=Tt.readdirSync(r,{withFileTypes:!0}).filter(y=>{if(y.isDirectory()){let P=b.join(r,y.name);return gt(P)}return ht.has(y.name)}).sort();for(let y of x){let P=_(b.join(r,y.name));if(y.isDirectory()){let l=y.name,T=l.startsWith("(")&&l.endsWith(")"),u=l.startsWith("@"),f=l.startsWith("[[...")&&l.endsWith("]]"),h=l.startsWith("[...")&&l.endsWith("]"),d=l.startsWith("[")&&l.endsWith("]"),{paramName:At,keyName:Rt}=wt(l,{isDynamic:d,isCatchAll:h,isOptionalCatchAll:f}),Ot=d||h||f?[...c,{paramName:At,routeType:{isDynamic:d,isCatchAll:h,isOptionalCatchAll:f,isGroup:T,isParallel:u}}]:c,J=T||u,{pathStructure:Z,imports:Lt,paramsTypes:Dt}=V(t,P,J?n:i,Ot);if(p.push(...Lt),m.push(...Dt),J){let tt=Z.match(/^\s*\{([\s\S]*)\}\s*$/);tt&&s.push(`${i}${tt[1].trim()}`)}else s.push(`${i}"${Rt}": ${Z}`)}else{let l=mt(t,P);if(l){let{importStatement:T,importPath:u,type:f}=l;p.push({statement:T,path:u}),a.push(f)}if(k.forEach(T=>{let u=lt(t,P,T);if(u){let{importStatement:f,importPath:h,type:d}=u;p.push({statement:f,path:h}),a.push(d)}}),a.push(j),c.length>0){let T=c.map(({paramName:f,routeType:h})=>{let d=h.isCatchAll?"string[]":h.isOptionalCatchAll?"string[] | undefined":"string";return{name:f,type:d}}),u=L(T);m.push({paramsType:u,dirPath:b.dirname(P)}),a.push(I(Q,u))}}}let A=a.join(" & "),F=s.length>0?`{${E}${s.join(`,${E}`)}${E}${n}}`:"",z={pathStructure:A&&F?`${A} & ${F}`:A||F,imports:p,paramsTypes:m};return N.set(r,z),z};var yt=(t,r)=>{let{pathStructure:e,imports:o,paramsTypes:n}=V(t,r),i=`export type PathStructure = ${e}${S}`,s=o.length?`${o.sort((c,x)=>c.path.localeCompare(x.path,void 0,{numeric:!0})).map(c=>c.statement).join(E)}`:"",p=ot.filter(c=>e.includes(c)),a=D(p.join(" ,"),nt),m=n.map(({paramsType:c,dirPath:x})=>({paramsType:`export type Params = ${c}${S}`,dirPath:x}));return{pathStructure:`${a}${E}${s}${E}${E}${i}`,paramsTypes:m}};import v from"chalk";var q=(t,r,e="\u2192",o=24)=>t.padEnd(o)+` ${e} ${r}`,B=(t=0)=>O.repeat(t),dt=()=>({info:(t,r={})=>{let{indentLevel:e=0,event:o}=r,n=o?`${v.cyan(`[${o}]`)} `:"";console.log(`${B(e)}${n}${t}`)},success:(t,r={})=>{let{indentLevel:e=0}=r;console.log(`${B(e)}${v.green("\u2713")} ${t}`)},error:(t,r={})=>{let{indentLevel:e=0}=r;console.error(`${B(e)}${v.red("\u2717")} ${v.red(t)}`)}});var _t=({baseDir:t,outputPath:r,paramsFileName:e,logger:o})=>{o.info("Generating types...",{event:"generate"});let{pathStructure:n,paramsTypes:i}=yt(r,t);Pt.writeFileSync(r,n),o.success(q("Path structure type",C(r),W,M),{indentLevel:Y}),e&&(i.forEach(({paramsType:s,dirPath:p})=>{let a=Yt.join(p,e);Pt.writeFileSync(a,s)}),o.success(q("Params types",e,W,M),{indentLevel:Y}))};import Mt from"chokidar";var St=(t,r)=>{let e=null,o=!1,n=null,i=async(...s)=>{o=!0;try{await t(...s)}finally{if(o=!1,n){let p=n;n=null,i(...p)}}};return(...s)=>{e&&clearTimeout(e),e=setTimeout(()=>{if(o){n=s;return}i(...s)},r)}};var xt=(t,r,e)=>{e.info(`${C(t)}`,{event:"watch"});let o=a=>R.some(m=>a.endsWith(m)),n=new Set,i=St(()=>{n.forEach(a=>{it(a),at(a)}),n.clear(),r()},300),s=Mt.watch(t,{ignoreInitial:!0,ignored:(a,m)=>!!m?.isFile()&&!o(a)});s.on("ready",()=>{i(),s.on("all",(a,m)=>{if(o(m)){let c=C(m);e.info(c,{event:a}),n.add(m),i()}})}),s.on("error",a=>{a instanceof Error?e.error(`Watcher error: ${a.message}`):e.error(`Unknown watcher error: ${String(a)}`)});let p=()=>{s.close().then(()=>{e.info("Watcher closed.",{event:"watch"})}).catch(a=>{e.error(`Failed to close watcher: ${a.message}`)})};process.on("SIGINT",p),process.on("SIGTERM",p)};var Ct=(t,r,e,o)=>{try{return _t({baseDir:t,outputPath:r,paramsFileName:e,logger:o}),w}catch(n){return n instanceof Error?o.error(`Failed to generate: ${n.message}`):o.error(`Unknown error occurred during generate: ${String(n)}`),$}},Nt=(t,r,e,o)=>{let n=_($t.resolve(t)),i=_($t.resolve(r)),s=typeof e.paramsFile=="string"?e.paramsFile:null;return e.paramsFile!==void 0&&!s?(o.error("Error: --params-file requires a filename."),$):e.watch?(xt(n,()=>{Ct(n,i,s,o)},o),w):Ct(n,i,s,o)};var It=(t,r=dt())=>{let e=new Wt;e.description("Generate RPC client type definitions based on the Next.js path structure.").argument("<baseDir>","Base directory containing Next.js paths for type generation").argument("<outputPath>","Output path for the generated type definitions").option("-w, --watch","Watch mode: regenerate on file changes").option("-p, --params-file [filename]","Generate params types file with specified filename").action(async(o,n,i)=>{try{let s=await Nt(o,n,i,r);i.watch||process.exit(s)}catch(s){r.error(`Unexpected error occurred:${s instanceof Error?s.message:String(s)}`),process.exit($)}}),e.parse(t)};It(process.argv);
2
+ import{Command as Wt}from"commander";import xt from"path";var I=["page.tsx","route.ts"],w=0,$=1,M=1,W=20,Y="\u2192";import U from"path";var tt=(t,r)=>{let e=S(U.relative(U.dirname(t),r)).replace(/\.tsx?$/,"");return e.startsWith("../")||(e="./"+e),e},S=t=>t.replace(/\\/g,"/"),C=t=>U.relative(process.cwd(),t);import dt from"fs";import wt from"path";var et=["Query"],R=" ",h=`
3
+ `,_=";",H=";",j="Endpoint",X="QueryKey",G="ParamsKey",rt=[j,G,X],ot="rpc4next/client";import ht from"fs";import b from"path";import k from"path";var g=new Map,N=new Map,nt=(t,r)=>{let e=k.resolve(r);[...t.keys()].forEach(o=>{let n=k.resolve(o);(n===e||e.startsWith(n+k.sep))&&t.delete(o)})},st=t=>{nt(g,t)},it=t=>{nt(N,t)};import bt from"fs";import Dt from"crypto";var at=(t,r)=>{let e=Dt.createHash("md5").update(`${t}::${r}`).digest("hex").slice(0,16);return`${r}_${e}`};var L=(t,r)=>!t||!r?"":`Record<${t}, ${r}>`,O=t=>t.length===0||t.some(({name:r,type:e})=>!r||!e)?"":`{ ${t.map(({name:r,type:e})=>`"${r}": ${e}`).join(`${H} `)}${t.length>1?H:""} }`,D=(t,r,e)=>!t||!r?"":e?`import type { ${t} as ${e} } from "${r}"${_}`:`import type { ${t} } from "${r}"${_}`;var pt=(t,r,e,o)=>{let n=bt.readFileSync(r,"utf8"),i=e(n);if(!i)return;let s=tt(t,r),p=at(s,i);return{importName:p,importPath:s,importStatement:D(i,s,p),type:o(i,p)}},ct=(t,r)=>pt(t,r,e=>et.find(o=>new RegExp(`export (interface ${o} ?{|type ${o} ?=)`).test(e)),(e,o)=>L(X,o)),mt=(t,r,e)=>pt(t,r,o=>[e].find(n=>new RegExp(`export (async )?(function ${n} ?\\(|const ${n} ?=|\\{[^}]*\\b${n}\\b[^}]*\\} ?=|const \\{[^}]*\\b${n}\\b[^}]*\\} ?=|\\{[^}]*\\b${n}\\b[^}]*\\} from)`).test(o)),(o,n)=>O([{name:`$${o.toLowerCase()}`,type:`typeof ${n}`}]));var vt=["GET","HEAD","OPTIONS","POST","PUT","DELETE","PATCH"],lt="_____",ut="___",ft="_",K=vt.filter(t=>t!=="OPTIONS"),re=K.map(t=>`$${t.toLowerCase()}`);var Tt=new Set(I),Et=t=>{if(g.has(t))return g.get(t);let r=ht.readdirSync(t,{withFileTypes:!0});for(let e of r){let{name:o}=e,n=b.join(t,o);if(o==="node_modules"||o.startsWith("_")||o.startsWith("(.)")||o.startsWith("(..)")||o.startsWith("(...)"))return g.set(t,!1),!1;if(e.isFile()&&Tt.has(o))return g.set(t,!0),!0;if(e.isDirectory()&&Et(n))return g.set(t,!0),!0}return g.set(t,!1),!1},Ft=(t,{isDynamic:r,isCatchAll:e,isOptionalCatchAll:o})=>{let n=t;return r&&(n=n.replace(/^\[+|\]+$/g,"")),(e||o)&&(n=n.replace(/^\.{3}/,"")),{paramName:n,keyName:`${o?lt:e?ut:r?ft:""}${n}`}},Q=(t,r,e="",o=[])=>{if(N.has(r))return N.get(r);let n=e,i=e+R,s=[],p=[],a=[],m=[],c=[...o],x=ht.readdirSync(r,{withFileTypes:!0}).filter(y=>{if(y.isDirectory()){let P=b.join(r,y.name);return Et(P)}return Tt.has(y.name)}).sort();for(let y of x){let P=S(b.join(r,y.name));if(y.isDirectory()){let l=y.name,T=l.startsWith("(")&&l.endsWith(")"),u=l.startsWith("@"),f=l.startsWith("[[...")&&l.endsWith("]]"),E=l.startsWith("[...")&&l.endsWith("]"),d=l.startsWith("[")&&l.endsWith("]"),{paramName:At,keyName:It}=Ft(l,{isDynamic:d,isCatchAll:E,isOptionalCatchAll:f}),Rt=d||E||f?[...c,{paramName:At,routeType:{isDynamic:d,isCatchAll:E,isOptionalCatchAll:f,isGroup:T,isParallel:u}}]:c,z=T||u,{pathStructure:J,imports:Lt,paramsTypes:Ot}=Q(t,P,z?n:i,Rt);if(p.push(...Lt),m.push(...Ot),z){let Z=J.match(/^\s*\{([\s\S]*)\}\s*$/);Z&&s.push(`${i}${Z[1].trim()}`)}else s.push(`${i}"${It}": ${J}`)}else{let l=ct(t,P);if(l){let{importStatement:T,importPath:u,type:f}=l;p.push({statement:T,path:u}),a.push(f)}if(K.forEach(T=>{let u=mt(t,P,T);if(u){let{importStatement:f,importPath:E,type:d}=u;p.push({statement:f,path:E}),a.push(d)}}),a.push(j),c.length>0){let T=c.map(({paramName:f,routeType:E})=>{let d=E.isCatchAll?"string[]":E.isOptionalCatchAll?"string[] | undefined":"string";return{name:f,type:d}}),u=O(T);m.push({paramsType:u,dirPath:b.dirname(P)}),a.push(L(G,u))}}}let A=a.join(" & "),F=s.length>0?`{${h}${s.join(`,${h}`)}${h}${n}}`:"",q={pathStructure:A&&F?`${A} & ${F}`:A||F,imports:p,paramsTypes:m};return N.set(r,q),q};var gt=(t,r)=>{let{pathStructure:e,imports:o,paramsTypes:n}=Q(t,r),i=`export type PathStructure = ${e}${_}`,s=o.length?`${o.sort((c,x)=>c.path.localeCompare(x.path,void 0,{numeric:!0})).map(c=>c.statement).join(h)}`:"",p=rt.filter(c=>e.includes(c)),a=D(p.join(" ,"),ot),m=n.map(({paramsType:c,dirPath:x})=>({paramsType:`export type Params = ${c}${_}`,dirPath:x}));return{pathStructure:`${a}${h}${s}${h}${h}${i}`,paramsTypes:m}};import v from"chalk";var B=(t,r,e="\u2192",o=24)=>t.padEnd(o)+` ${e} ${r}`,V=(t=0)=>R.repeat(t),yt=()=>({info:(t,r={})=>{let{indentLevel:e=0,event:o}=r,n=o?`${v.cyan(`[${o}]`)} `:"";console.log(`${V(e)}${n}${t}`)},success:(t,r={})=>{let{indentLevel:e=0}=r;console.log(`${V(e)}${v.green("\u2713")} ${t}`)},error:(t,r={})=>{let{indentLevel:e=0}=r;console.error(`${V(e)}${v.red("\u2717")} ${v.red(t)}`)}});var Pt=({baseDir:t,outputPath:r,paramsFileName:e,logger:o})=>{o.info("Generating types...",{event:"generate"});let{pathStructure:n,paramsTypes:i}=gt(r,t);dt.writeFileSync(r,n),o.success(B("Path structure type",C(r),Y,W),{indentLevel:M}),e&&(i.forEach(({paramsType:s,dirPath:p})=>{let a=wt.join(p,e);dt.writeFileSync(a,s)}),o.success(B("Params types",e,Y,W),{indentLevel:M}))};import Mt from"chokidar";var St=(t,r)=>{let e=null,o=!1,n=null,i=async(...s)=>{o=!0;try{await t(...s)}finally{if(o=!1,n){let p=n;n=null,i(...p)}}};return(...s)=>{e&&clearTimeout(e),e=setTimeout(()=>{if(o){n=s;return}i(...s)},r)}};var _t=(t,r,e)=>{e.info(`${C(t)}`,{event:"watch"});let o=a=>I.some(m=>a.endsWith(m)),n=new Set,i=St(()=>{n.forEach(a=>{st(a),it(a)}),n.clear(),r()},300),s=Mt.watch(t,{ignoreInitial:!0,ignored:(a,m)=>!!m?.isFile()&&!o(a)});s.on("ready",()=>{i(),s.on("all",(a,m)=>{if(o(m)){let c=C(m);e.info(c,{event:a}),n.add(m),i()}})}),s.on("error",a=>{a instanceof Error?e.error(`Watcher error: ${a.message}`):e.error(`Unknown watcher error: ${String(a)}`)});let p=()=>{s.close().then(()=>{e.info("Watcher closed.",{event:"watch"})}).catch(a=>{e.error(`Failed to close watcher: ${a.message}`)})};process.on("SIGINT",p),process.on("SIGTERM",p)};var $t=(t,r,e,o)=>{try{return Pt({baseDir:t,outputPath:r,paramsFileName:e,logger:o}),w}catch(n){return n instanceof Error?o.error(`Failed to generate: ${n.message}`):o.error(`Unknown error occurred during generate: ${String(n)}`),$}},Ct=(t,r,e,o)=>{let n=S(xt.resolve(t)),i=S(xt.resolve(r)),s=typeof e.paramsFile=="string"?e.paramsFile:null;return e.paramsFile!==void 0&&!s?(o.error("Error: --params-file requires a filename."),$):e.watch?(_t(n,()=>{$t(n,i,s,o)},o),w):$t(n,i,s,o)};var Nt=(t,r=yt())=>{let e=new Wt;e.description("Generate RPC client type definitions based on the Next.js path structure.").argument("<baseDir>","Base directory containing Next.js paths for type generation").argument("<outputPath>","Output path for the generated type definitions").option("-w, --watch","Watch mode: regenerate on file changes").option("-p, --params-file [filename]","Generate params types file with specified filename").action(async(o,n,i)=>{try{let s=await Ct(o,n,i,r);i.watch||process.exit(s)}catch(s){r.error(`Unexpected error occurred:${s instanceof Error?s.message:String(s)}`),process.exit($)}}),e.parse(t)};Nt(process.argv);
4
4
  /*!
5
5
  * Inspired by pathpida (https://github.com/aspida/pathpida),
6
6
  * especially the design and UX of its CLI.
@@ -1 +1 @@
1
- import{deepMerge as q}from"./client-utils";import{createUrl as T}from"./url";const l=t=>{const e={};return t?t instanceof Headers?(t.forEach((n,r)=>{e[r.toLowerCase()]=n}),e):Array.isArray(t)?(t.forEach(([n,r])=>{e[n.toLowerCase()]=r}),e):(Object.entries(t).forEach(([n,r])=>{e[n.toLowerCase()]=r}),e):e},F=(t,e,n,r,c)=>async(s,p)=>{let d,a;s?.body?.json&&(a="application/json",d=JSON.stringify(s.body.json));const g=s?.requestHeaders?.headers,f=s?.requestHeaders?.cookies,m=T([...e],n,r)(s?.url),h=t.replace(/^\$/,"").toUpperCase(),H=p?.fetch??c.fetch??fetch,u=c.init??{},y=p?.init??{},O=l(u.headers),C=l(g??y.headers),o={...O,...C};a&&(o["content-type"]=a),f&&(o.cookie=Object.entries(f).map(([j,R])=>`${j}=${R}`).join("; "));const{headers:k,...b}=u,{headers:w,...I}=y,i=q(b,I);return i.method=h,Object.keys(o).length>0&&(i.headers=o),d&&(i.body=d),await H(m.path,i)};export{F as httpMethod};
1
+ import{deepMerge as R}from"./client-utils";import{createUrl as T}from"./url";import{normalizeHeaders as p}from"../lib/headers";const W=(f,u,h,y,d)=>async(e,a)=>{let s,r;e?.body?.json&&(r="application/json",s=JSON.stringify(e.body.json));const m=e?.requestHeaders?.headers,c=e?.requestHeaders?.cookies,l=T([...u],h,y)(e?.url),H=f.replace(/^\$/,"").toUpperCase(),g=a?.fetch??d.fetch??fetch,i=d.init??{},o=a?.init??{},I=p(i.headers??i.headersInit),O=p(m??o.headers??o.headersInit),t={...I,...O};r&&(t["content-type"]=r),c&&(t.cookie=Object.entries(c).map(([j,q])=>`${j}=${q}`).join("; "));const{headers:k,headersInit:B,...b}=i,{headers:U,headersInit:_,...C}=o,n=R(b,C);return n.method=H,Object.keys(t).length>0&&(n.headers=t),s&&(n.body=s),await g(l.path,n)};export{W as httpMethod};
@@ -1,3 +1,3 @@
1
1
  export { createRpcClient } from "./rpc-client";
2
2
  export { createRpcHelper } from "./rpc-helper";
3
- export type { Endpoint, ParamsKey, QueryKey, OptionalQueryKey } from "./types";
3
+ export type { Endpoint, ParamsKey, QueryKey } from "./types";
@@ -1 +1,5 @@
1
- export declare const matchPath: (paths: string[], dynamicKeys: string[]) => (path: string) => Record<string, string | string[] | undefined> | null;
1
+ export declare const matchPath: (paths: string[], dynamicKeys: string[]) => (input: string) => {
2
+ params: Record<string, string | string[] | undefined>;
3
+ query: Record<string, string | string[] | undefined>;
4
+ hash: string | undefined;
5
+ } | null;
@@ -1 +1 @@
1
- import{isCatchAllOrOptional as d}from"./client-utils";import{replaceDynamicSegments as u}from"./url";const f=(r,o)=>a=>{const c=`/${r.slice(1).join("/")}`,i=u(c,{optionalCatchAll:"(?:/(.*))?",catchAll:"/([^/]+(?:/[^/]+)*)",dynamic:"/([^/]+)"}),n=new RegExp(`^${i}/?$`).exec(a);return n?o.reduce((l,t,s)=>{const m=t.replace(/^_+/,""),e=n[s+1],p=d(t)?e===void 0||e===""?void 0:e.split("/").filter(Boolean).map(decodeURIComponent):decodeURIComponent(e);return{...l,[m]:p}},{}):null};export{f as matchPath};
1
+ import{isCatchAllOrOptional as g}from"./client-utils";import{replaceDynamicSegments as R}from"./url";import{searchParamsToObject as C}from"../lib/search-params";const U=(r,o)=>c=>{const e=new URL(c,"http://dummy"),s=e.pathname,m=`/${r.slice(1).join("/")}`,i=R(m,{optionalCatchAll:"(?:/(.*))?",catchAll:"/([^/]+(?:/[^/]+)*)",dynamic:"/([^/]+)"}),t=new RegExp(`^${i}/?$`).exec(s);if(!t)return null;const l=o.reduce((h,a,d)=>{const u=a.replace(/^_+/,""),n=t[d+1],f=g(a)?n===void 0||n===""?void 0:n.split("/").filter(Boolean).map(decodeURIComponent):decodeURIComponent(n);return{...h,[u]:f}},{}),p=C(e.searchParams);return{params:l,query:p,hash:e.hash?decodeURIComponent(e.hash.slice(1)):void 0}};export{U as matchPath};
@@ -5,15 +5,20 @@ import type { HttpStatusCode } from "../lib/http-status-code-types";
5
5
  import type { RouteHandlerResponse, RouteResponse, ValidationSchema } from "../server/route-types";
6
6
  import type { TypedNextResponse, ValidationInputFor } from "../server/types";
7
7
  import type { NextResponse } from "next/server";
8
+ type DistributeOmit<T, K extends keyof any> = T extends any ? Omit<T, K> : never;
8
9
  /**
9
10
  * Extension of the standard `RequestInit` interface with strongly typed headers.
10
11
  */
11
- export interface TypedRequestInit<TWithoutHeaders extends "Content-Type" | "Cookie" = never> extends RequestInit {
12
- headers?: (Omit<HttpRequestHeaders, TWithoutHeaders> & Record<string, string>) | HeadersInit;
13
- }
14
- export type ClientOptions<TWithoutHeaders extends "Content-Type" | "Cookie" = never, TWithoutInit extends "body" | "headers" = never> = {
12
+ export type TypedRequestInit<TWithoutHeaders extends keyof HttpRequestHeaders = never> = Omit<RequestInit, "headers"> & ({
13
+ headers?: Omit<HttpRequestHeaders, TWithoutHeaders> & Record<string, string>;
14
+ headersInit?: never;
15
+ } | {
16
+ headers?: never;
17
+ headersInit?: HeadersInit;
18
+ });
19
+ export type ClientOptions<TWithoutHeaders extends "Content-Type" | "Cookie" = never, TWithoutInit extends "body" | "headers" | "headersInit" = never> = {
15
20
  fetch?: typeof fetch;
16
- init?: Omit<TypedRequestInit<TWithoutHeaders>, TWithoutInit>;
21
+ init?: DistributeOmit<TypedRequestInit<TWithoutHeaders>, TWithoutInit>;
17
22
  };
18
23
  declare const __proxy: unique symbol;
19
24
  export type Endpoint = {
@@ -23,8 +28,6 @@ export type ParamsKey = "__params";
23
28
  type IsParams = Record<ParamsKey, unknown>;
24
29
  export type QueryKey = "__query";
25
30
  type IsQuery = Record<QueryKey, unknown>;
26
- export type OptionalQueryKey = "__op_query";
27
- type IsOptionalQuery = Record<OptionalQueryKey, unknown>;
28
31
  export type HttpMethodFuncKey = (typeof HTTP_METHOD_FUNC_KEYS)[number];
29
32
  type IsHttpMethod = {
30
33
  [K in HttpMethodFuncKey]?: unknown;
@@ -33,16 +36,20 @@ type IsOptionalCatchAll = `${typeof OPTIONAL_CATCH_ALL_PREFIX}${string}`;
33
36
  type IsCatchAll = `${typeof CATCH_ALL_PREFIX}${string}`;
34
37
  type IsDynamic = `${typeof DYNAMIC_PREFIX}${string}`;
35
38
  export type FuncParams<T = Record<string, string | number | string[] | undefined>> = T;
36
- type QueryParams<T = Record<string, string | number>> = T;
37
39
  type Params<T = unknown> = T extends IsParams ? T[ParamsKey] : Record<string, string>;
38
- export type UrlOptions<T = unknown> = T extends IsQuery ? {
40
+ export type UrlOptions<T = unknown, TQuery = unknown> = T extends IsQuery ? AllOptional<T[QueryKey]> extends true ? {
41
+ query?: T[QueryKey];
42
+ hash?: string;
43
+ } : {
39
44
  query: T[QueryKey];
40
45
  hash?: string;
41
- } : T extends IsOptionalQuery ? {
42
- query?: T[OptionalQueryKey];
46
+ } : IsNever<TQuery> extends true ? {
47
+ hash?: string;
48
+ } : AllOptional<TQuery> extends true ? {
49
+ query?: TQuery;
43
50
  hash?: string;
44
51
  } : {
45
- query?: QueryParams;
52
+ query: TQuery;
46
53
  hash?: string;
47
54
  };
48
55
  export type UrlResult<T = unknown> = {
@@ -53,11 +60,11 @@ export type UrlResult<T = unknown> = {
53
60
  };
54
61
  type IsNever<T> = [T] extends [never] ? true : false;
55
62
  type AllOptional<T> = Partial<T> extends T ? true : false;
56
- type UrlArgs<T> = T extends IsQuery ? [url: UrlOptions<T>] : [url?: UrlOptions<T>];
57
- type UrlArgsObj<T> = T extends IsQuery ? {
58
- url: UrlOptions<T>;
63
+ type UrlArgs<T, TQuery, TUrlOptions = UrlOptions<T, TQuery>> = AllOptional<TUrlOptions> extends true ? [url?: TUrlOptions] : [url: TUrlOptions];
64
+ type UrlArgsObj<T, TQuery, TUrlOptions = UrlOptions<T, TQuery>> = AllOptional<TUrlOptions> extends true ? {
65
+ url?: TUrlOptions;
59
66
  } : {
60
- url?: UrlOptions<T>;
67
+ url: TUrlOptions;
61
68
  };
62
69
  export type BodyOptions<TJson = unknown> = {
63
70
  json: TJson;
@@ -76,30 +83,36 @@ type HeadersArgsObj<THeaders = unknown, TCookies = unknown> = IsNever<THeaders>
76
83
  } : {
77
84
  requestHeaders: HeadersOptions<THeaders, TCookies>;
78
85
  };
79
- type HttpMethodsArgs<T, TValidationSchema extends ValidationSchema, TJson = ValidationInputFor<"json", TValidationSchema>, THeaders = ValidationInputFor<"headers", TValidationSchema>, TCookies = ValidationInputFor<"cookies", TValidationSchema>, TBaseArgs = UrlArgsObj<T> & BodyArgsObj<TJson> & HeadersArgsObj<THeaders, TCookies>> = [
86
+ type HttpMethodsArgs<T, TValidationSchema extends ValidationSchema, TQuery = ValidationInputFor<"query", TValidationSchema>, TJson = ValidationInputFor<"json", TValidationSchema>, THeaders = ValidationInputFor<"headers", TValidationSchema>, TCookies = ValidationInputFor<"cookies", TValidationSchema>, TBaseArgs = UrlArgsObj<T, TQuery> & BodyArgsObj<TJson> & HeadersArgsObj<THeaders, TCookies>> = [
80
87
  ...(AllOptional<TBaseArgs> extends true ? [methodParam?: TBaseArgs] : [methodParam: TBaseArgs]),
81
- option?: ClientOptions<(IsNever<TJson> extends true ? never : "Content-Type") | (IsNever<TCookies> extends true ? never : "Cookie"), (IsNever<TJson> extends true ? never : "body") | (IsNever<THeaders> extends true ? never : "headers")>
88
+ option?: ClientOptions<(IsNever<TJson> extends true ? never : "Content-Type") | (IsNever<TCookies> extends true ? never : "Cookie"), (IsNever<TJson> extends true ? never : "body") | (IsNever<THeaders> extends true ? never : "headers" | "headersInit")>
82
89
  ];
83
90
  type InferHttpMethods<T extends IsHttpMethod> = {
84
91
  [K in keyof T as K extends HttpMethodFuncKey ? K : never]: (...args: HttpMethodsArgs<T, InferValidationSchema<T[K]>>) => Promise<InferTypedNextResponseType<T[K]>>;
85
92
  };
93
+ type InferHttpMethodValidationSchema<T> = {
94
+ [K in keyof T]: K extends HttpMethodFuncKey ? InferValidationSchema<T[K]> : never;
95
+ }[keyof T & HttpMethodFuncKey];
86
96
  type InferValidationSchema<T> = T extends (...args: any[]) => RouteHandlerResponse<RouteResponse, infer TValidationSchema> ? TValidationSchema : ValidationSchema;
87
97
  type InferNextResponseType<T> = T extends (...args: any[]) => Promise<NextResponse<infer U>> ? U : never;
88
98
  type InferTypedNextResponseType<T> = T extends (...args: any[]) => Promise<TypedNextResponse> ? Awaited<ReturnType<T>> : TypedNextResponse<InferNextResponseType<T>, HttpStatusCode, ContentType>;
89
99
  type PathProxyAsProperty<T> = {
90
- $match: (path: string) => Params<T> | null;
100
+ $match: (path: string) => ({
101
+ params: Params<T>;
102
+ } & Partial<UrlOptions<T, InferQuery<T>>>) | null;
91
103
  };
104
+ type InferQuery<T> = ValidationInputFor<"query", InferHttpMethodValidationSchema<T>>;
92
105
  type PathProxyAsFunction<T> = {
93
- $url: (...args: UrlArgs<T>) => UrlResult<T>;
106
+ $url: (...args: UrlArgs<T, InferQuery<T>>) => UrlResult<T>;
94
107
  } & (T extends IsHttpMethod ? InferHttpMethods<T> : unknown);
95
- type ParamFunction<T, TParamArgs extends unknown[]> = (...args: [...TParamArgs]) => DynamicPathProxyAsFunction<T>;
108
+ type ParamFunction<T, TParamArgs extends unknown[]> = (...args: TParamArgs) => DynamicPathProxyAsFunction<T>;
96
109
  type NonEmptyArray<T> = [T, ...T[]];
97
110
  export type DynamicPathProxyAsFunction<T> = Omit<(T extends Endpoint ? PathProxyAsFunction<T> : unknown) & {
98
111
  [K in keyof T]: K extends IsOptionalCatchAll ? ParamFunction<T[K], [value?: string[]]> : K extends IsCatchAll ? ParamFunction<T[K], [value: NonEmptyArray<string>]> : K extends IsDynamic ? ParamFunction<T[K], [value: string | number]> : DynamicPathProxyAsFunction<T[K]>;
99
- }, QueryKey | OptionalQueryKey | ParamsKey>;
112
+ }, QueryKey | ParamsKey>;
100
113
  export type DynamicPathProxyAsProperty<T> = Omit<(T extends Endpoint ? PathProxyAsProperty<T> : unknown) & {
101
114
  [K in keyof T]: K extends unknown ? DynamicPathProxyAsProperty<T[K]> : DynamicPathProxyAsProperty<T[K]>;
102
- }, QueryKey | OptionalQueryKey | ParamsKey>;
115
+ }, QueryKey | ParamsKey>;
103
116
  export type RpcHandler = (key: string, context: {
104
117
  paths: string[];
105
118
  params: FuncParams;
@@ -1,4 +1,4 @@
1
- type KnownContentType = "application/json" | "text/html" | "text/plain" | "application/javascript" | "text/css" | "image/png" | "image/jpeg" | "image/svg+xml" | "application/pdf" | "application/octet-stream" | "multipart/form-data" | "application/x-www-form-urlencoded";
1
+ type KnownContentType = "application/1d-interleaved-parityfec" | "application/3gpdash-qoe-report+xml" | "application/3gpp-ims+xml" | "application/3gppHal+json" | "application/3gppHalForms+json" | "application/A2L" | "application/AML" | "application/ATF" | "application/ATFX" | "application/ATXML" | "application/CALS-1840" | "application/CDFX+XML" | "application/CEA" | "application/CSTAdata+xml" | "application/DCD" | "application/DII" | "application/DIT" | "application/EDI-X12" | "application/EDI-consent" | "application/EDIFACT" | "application/EmergencyCallData.Comment+xml" | "application/EmergencyCallData.Control+xml" | "application/EmergencyCallData.DeviceInfo+xml" | "application/EmergencyCallData.LegacyESN+json" | "application/EmergencyCallData.ProviderInfo+xml" | "application/EmergencyCallData.ServiceInfo+xml" | "application/EmergencyCallData.SubscriberInfo+xml" | "application/EmergencyCallData.VEDS+xml" | "application/EmergencyCallData.cap+xml" | "application/EmergencyCallData.eCall.MSD" | "application/H224" | "application/IOTP" | "application/ISUP" | "application/LXF" | "application/MF4" | "application/ODA" | "application/ODX" | "application/PDX" | "application/QSIG" | "application/SGML" | "application/ST2110-41" | "application/TETRA_ISI" | "application/ace+cbor" | "application/ace+json" | "application/ace-groupcomm+cbor" | "application/ace-trl+cbor" | "application/activemessage" | "application/activity+json" | "application/aif+cbor" | "application/aif+json" | "application/alto-cdni+json" | "application/alto-cdnifilter+json" | "application/alto-costmap+json" | "application/alto-costmapfilter+json" | "application/alto-directory+json" | "application/alto-endpointcost+json" | "application/alto-endpointcostparams+json" | "application/alto-endpointprop+json" | "application/alto-endpointpropparams+json" | "application/alto-error+json" | "application/alto-networkmap+json" | "application/alto-networkmapfilter+json" | "application/alto-propmap+json" | "application/alto-propmapparams+json" | "application/alto-tips+json" | "application/alto-tipsparams+json" | "application/alto-updatestreamcontrol+json" | "application/alto-updatestreamparams+json" | "application/andrew-inset" | "application/applefile" | "application/application/jwk-set+jwt" | "application/application/resolve-response+jwt" | "application/application/trust-chain+json" | "application/application/trust-mark+jwt" | "application/application/trust-mark-delegation+jwt" | "application/at+jwt" | "application/atom+xml" | "application/atomcat+xml" | "application/atomdeleted+xml" | "application/atomicmail" | "application/atomsvc+xml" | "application/atsc-dwd+xml" | "application/atsc-dynamic-event-message" | "application/atsc-held+xml" | "application/atsc-rdt+json" | "application/atsc-rsat+xml" | "application/auth-policy+xml" | "application/automationml-aml+xml" | "application/automationml-amlx+zip" | "application/bacnet-xdd+zip" | "application/batch-SMTP" | "application/beep+xml" | "application/bufr" | "application/c2pa" | "application/calendar+json" | "application/calendar+xml" | "application/call-completion" | "application/captive+json" | "application/cbor" | "application/cbor-seq" | "application/cccex" | "application/ccmp+xml" | "application/ccxml+xml" | "application/cda+xml" | "application/cdmi-capability" | "application/cdmi-container" | "application/cdmi-domain" | "application/cdmi-object" | "application/cdmi-queue" | "application/cdni" | "application/ce+cbor" | "application/cea-2018+xml" | "application/cellml+xml" | "application/cfw" | "application/cid" | "application/cid-edhoc+cbor-seq" | "application/city+json" | "application/city+json-seq" | "application/clr" | "application/clue+xml" | "application/clue_info+xml" | "application/cms" | "application/cnrp+xml" | "application/coap-eap" | "application/coap-group+json" | "application/coap-payload" | "application/commonground" | "application/concise-problem-details+cbor" | "application/conference-info+xml" | "application/cose" | "application/cose-key" | "application/cose-key-set" | "application/cose-x509" | "application/cpl+xml" | "application/csrattrs" | "application/csta+xml" | "application/csvm+json" | "application/cwl" | "application/cwl+json" | "application/cwl+yaml" | "application/cwt" | "application/cybercash" | "application/dash+xml" | "application/dash-patch+xml" | "application/dashdelta" | "application/davmount+xml" | "application/dca-rft" | "application/dec-dx" | "application/dialog-info+xml" | "application/dicom" | "application/dicom+json" | "application/dicom+xml" | "application/did" | "application/dns" | "application/dns+json" | "application/dns-message" | "application/dots+cbor" | "application/dpop+jwt" | "application/dskpp+xml" | "application/dssc+der" | "application/dssc+xml" | "application/dvcs" | "application/eat+cwt" | "application/eat+jwt" | "application/eat-bun+cbor" | "application/eat-bun+json" | "application/eat-ucs+cbor" | "application/eat-ucs+json" | "application/ecmascript (OBSOLETED in favor of text/javascript)" | "application/edhoc+cbor-seq" | "application/efi" | "application/elm+json" | "application/elm+xml" | "application/emma+xml" | "application/emotionml+xml" | "application/encaprtp" | "application/entity-statement+jwt" | "application/epp+xml" | "application/epub+zip" | "application/eshop" | "application/example" | "application/exi" | "application/expect-ct-report+json" | "application/express" | "application/fastinfoset" | "application/fastsoap" | "application/fdf" | "application/fdt+xml" | "application/fhir+json" | "application/fhir+xml" | "application/fits" | "application/flexfec" | "application/font-sfnt - DEPRECATED in favor of font/sfnt" | "application/font-tdpfr" | "application/font-woff - DEPRECATED in favor of font/woff" | "application/framework-attributes+xml" | "application/geo+json" | "application/geo+json-seq" | "application/geopackage+sqlite3" | "application/geopose+json" | "application/geoxacml+json" | "application/geoxacml+xml" | "application/gltf-buffer" | "application/gml+xml" | "application/gnap-binding-jws" | "application/gnap-binding-jwsd" | "application/gnap-binding-rotation-jws" | "application/gnap-binding-rotation-jwsd" | "application/grib" | "application/gzip" | "application/held+xml" | "application/hl7v2+xml" | "application/http" | "application/hyperstudio" | "application/ibe-key-request+xml" | "application/ibe-pkg-reply+xml" | "application/ibe-pp-data" | "application/iges" | "application/im-iscomposing+xml" | "application/index" | "application/index.cmd" | "application/index.obj" | "application/index.response" | "application/index.vnd" | "application/inkml+xml" | "application/ipfix" | "application/ipp" | "application/its+xml" | "application/java-archive" | "application/javascript (OBSOLETED in favor of text/javascript)" | "application/jf2feed+json" | "application/jose" | "application/jose+json" | "application/jrd+json" | "application/jscalendar+json" | "application/jscontact+json" | "application/json" | "application/json-patch+json" | "application/json-seq" | "application/jsonpath" | "application/jwk+json" | "application/jwk-set+json" | "application/jwt" | "application/kpml-request+xml" | "application/kpml-response+xml" | "application/ld+json" | "application/lgr+xml" | "application/link-format" | "application/linkset" | "application/linkset+json" | "application/load-control+xml" | "application/logout+jwt" | "application/lost+xml" | "application/lostsync+xml" | "application/lpf+zip" | "application/mac-binhex40" | "application/macwriteii" | "application/mads+xml" | "application/manifest+json" | "application/marc" | "application/marcxml+xml" | "application/mathematica" | "application/mathml+xml" | "application/mathml-content+xml" | "application/mathml-presentation+xml" | "application/mbms-associated-procedure-description+xml" | "application/mbms-deregister+xml" | "application/mbms-envelope+xml" | "application/mbms-msk+xml" | "application/mbms-msk-response+xml" | "application/mbms-protection-description+xml" | "application/mbms-reception-report+xml" | "application/mbms-register+xml" | "application/mbms-register-response+xml" | "application/mbms-schedule+xml" | "application/mbms-user-service-description+xml" | "application/mbox" | "application/media-policy-dataset+xml" | "application/media_control+xml" | "application/mediaservercontrol+xml" | "application/merge-patch+json" | "application/metalink4+xml" | "application/mets+xml" | "application/mikey" | "application/mipc" | "application/missing-blocks+cbor-seq" | "application/mmt-aei+xml" | "application/mmt-usd+xml" | "application/mods+xml" | "application/moss-keys" | "application/moss-signature" | "application/mosskey-data" | "application/mosskey-request" | "application/mp21" | "application/mp4" | "application/mpeg4-generic" | "application/mpeg4-iod" | "application/mpeg4-iod-xmt" | "application/mrb-consumer+xml" | "application/mrb-publish+xml" | "application/msc-ivr+xml" | "application/msc-mixer+xml" | "application/msword" | "application/mud+json" | "application/multipart-core" | "application/mxf" | "application/n-quads" | "application/n-triples" | "application/nasdata" | "application/news-checkgroups" | "application/news-groupinfo" | "application/news-transmission" | "application/nlsml+xml" | "application/node" | "application/nss" | "application/oauth-authz-req+jwt" | "application/oblivious-dns-message" | "application/ocsp-request" | "application/ocsp-response" | "application/octet-stream" | "application/odm+xml" | "application/oebps-package+xml" | "application/ogg" | "application/ohttp-keys" | "application/opc-nodeset+xml" | "application/oscore" | "application/oxps" | "application/p21" | "application/p21+zip" | "application/p2p-overlay+xml" | "application/parityfec" | "application/passport" | "application/patch-ops-error+xml" | "application/pdf" | "application/pem-certificate-chain" | "application/pgp-encrypted" | "application/pgp-keys" | "application/pgp-signature" | "application/pidf+xml" | "application/pidf-diff+xml" | "application/pkcs10" | "application/pkcs12" | "application/pkcs7-mime" | "application/pkcs7-signature" | "application/pkcs8" | "application/pkcs8-encrypted" | "application/pkix-attr-cert" | "application/pkix-cert" | "application/pkix-crl" | "application/pkix-pkipath" | "application/pkixcmp" | "application/pls+xml" | "application/poc-settings+xml" | "application/postscript" | "application/ppsp-tracker+json" | "application/private-token-issuer-directory" | "application/private-token-request" | "application/private-token-response" | "application/problem+json" | "application/problem+xml" | "application/provenance+xml" | "application/provided-claims+jwt" | "application/prs.alvestrand.titrax-sheet" | "application/prs.cww" | "application/prs.cyn" | "application/prs.hpub+zip" | "application/prs.implied-document+xml" | "application/prs.implied-executable" | "application/prs.implied-object+json" | "application/prs.implied-object+json-seq" | "application/prs.implied-object+yaml" | "application/prs.implied-structure" | "application/prs.mayfile" | "application/prs.nprend" | "application/prs.plucker" | "application/prs.rdf-xml-crypt" | "application/prs.vcfbzip2" | "application/prs.xsf+xml" | "application/pskc+xml" | "application/pvd+json" | "application/raptorfec" | "application/rdap+json" | "application/rdf+xml" | "application/reginfo+xml" | "application/relax-ng-compact-syntax" | "application/remote-printing (OBSOLETE)" | "application/reputon+json" | "application/resource-lists+xml" | "application/resource-lists-diff+xml" | "application/rfc+xml" | "application/riscos" | "application/rlmi+xml" | "application/rls-services+xml" | "application/route-apd+xml" | "application/route-s-tsid+xml" | "application/route-usd+xml" | "application/rpki-checklist" | "application/rpki-ghostbusters" | "application/rpki-manifest" | "application/rpki-publication" | "application/rpki-roa" | "application/rpki-signed-tal" | "application/rpki-updown" | "application/rtf" | "application/rtploopback" | "application/rtx" | "application/samlassertion+xml" | "application/samlmetadata+xml" | "application/sarif+json" | "application/sarif-external-properties+json" | "application/sbe" | "application/sbml+xml" | "application/scaip+xml" | "application/scim+json" | "application/scvp-cv-request" | "application/scvp-cv-response" | "application/scvp-vp-request" | "application/scvp-vp-response" | "application/sdf+json" | "application/sdp" | "application/secevent+jwt" | "application/senml+cbor" | "application/senml+json" | "application/senml+xml" | "application/senml-etch+cbor" | "application/senml-etch+json" | "application/senml-exi" | "application/sensml+cbor" | "application/sensml+json" | "application/sensml+xml" | "application/sensml-exi" | "application/sep+xml" | "application/sep-exi" | "application/session-info" | "application/set-payment" | "application/set-payment-initiation" | "application/set-registration" | "application/set-registration-initiation" | "application/sgml-open-catalog" | "application/shf+xml" | "application/sieve" | "application/simple-filter+xml" | "application/simple-message-summary" | "application/simpleSymbolContainer" | "application/sipc" | "application/slate" | "application/smil (OBSOLETED in favor of application/smil+xml)" | "application/smil+xml" | "application/smpte336m" | "application/soap+fastinfoset" | "application/soap+xml" | "application/sparql-query" | "application/sparql-results+xml" | "application/spdx+json" | "application/spirits-event+xml" | "application/sql" | "application/srgs" | "application/srgs+xml" | "application/sru+xml" | "application/sslkeylogfile" | "application/ssml+xml" | "application/stix+json" | "application/stratum" | "application/swid+cbor" | "application/swid+xml" | "application/tamp-apex-update" | "application/tamp-apex-update-confirm" | "application/tamp-community-update" | "application/tamp-community-update-confirm" | "application/tamp-error" | "application/tamp-sequence-adjust" | "application/tamp-sequence-adjust-confirm" | "application/tamp-status-query" | "application/tamp-status-response" | "application/tamp-update" | "application/tamp-update-confirm" | "application/taxii+json" | "application/td+json" | "application/tei+xml" | "application/texinfo" | "application/thraud+xml" | "application/timestamp-query" | "application/timestamp-reply" | "application/timestamped-data" | "application/tlsrpt+gzip" | "application/tlsrpt+json" | "application/tm+json" | "application/tnauthlist" | "application/toc+cbor" | "application/token-introspection+jwt" | "application/toml" | "application/trickle-ice-sdpfrag" | "application/trig" | "application/ttml+xml" | "application/tve-trigger" | "application/tzif" | "application/tzif-leap" | "application/uccs+cbor" | "application/ujcs+json" | "application/ulpfec" | "application/urc-grpsheet+xml" | "application/urc-ressheet+xml" | "application/urc-targetdesc+xml" | "application/urc-uisocketdesc+xml" | "application/vc" | "application/vc+cose" | "application/vc+jwt" | "application/vcard+json" | "application/vcard+xml" | "application/vemmi" | "application/vnd.1000minds.decision-model+xml" | "application/vnd.1ob" | "application/vnd.3M.Post-it-Notes" | "application/vnd.3gpp-prose+xml" | "application/vnd.3gpp-prose-pc3a+xml" | "application/vnd.3gpp-prose-pc3ach+xml" | "application/vnd.3gpp-prose-pc3ch+xml" | "application/vnd.3gpp-prose-pc8+xml" | "application/vnd.3gpp-v2x-local-service-information" | "application/vnd.3gpp.5gnas" | "application/vnd.3gpp.5gsa2x" | "application/vnd.3gpp.5gsa2x-local-service-information" | "application/vnd.3gpp.5gsv2x" | "application/vnd.3gpp.5gsv2x-local-service-information" | "application/vnd.3gpp.GMOP+xml" | "application/vnd.3gpp.SRVCC-info+xml" | "application/vnd.3gpp.access-transfer-events+xml" | "application/vnd.3gpp.bsf+xml" | "application/vnd.3gpp.crs+xml" | "application/vnd.3gpp.current-location-discovery+xml" | "application/vnd.3gpp.gtpc" | "application/vnd.3gpp.interworking-data" | "application/vnd.3gpp.lpp" | "application/vnd.3gpp.mc-signalling-ear" | "application/vnd.3gpp.mcdata-affiliation-command+xml" | "application/vnd.3gpp.mcdata-info+xml" | "application/vnd.3gpp.mcdata-msgstore-ctrl-request+xml" | "application/vnd.3gpp.mcdata-payload" | "application/vnd.3gpp.mcdata-regroup+xml" | "application/vnd.3gpp.mcdata-service-config+xml" | "application/vnd.3gpp.mcdata-signalling" | "application/vnd.3gpp.mcdata-ue-config+xml" | "application/vnd.3gpp.mcdata-user-profile+xml" | "application/vnd.3gpp.mcptt-affiliation-command+xml" | "application/vnd.3gpp.mcptt-floor-request+xml" | "application/vnd.3gpp.mcptt-info+xml" | "application/vnd.3gpp.mcptt-location-info+xml" | "application/vnd.3gpp.mcptt-mbms-usage-info+xml" | "application/vnd.3gpp.mcptt-regroup+xml" | "application/vnd.3gpp.mcptt-service-config+xml" | "application/vnd.3gpp.mcptt-signed+xml" | "application/vnd.3gpp.mcptt-ue-config+xml" | "application/vnd.3gpp.mcptt-ue-init-config+xml" | "application/vnd.3gpp.mcptt-user-profile+xml" | "application/vnd.3gpp.mcvideo-affiliation-command+xml" | "application/vnd.3gpp.mcvideo-affiliation-info+xml (OBSOLETED in favor of application/vnd.3gpp.mcvideo-info+xml)" | "application/vnd.3gpp.mcvideo-info+xml" | "application/vnd.3gpp.mcvideo-location-info+xml" | "application/vnd.3gpp.mcvideo-mbms-usage-info+xml" | "application/vnd.3gpp.mcvideo-regroup+xml" | "application/vnd.3gpp.mcvideo-service-config+xml" | "application/vnd.3gpp.mcvideo-transmission-request+xml" | "application/vnd.3gpp.mcvideo-ue-config+xml" | "application/vnd.3gpp.mcvideo-user-profile+xml" | "application/vnd.3gpp.mid-call+xml" | "application/vnd.3gpp.ngap" | "application/vnd.3gpp.pfcp" | "application/vnd.3gpp.pic-bw-large" | "application/vnd.3gpp.pic-bw-small" | "application/vnd.3gpp.pic-bw-var" | "application/vnd.3gpp.pinapp-info+xml" | "application/vnd.3gpp.s1ap" | "application/vnd.3gpp.seal-group-doc+xml" | "application/vnd.3gpp.seal-info+xml" | "application/vnd.3gpp.seal-location-info+xml" | "application/vnd.3gpp.seal-mbms-usage-info+xml" | "application/vnd.3gpp.seal-network-QoS-management-info+xml" | "application/vnd.3gpp.seal-ue-config-info+xml" | "application/vnd.3gpp.seal-unicast-info+xml" | "application/vnd.3gpp.seal-user-profile-info+xml" | "application/vnd.3gpp.sms" | "application/vnd.3gpp.sms+xml" | "application/vnd.3gpp.srvcc-ext+xml" | "application/vnd.3gpp.state-and-event-info+xml" | "application/vnd.3gpp.ussd+xml" | "application/vnd.3gpp.v2x" | "application/vnd.3gpp.vae-info+xml" | "application/vnd.3gpp2.bcmcsinfo+xml" | "application/vnd.3gpp2.sms" | "application/vnd.3gpp2.tcap" | "application/vnd.3lightssoftware.imagescal" | "application/vnd.FloGraphIt" | "application/vnd.HandHeld-Entertainment+xml" | "application/vnd.Kinar" | "application/vnd.MFER" | "application/vnd.Mobius.DAF" | "application/vnd.Mobius.DIS" | "application/vnd.Mobius.MBK" | "application/vnd.Mobius.MQY" | "application/vnd.Mobius.MSL" | "application/vnd.Mobius.PLC" | "application/vnd.Mobius.TXF" | "application/vnd.Quark.QuarkXPress" | "application/vnd.RenLearn.rlprint" | "application/vnd.SimTech-MindMapper" | "application/vnd.accpac.simply.aso" | "application/vnd.accpac.simply.imp" | "application/vnd.acm.addressxfer+json" | "application/vnd.acm.chatbot+json" | "application/vnd.acucobol" | "application/vnd.acucorp" | "application/vnd.adobe.flash.movie" | "application/vnd.adobe.formscentral.fcdt" | "application/vnd.adobe.fxp" | "application/vnd.adobe.partial-upload" | "application/vnd.adobe.xdp+xml" | "application/vnd.aether.imp" | "application/vnd.afpc.afplinedata" | "application/vnd.afpc.afplinedata-pagedef" | "application/vnd.afpc.cmoca-cmresource" | "application/vnd.afpc.foca-charset" | "application/vnd.afpc.foca-codedfont" | "application/vnd.afpc.foca-codepage" | "application/vnd.afpc.modca" | "application/vnd.afpc.modca-cmtable" | "application/vnd.afpc.modca-formdef" | "application/vnd.afpc.modca-mediummap" | "application/vnd.afpc.modca-objectcontainer" | "application/vnd.afpc.modca-overlay" | "application/vnd.afpc.modca-pagesegment" | "application/vnd.age" | "application/vnd.ah-barcode" | "application/vnd.ahead.space" | "application/vnd.airzip.filesecure.azf" | "application/vnd.airzip.filesecure.azs" | "application/vnd.amadeus+json" | "application/vnd.amazon.mobi8-ebook" | "application/vnd.americandynamics.acc" | "application/vnd.amiga.ami" | "application/vnd.amundsen.maze+xml" | "application/vnd.android.ota" | "application/vnd.anki" | "application/vnd.anser-web-certificate-issue-initiation" | "application/vnd.antix.game-component" | "application/vnd.apache.arrow.file" | "application/vnd.apache.arrow.stream" | "application/vnd.apache.parquet" | "application/vnd.apache.thrift.binary" | "application/vnd.apache.thrift.compact" | "application/vnd.apache.thrift.json" | "application/vnd.apexlang" | "application/vnd.api+json" | "application/vnd.aplextor.warrp+json" | "application/vnd.apothekende.reservation+json" | "application/vnd.apple.installer+xml" | "application/vnd.apple.keynote" | "application/vnd.apple.mpegurl" | "application/vnd.apple.numbers" | "application/vnd.apple.pages" | "application/vnd.arastra.swi (OBSOLETED in favor of application/vnd.aristanetworks.swi)" | "application/vnd.aristanetworks.swi" | "application/vnd.artisan+json" | "application/vnd.artsquare" | "application/vnd.astraea-software.iota" | "application/vnd.audiograph" | "application/vnd.autopackage" | "application/vnd.avalon+json" | "application/vnd.avistar+xml" | "application/vnd.balsamiq.bmml+xml" | "application/vnd.balsamiq.bmpr" | "application/vnd.banana-accounting" | "application/vnd.bbf.usp.error" | "application/vnd.bbf.usp.msg" | "application/vnd.bbf.usp.msg+json" | "application/vnd.bekitzur-stech+json" | "application/vnd.belightsoft.lhzd+zip" | "application/vnd.belightsoft.lhzl+zip" | "application/vnd.bint.med-content" | "application/vnd.biopax.rdf+xml" | "application/vnd.blink-idb-value-wrapper" | "application/vnd.blueice.multipass" | "application/vnd.bluetooth.ep.oob" | "application/vnd.bluetooth.le.oob" | "application/vnd.bmi" | "application/vnd.bpf" | "application/vnd.bpf3" | "application/vnd.businessobjects" | "application/vnd.byu.uapi+json" | "application/vnd.bzip3" | "application/vnd.c3voc.schedule+xml" | "application/vnd.cab-jscript" | "application/vnd.canon-cpdl" | "application/vnd.canon-lips" | "application/vnd.capasystems-pg+json" | "application/vnd.cel" | "application/vnd.cendio.thinlinc.clientconf" | "application/vnd.century-systems.tcp_stream" | "application/vnd.chemdraw+xml" | "application/vnd.chess-pgn" | "application/vnd.chipnuts.karaoke-mmd" | "application/vnd.ciedi" | "application/vnd.cinderella" | "application/vnd.cirpack.isdn-ext" | "application/vnd.citationstyles.style+xml" | "application/vnd.claymore" | "application/vnd.cloanto.rp9" | "application/vnd.clonk.c4group" | "application/vnd.cluetrust.cartomobile-config" | "application/vnd.cluetrust.cartomobile-config-pkg" | "application/vnd.cncf.helm.chart.content.v1.tar+gzip" | "application/vnd.cncf.helm.chart.provenance.v1.prov" | "application/vnd.cncf.helm.config.v1+json" | "application/vnd.coffeescript" | "application/vnd.collabio.xodocuments.document" | "application/vnd.collabio.xodocuments.document-template" | "application/vnd.collabio.xodocuments.presentation" | "application/vnd.collabio.xodocuments.presentation-template" | "application/vnd.collabio.xodocuments.spreadsheet" | "application/vnd.collabio.xodocuments.spreadsheet-template" | "application/vnd.collection+json" | "application/vnd.collection.doc+json" | "application/vnd.collection.next+json" | "application/vnd.comicbook+zip" | "application/vnd.comicbook-rar" | "application/vnd.commerce-battelle" | "application/vnd.commonspace" | "application/vnd.contact.cmsg" | "application/vnd.coreos.ignition+json" | "application/vnd.cosmocaller" | "application/vnd.crick.clicker" | "application/vnd.crick.clicker.keyboard" | "application/vnd.crick.clicker.palette" | "application/vnd.crick.clicker.template" | "application/vnd.crick.clicker.wordbank" | "application/vnd.criticaltools.wbs+xml" | "application/vnd.cryptii.pipe+json" | "application/vnd.crypto-shade-file" | "application/vnd.cryptomator.encrypted" | "application/vnd.cryptomator.vault" | "application/vnd.ctc-posml" | "application/vnd.ctct.ws+xml" | "application/vnd.cups-pdf" | "application/vnd.cups-postscript" | "application/vnd.cups-ppd" | "application/vnd.cups-raster" | "application/vnd.cups-raw" | "application/vnd.curl" | "application/vnd.cyan.dean.root+xml" | "application/vnd.cybank" | "application/vnd.cyclonedx+json" | "application/vnd.cyclonedx+xml" | "application/vnd.d2l.coursepackage1p0+zip" | "application/vnd.d3m-dataset" | "application/vnd.d3m-problem" | "application/vnd.dart" | "application/vnd.data-vision.rdz" | "application/vnd.datalog" | "application/vnd.datapackage+json" | "application/vnd.dataresource+json" | "application/vnd.dbf" | "application/vnd.dcmp+xml" | "application/vnd.debian.binary-package" | "application/vnd.dece.data" | "application/vnd.dece.ttml+xml" | "application/vnd.dece.unspecified" | "application/vnd.dece.zip" | "application/vnd.denovo.fcselayout-link" | "application/vnd.desmume.movie" | "application/vnd.dir-bi.plate-dl-nosuffix" | "application/vnd.dm.delegation+xml" | "application/vnd.dna" | "application/vnd.document+json" | "application/vnd.dolby.mobile.1" | "application/vnd.dolby.mobile.2" | "application/vnd.doremir.scorecloud-binary-document" | "application/vnd.dpgraph" | "application/vnd.dreamfactory" | "application/vnd.drive+json" | "application/vnd.dtg.local" | "application/vnd.dtg.local.flash" | "application/vnd.dtg.local.html" | "application/vnd.dvb.ait" | "application/vnd.dvb.dvbisl+xml" | "application/vnd.dvb.dvbj" | "application/vnd.dvb.esgcontainer" | "application/vnd.dvb.ipdcdftnotifaccess" | "application/vnd.dvb.ipdcesgaccess" | "application/vnd.dvb.ipdcesgaccess2" | "application/vnd.dvb.ipdcesgpdd" | "application/vnd.dvb.ipdcroaming" | "application/vnd.dvb.iptv.alfec-base" | "application/vnd.dvb.iptv.alfec-enhancement" | "application/vnd.dvb.notif-aggregate-root+xml" | "application/vnd.dvb.notif-container+xml" | "application/vnd.dvb.notif-generic+xml" | "application/vnd.dvb.notif-ia-msglist+xml" | "application/vnd.dvb.notif-ia-registration-request+xml" | "application/vnd.dvb.notif-ia-registration-response+xml" | "application/vnd.dvb.notif-init+xml" | "application/vnd.dvb.pfr" | "application/vnd.dvb.service" | "application/vnd.dxr" | "application/vnd.dynageo" | "application/vnd.dzr" | "application/vnd.easykaraoke.cdgdownload" | "application/vnd.ecdis-update" | "application/vnd.ecip.rlp" | "application/vnd.eclipse.ditto+json" | "application/vnd.ecowin.chart" | "application/vnd.ecowin.filerequest" | "application/vnd.ecowin.fileupdate" | "application/vnd.ecowin.series" | "application/vnd.ecowin.seriesrequest" | "application/vnd.ecowin.seriesupdate" | "application/vnd.efi.img" | "application/vnd.efi.iso" | "application/vnd.eln+zip" | "application/vnd.emclient.accessrequest+xml" | "application/vnd.enliven" | "application/vnd.enphase.envoy" | "application/vnd.eprints.data+xml" | "application/vnd.epson.esf" | "application/vnd.epson.msf" | "application/vnd.epson.quickanime" | "application/vnd.epson.salt" | "application/vnd.epson.ssf" | "application/vnd.ericsson.quickcall" | "application/vnd.erofs" | "application/vnd.espass-espass+zip" | "application/vnd.eszigno3+xml" | "application/vnd.etsi.aoc+xml" | "application/vnd.etsi.asic-e+zip" | "application/vnd.etsi.asic-s+zip" | "application/vnd.etsi.cug+xml" | "application/vnd.etsi.iptvcommand+xml" | "application/vnd.etsi.iptvdiscovery+xml" | "application/vnd.etsi.iptvprofile+xml" | "application/vnd.etsi.iptvsad-bc+xml" | "application/vnd.etsi.iptvsad-cod+xml" | "application/vnd.etsi.iptvsad-npvr+xml" | "application/vnd.etsi.iptvservice+xml" | "application/vnd.etsi.iptvsync+xml" | "application/vnd.etsi.iptvueprofile+xml" | "application/vnd.etsi.mcid+xml" | "application/vnd.etsi.mheg5" | "application/vnd.etsi.overload-control-policy-dataset+xml" | "application/vnd.etsi.pstn+xml" | "application/vnd.etsi.sci+xml" | "application/vnd.etsi.simservs+xml" | "application/vnd.etsi.timestamp-token" | "application/vnd.etsi.tsl+xml" | "application/vnd.etsi.tsl.der" | "application/vnd.eu.kasparian.car+json" | "application/vnd.eudora.data" | "application/vnd.evolv.ecig.profile" | "application/vnd.evolv.ecig.settings" | "application/vnd.evolv.ecig.theme" | "application/vnd.exstream-empower+zip" | "application/vnd.exstream-package" | "application/vnd.ezpix-album" | "application/vnd.ezpix-package" | "application/vnd.f-secure.mobile" | "application/vnd.familysearch.gedcom+zip" | "application/vnd.fastcopy-disk-image" | "application/vnd.fdsn.mseed" | "application/vnd.fdsn.seed" | "application/vnd.fdsn.stationxml+xml" | "application/vnd.ffsns" | "application/vnd.ficlab.flb+zip" | "application/vnd.filmit.zfc" | "application/vnd.fints" | "application/vnd.firemonkeys.cloudcell" | "application/vnd.fluxtime.clip" | "application/vnd.font-fontforge-sfd" | "application/vnd.framemaker" | "application/vnd.freelog.comic" | "application/vnd.frogans.fnc (OBSOLETE)" | "application/vnd.frogans.ltf (OBSOLETE)" | "application/vnd.fsc.weblaunch" | "application/vnd.fujifilm.fb.docuworks" | "application/vnd.fujifilm.fb.docuworks.binder" | "application/vnd.fujifilm.fb.docuworks.container" | "application/vnd.fujifilm.fb.jfi+xml" | "application/vnd.fujitsu.oasys" | "application/vnd.fujitsu.oasys2" | "application/vnd.fujitsu.oasys3" | "application/vnd.fujitsu.oasysgp" | "application/vnd.fujitsu.oasysprs" | "application/vnd.fujixerox.ART-EX" | "application/vnd.fujixerox.ART4" | "application/vnd.fujixerox.HBPL" | "application/vnd.fujixerox.ddd" | "application/vnd.fujixerox.docuworks" | "application/vnd.fujixerox.docuworks.binder" | "application/vnd.fujixerox.docuworks.container" | "application/vnd.fut-misnet" | "application/vnd.futoin+cbor" | "application/vnd.futoin+json" | "application/vnd.fuzzysheet" | "application/vnd.ga4gh.passport+jwt" | "application/vnd.genomatix.tuxedo" | "application/vnd.genozip" | "application/vnd.gentics.grd+json" | "application/vnd.gentoo.catmetadata+xml" | "application/vnd.gentoo.ebuild" | "application/vnd.gentoo.eclass" | "application/vnd.gentoo.gpkg" | "application/vnd.gentoo.manifest" | "application/vnd.gentoo.pkgmetadata+xml" | "application/vnd.gentoo.xpak" | "application/vnd.geo+json (OBSOLETED by [RFC7946] in favor of application/geo+json)" | "application/vnd.geocube+xml (OBSOLETED by request)" | "application/vnd.geogebra.file" | "application/vnd.geogebra.pinboard" | "application/vnd.geogebra.slides" | "application/vnd.geogebra.tool" | "application/vnd.geometry-explorer" | "application/vnd.geonext" | "application/vnd.geoplan" | "application/vnd.geospace" | "application/vnd.gerber" | "application/vnd.globalplatform.card-content-mgt" | "application/vnd.globalplatform.card-content-mgt-response" | "application/vnd.gmx - DEPRECATED" | "application/vnd.gnu.taler.exchange+json" | "application/vnd.gnu.taler.merchant+json" | "application/vnd.google-earth.kml+xml" | "application/vnd.google-earth.kmz" | "application/vnd.gov.sk.e-form+xml (OBSOLETED by request)" | "application/vnd.gov.sk.e-form+zip" | "application/vnd.gov.sk.xmldatacontainer+xml" | "application/vnd.gpxsee.map+xml" | "application/vnd.grafeq" | "application/vnd.gridmp" | "application/vnd.groove-account" | "application/vnd.groove-help" | "application/vnd.groove-identity-message" | "application/vnd.groove-injector" | "application/vnd.groove-tool-message" | "application/vnd.groove-tool-template" | "application/vnd.groove-vcard" | "application/vnd.hal+json" | "application/vnd.hal+xml" | "application/vnd.hbci" | "application/vnd.hc+json" | "application/vnd.hcl-bireports" | "application/vnd.hdt" | "application/vnd.heroku+json" | "application/vnd.hhe.lesson-player" | "application/vnd.hp-HPGL" | "application/vnd.hp-PCL" | "application/vnd.hp-PCLXL" | "application/vnd.hp-hpid" | "application/vnd.hp-hps" | "application/vnd.hp-jlyt" | "application/vnd.hsl" | "application/vnd.httphone" | "application/vnd.hydrostatix.sof-data" | "application/vnd.hyper+json" | "application/vnd.hyper-item+json" | "application/vnd.hyperdrive+json" | "application/vnd.hzn-3d-crossword" | "application/vnd.ibm.MiniPay" | "application/vnd.ibm.afplinedata (OBSOLETED in favor of vnd.afpc.afplinedata)" | "application/vnd.ibm.electronic-media" | "application/vnd.ibm.modcap (OBSOLETED in favor of application/vnd.afpc.modca)" | "application/vnd.ibm.rights-management" | "application/vnd.ibm.secure-container" | "application/vnd.iccprofile" | "application/vnd.ieee.1905" | "application/vnd.igloader" | "application/vnd.imagemeter.folder+zip" | "application/vnd.imagemeter.image+zip" | "application/vnd.immervision-ivp" | "application/vnd.immervision-ivu" | "application/vnd.ims.imsccv1p1" | "application/vnd.ims.imsccv1p2" | "application/vnd.ims.imsccv1p3" | "application/vnd.ims.lis.v2.result+json" | "application/vnd.ims.lti.v2.toolconsumerprofile+json" | "application/vnd.ims.lti.v2.toolproxy+json" | "application/vnd.ims.lti.v2.toolproxy.id+json" | "application/vnd.ims.lti.v2.toolsettings+json" | "application/vnd.ims.lti.v2.toolsettings.simple+json" | "application/vnd.informedcontrol.rms+xml" | "application/vnd.informix-visionary (OBSOLETED in favor of application/vnd.visionary)" | "application/vnd.infotech.project" | "application/vnd.infotech.project+xml" | "application/vnd.innopath.wamp.notification" | "application/vnd.insors.igm" | "application/vnd.intercon.formnet" | "application/vnd.intergeo" | "application/vnd.intertrust.digibox" | "application/vnd.intertrust.nncp" | "application/vnd.intu.qbo" | "application/vnd.intu.qfx" | "application/vnd.ipfs.ipns-record" | "application/vnd.ipld.car" | "application/vnd.ipld.dag-cbor" | "application/vnd.ipld.dag-json" | "application/vnd.ipld.raw" | "application/vnd.iptc.g2.catalogitem+xml" | "application/vnd.iptc.g2.conceptitem+xml" | "application/vnd.iptc.g2.knowledgeitem+xml" | "application/vnd.iptc.g2.newsitem+xml" | "application/vnd.iptc.g2.newsmessage+xml" | "application/vnd.iptc.g2.packageitem+xml" | "application/vnd.iptc.g2.planningitem+xml" | "application/vnd.ipunplugged.rcprofile" | "application/vnd.irepository.package+xml" | "application/vnd.is-xpr" | "application/vnd.isac.fcs" | "application/vnd.iso11783-10+zip" | "application/vnd.jam" | "application/vnd.japannet-directory-service" | "application/vnd.japannet-jpnstore-wakeup" | "application/vnd.japannet-payment-wakeup" | "application/vnd.japannet-registration" | "application/vnd.japannet-registration-wakeup" | "application/vnd.japannet-setstore-wakeup" | "application/vnd.japannet-verification" | "application/vnd.japannet-verification-wakeup" | "application/vnd.jcp.javame.midlet-rms" | "application/vnd.jisp" | "application/vnd.joost.joda-archive" | "application/vnd.jsk.isdn-ngn" | "application/vnd.kahootz" | "application/vnd.kde.karbon" | "application/vnd.kde.kchart" | "application/vnd.kde.kformula" | "application/vnd.kde.kivio" | "application/vnd.kde.kontour" | "application/vnd.kde.kpresenter" | "application/vnd.kde.kspread" | "application/vnd.kde.kword" | "application/vnd.kdl" | "application/vnd.kenameaapp" | "application/vnd.keyman.kmp+zip" | "application/vnd.keyman.kmx" | "application/vnd.kidspiration" | "application/vnd.koan" | "application/vnd.kodak-descriptor" | "application/vnd.las" | "application/vnd.las.las+json" | "application/vnd.las.las+xml" | "application/vnd.laszip" | "application/vnd.ldev.productlicensing" | "application/vnd.leap+json" | "application/vnd.liberty-request+xml" | "application/vnd.llamagraphics.life-balance.desktop" | "application/vnd.llamagraphics.life-balance.exchange+xml" | "application/vnd.logipipe.circuit+zip" | "application/vnd.loom" | "application/vnd.lotus-1-2-3" | "application/vnd.lotus-approach" | "application/vnd.lotus-freelance" | "application/vnd.lotus-notes" | "application/vnd.lotus-organizer" | "application/vnd.lotus-screencam" | "application/vnd.lotus-wordpro" | "application/vnd.macports.portpkg" | "application/vnd.mapbox-vector-tile" | "application/vnd.marlin.drm.actiontoken+xml" | "application/vnd.marlin.drm.conftoken+xml" | "application/vnd.marlin.drm.license+xml" | "application/vnd.marlin.drm.mdcf" | "application/vnd.mason+json" | "application/vnd.maxar.archive.3tz+zip" | "application/vnd.maxmind.maxmind-db" | "application/vnd.mcd" | "application/vnd.mdl" | "application/vnd.mdl-mbsdf" | "application/vnd.medcalcdata" | "application/vnd.mediastation.cdkey" | "application/vnd.medicalholodeck.recordxr" | "application/vnd.meridian-slingshot" | "application/vnd.mermaid" | "application/vnd.mfmp" | "application/vnd.micro+json" | "application/vnd.micrografx.flo" | "application/vnd.micrografx.igx" | "application/vnd.microsoft.portable-executable" | "application/vnd.microsoft.windows.thumbnail-cache" | "application/vnd.miele+json" | "application/vnd.mif" | "application/vnd.minisoft-hp3000-save" | "application/vnd.mitsubishi.misty-guard.trustweb" | "application/vnd.modl" | "application/vnd.mophun.application" | "application/vnd.mophun.certificate" | "application/vnd.motorola.flexsuite" | "application/vnd.motorola.flexsuite.adsi" | "application/vnd.motorola.flexsuite.fis" | "application/vnd.motorola.flexsuite.gotap" | "application/vnd.motorola.flexsuite.kmr" | "application/vnd.motorola.flexsuite.ttc" | "application/vnd.motorola.flexsuite.wem" | "application/vnd.motorola.iprm" | "application/vnd.mozilla.xul+xml" | "application/vnd.ms-3mfdocument" | "application/vnd.ms-PrintDeviceCapabilities+xml" | "application/vnd.ms-PrintSchemaTicket+xml" | "application/vnd.ms-artgalry" | "application/vnd.ms-asf" | "application/vnd.ms-cab-compressed" | "application/vnd.ms-excel" | "application/vnd.ms-excel.addin.macroEnabled.12" | "application/vnd.ms-excel.sheet.binary.macroEnabled.12" | "application/vnd.ms-excel.sheet.macroEnabled.12" | "application/vnd.ms-excel.template.macroEnabled.12" | "application/vnd.ms-fontobject" | "application/vnd.ms-htmlhelp" | "application/vnd.ms-ims" | "application/vnd.ms-lrm" | "application/vnd.ms-office.activeX+xml" | "application/vnd.ms-officetheme" | "application/vnd.ms-playready.initiator+xml" | "application/vnd.ms-powerpoint" | "application/vnd.ms-powerpoint.addin.macroEnabled.12" | "application/vnd.ms-powerpoint.presentation.macroEnabled.12" | "application/vnd.ms-powerpoint.slide.macroEnabled.12" | "application/vnd.ms-powerpoint.slideshow.macroEnabled.12" | "application/vnd.ms-powerpoint.template.macroEnabled.12" | "application/vnd.ms-project" | "application/vnd.ms-tnef" | "application/vnd.ms-windows.devicepairing" | "application/vnd.ms-windows.nwprinting.oob" | "application/vnd.ms-windows.printerpairing" | "application/vnd.ms-windows.wsd.oob" | "application/vnd.ms-wmdrm.lic-chlg-req" | "application/vnd.ms-wmdrm.lic-resp" | "application/vnd.ms-wmdrm.meter-chlg-req" | "application/vnd.ms-wmdrm.meter-resp" | "application/vnd.ms-word.document.macroEnabled.12" | "application/vnd.ms-word.template.macroEnabled.12" | "application/vnd.ms-works" | "application/vnd.ms-wpl" | "application/vnd.ms-xpsdocument" | "application/vnd.msa-disk-image" | "application/vnd.mseq" | "application/vnd.msgpack" | "application/vnd.msign" | "application/vnd.multiad.creator" | "application/vnd.multiad.creator.cif" | "application/vnd.music-niff" | "application/vnd.musician" | "application/vnd.muvee.style" | "application/vnd.mynfc" | "application/vnd.nacamar.ybrid+json" | "application/vnd.nato.bindingdataobject+cbor" | "application/vnd.nato.bindingdataobject+json" | "application/vnd.nato.bindingdataobject+xml" | "application/vnd.nato.openxmlformats-package.iepd+zip" | "application/vnd.ncd.control" | "application/vnd.ncd.reference" | "application/vnd.nearst.inv+json" | "application/vnd.nebumind.line" | "application/vnd.nervana" | "application/vnd.netfpx" | "application/vnd.neurolanguage.nlu" | "application/vnd.nimn" | "application/vnd.nintendo.nitro.rom" | "application/vnd.nintendo.snes.rom" | "application/vnd.nitf" | "application/vnd.noblenet-directory" | "application/vnd.noblenet-sealer" | "application/vnd.noblenet-web" | "application/vnd.nokia.catalogs" | "application/vnd.nokia.conml+wbxml" | "application/vnd.nokia.conml+xml" | "application/vnd.nokia.iSDS-radio-presets" | "application/vnd.nokia.iptv.config+xml" | "application/vnd.nokia.landmark+wbxml" | "application/vnd.nokia.landmark+xml" | "application/vnd.nokia.landmarkcollection+xml" | "application/vnd.nokia.n-gage.ac+xml" | "application/vnd.nokia.n-gage.data" | "application/vnd.nokia.n-gage.symbian.install (OBSOLETE; no replacement given)" | "application/vnd.nokia.ncd" | "application/vnd.nokia.pcd+wbxml" | "application/vnd.nokia.pcd+xml" | "application/vnd.nokia.radio-preset" | "application/vnd.nokia.radio-presets" | "application/vnd.novadigm.EDM" | "application/vnd.novadigm.EDX" | "application/vnd.novadigm.EXT" | "application/vnd.ntt-local.content-share" | "application/vnd.ntt-local.file-transfer" | "application/vnd.ntt-local.ogw_remote-access" | "application/vnd.ntt-local.sip-ta_remote" | "application/vnd.ntt-local.sip-ta_tcp_stream" | "application/vnd.oai.workflows" | "application/vnd.oai.workflows+json" | "application/vnd.oai.workflows+yaml" | "application/vnd.oasis.opendocument.base" | "application/vnd.oasis.opendocument.chart" | "application/vnd.oasis.opendocument.chart-template" | "application/vnd.oasis.opendocument.database (OBSOLETED in favor of application/vnd.oasis.opendocument.base)" | "application/vnd.oasis.opendocument.formula" | "application/vnd.oasis.opendocument.formula-template" | "application/vnd.oasis.opendocument.graphics" | "application/vnd.oasis.opendocument.graphics-template" | "application/vnd.oasis.opendocument.image" | "application/vnd.oasis.opendocument.image-template" | "application/vnd.oasis.opendocument.presentation" | "application/vnd.oasis.opendocument.presentation-template" | "application/vnd.oasis.opendocument.spreadsheet" | "application/vnd.oasis.opendocument.spreadsheet-template" | "application/vnd.oasis.opendocument.text" | "application/vnd.oasis.opendocument.text-master" | "application/vnd.oasis.opendocument.text-master-template" | "application/vnd.oasis.opendocument.text-template" | "application/vnd.oasis.opendocument.text-web" | "application/vnd.obn" | "application/vnd.ocf+cbor" | "application/vnd.oci.image.manifest.v1+json" | "application/vnd.oftn.l10n+json" | "application/vnd.oipf.contentaccessdownload+xml" | "application/vnd.oipf.contentaccessstreaming+xml" | "application/vnd.oipf.cspg-hexbinary" | "application/vnd.oipf.dae.svg+xml" | "application/vnd.oipf.dae.xhtml+xml" | "application/vnd.oipf.mippvcontrolmessage+xml" | "application/vnd.oipf.pae.gem" | "application/vnd.oipf.spdiscovery+xml" | "application/vnd.oipf.spdlist+xml" | "application/vnd.oipf.ueprofile+xml" | "application/vnd.oipf.userprofile+xml" | "application/vnd.olpc-sugar" | "application/vnd.oma-scws-config" | "application/vnd.oma-scws-http-request" | "application/vnd.oma-scws-http-response" | "application/vnd.oma.bcast.associated-procedure-parameter+xml" | "application/vnd.oma.bcast.drm-trigger+xml" | "application/vnd.oma.bcast.imd+xml" | "application/vnd.oma.bcast.ltkm" | "application/vnd.oma.bcast.notification+xml" | "application/vnd.oma.bcast.provisioningtrigger" | "application/vnd.oma.bcast.sgboot" | "application/vnd.oma.bcast.sgdd+xml" | "application/vnd.oma.bcast.sgdu" | "application/vnd.oma.bcast.simple-symbol-container" | "application/vnd.oma.bcast.smartcard-trigger+xml" | "application/vnd.oma.bcast.sprov+xml" | "application/vnd.oma.bcast.stkm" | "application/vnd.oma.cab-address-book+xml" | "application/vnd.oma.cab-feature-handler+xml" | "application/vnd.oma.cab-pcc+xml" | "application/vnd.oma.cab-subs-invite+xml" | "application/vnd.oma.cab-user-prefs+xml" | "application/vnd.oma.dcd" | "application/vnd.oma.dcdc" | "application/vnd.oma.dd2+xml" | "application/vnd.oma.drm.risd+xml" | "application/vnd.oma.group-usage-list+xml" | "application/vnd.oma.lwm2m+cbor" | "application/vnd.oma.lwm2m+json" | "application/vnd.oma.lwm2m+tlv" | "application/vnd.oma.pal+xml" | "application/vnd.oma.poc.detailed-progress-report+xml" | "application/vnd.oma.poc.final-report+xml" | "application/vnd.oma.poc.groups+xml" | "application/vnd.oma.poc.invocation-descriptor+xml" | "application/vnd.oma.poc.optimized-progress-report+xml" | "application/vnd.oma.push" | "application/vnd.oma.scidm.messages+xml" | "application/vnd.oma.xcap-directory+xml" | "application/vnd.omads-email+xml" | "application/vnd.omads-file+xml" | "application/vnd.omads-folder+xml" | "application/vnd.omaloc-supl-init" | "application/vnd.onepager" | "application/vnd.onepagertamp" | "application/vnd.onepagertamx" | "application/vnd.onepagertat" | "application/vnd.onepagertatp" | "application/vnd.onepagertatx" | "application/vnd.onvif.metadata" | "application/vnd.openblox.game+xml" | "application/vnd.openblox.game-binary" | "application/vnd.openeye.oeb" | "application/vnd.openstreetmap.data+xml" | "application/vnd.opentimestamps.ots" | "application/vnd.openvpi.dspx+json" | "application/vnd.openxmlformats-officedocument.custom-properties+xml" | "application/vnd.openxmlformats-officedocument.customXmlProperties+xml" | "application/vnd.openxmlformats-officedocument.drawing+xml" | "application/vnd.openxmlformats-officedocument.drawingml.chart+xml" | "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml" | "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml" | "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml" | "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml" | "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml" | "application/vnd.openxmlformats-officedocument.extended-properties+xml" | "application/vnd.openxmlformats-officedocument.presentationml.commentAuthors+xml" | "application/vnd.openxmlformats-officedocument.presentationml.comments+xml" | "application/vnd.openxmlformats-officedocument.presentationml.handoutMaster+xml" | "application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml" | "application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml" | "application/vnd.openxmlformats-officedocument.presentationml.presProps+xml" | "application/vnd.openxmlformats-officedocument.presentationml.presentation" | "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml" | "application/vnd.openxmlformats-officedocument.presentationml.slide" | "application/vnd.openxmlformats-officedocument.presentationml.slide+xml" | "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml" | "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml" | "application/vnd.openxmlformats-officedocument.presentationml.slideUpdateInfo+xml" | "application/vnd.openxmlformats-officedocument.presentationml.slideshow" | "application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml" | "application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml" | "application/vnd.openxmlformats-officedocument.presentationml.tags+xml" | "application/vnd.openxmlformats-officedocument.presentationml.template" | "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml" | "application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.template" | "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.volatileDependencies+xml" | "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" | "application/vnd.openxmlformats-officedocument.theme+xml" | "application/vnd.openxmlformats-officedocument.themeOverride+xml" | "application/vnd.openxmlformats-officedocument.vmlDrawing" | "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml" | "application/vnd.openxmlformats-officedocument.wordprocessingml.document" | "application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml" | "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" | "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml" | "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml" | "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml" | "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml" | "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml" | "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml" | "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml" | "application/vnd.openxmlformats-officedocument.wordprocessingml.template" | "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml" | "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml" | "application/vnd.openxmlformats-package.core-properties+xml" | "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml" | "application/vnd.openxmlformats-package.relationships+xml" | "application/vnd.oracle.resource+json" | "application/vnd.orange.indata" | "application/vnd.osa.netdeploy" | "application/vnd.osgeo.mapguide.package" | "application/vnd.osgi.bundle" | "application/vnd.osgi.dp" | "application/vnd.osgi.subsystem" | "application/vnd.otps.ct-kip+xml" | "application/vnd.oxli.countgraph" | "application/vnd.pagerduty+json" | "application/vnd.palm" | "application/vnd.panoply" | "application/vnd.paos.xml" | "application/vnd.patentdive" | "application/vnd.patientecommsdoc" | "application/vnd.pawaafile" | "application/vnd.pcos" | "application/vnd.pg.format" | "application/vnd.pg.osasli" | "application/vnd.piaccess.application-licence" | "application/vnd.picsel" | "application/vnd.pmi.widget" | "application/vnd.pmtiles" | "application/vnd.poc.group-advertisement+xml" | "application/vnd.pocketlearn" | "application/vnd.powerbuilder6" | "application/vnd.powerbuilder6-s" | "application/vnd.powerbuilder7" | "application/vnd.powerbuilder7-s" | "application/vnd.powerbuilder75" | "application/vnd.powerbuilder75-s" | "application/vnd.preminet" | "application/vnd.previewsystems.box" | "application/vnd.proteus.magazine" | "application/vnd.psfs" | "application/vnd.pt.mundusmundi" | "application/vnd.publishare-delta-tree" | "application/vnd.pvi.ptid1" | "application/vnd.pwg-multiplexed" | "application/vnd.pwg-xhtml-print+xml" | "application/vnd.qualcomm.brew-app-res" | "application/vnd.quarantainenet" | "application/vnd.quobject-quoxdocument" | "application/vnd.radisys.moml+xml" | "application/vnd.radisys.msml+xml" | "application/vnd.radisys.msml-audit+xml" | "application/vnd.radisys.msml-audit-conf+xml" | "application/vnd.radisys.msml-audit-conn+xml" | "application/vnd.radisys.msml-audit-dialog+xml" | "application/vnd.radisys.msml-audit-stream+xml" | "application/vnd.radisys.msml-conf+xml" | "application/vnd.radisys.msml-dialog+xml" | "application/vnd.radisys.msml-dialog-base+xml" | "application/vnd.radisys.msml-dialog-fax-detect+xml" | "application/vnd.radisys.msml-dialog-fax-sendrecv+xml" | "application/vnd.radisys.msml-dialog-group+xml" | "application/vnd.radisys.msml-dialog-speech+xml" | "application/vnd.radisys.msml-dialog-transform+xml" | "application/vnd.rainstor.data" | "application/vnd.rapid" | "application/vnd.rar" | "application/vnd.realvnc.bed" | "application/vnd.recordare.musicxml" | "application/vnd.recordare.musicxml+xml" | "application/vnd.relpipe" | "application/vnd.resilient.logic" | "application/vnd.restful+json" | "application/vnd.rig.cryptonote" | "application/vnd.route66.link66+xml" | "application/vnd.rs-274x" | "application/vnd.ruckus.download" | "application/vnd.s3sms" | "application/vnd.sailingtracker.track" | "application/vnd.sar" | "application/vnd.sbm.cid" | "application/vnd.sbm.mid2" | "application/vnd.scribus" | "application/vnd.sealed.3df" | "application/vnd.sealed.csf" | "application/vnd.sealed.doc" | "application/vnd.sealed.eml" | "application/vnd.sealed.mht" | "application/vnd.sealed.net" | "application/vnd.sealed.ppt" | "application/vnd.sealed.tiff" | "application/vnd.sealed.xls" | "application/vnd.sealedmedia.softseal.html" | "application/vnd.sealedmedia.softseal.pdf" | "application/vnd.seemail" | "application/vnd.seis+json" | "application/vnd.sema" | "application/vnd.semd" | "application/vnd.semf" | "application/vnd.shade-save-file" | "application/vnd.shana.informed.formdata" | "application/vnd.shana.informed.formtemplate" | "application/vnd.shana.informed.interchange" | "application/vnd.shana.informed.package" | "application/vnd.shootproof+json" | "application/vnd.shopkick+json" | "application/vnd.shp" | "application/vnd.shx" | "application/vnd.sigrok.session" | "application/vnd.siren+json" | "application/vnd.sketchometry" | "application/vnd.smaf" | "application/vnd.smart.notebook" | "application/vnd.smart.teacher" | "application/vnd.smintio.portals.archive" | "application/vnd.snesdev-page-table" | "application/vnd.software602.filler.form+xml" | "application/vnd.software602.filler.form-xml-zip" | "application/vnd.solent.sdkm+xml" | "application/vnd.spotfire.dxp" | "application/vnd.spotfire.sfs" | "application/vnd.sqlite3" | "application/vnd.sss-cod" | "application/vnd.sss-dtf" | "application/vnd.sss-ntf" | "application/vnd.stepmania.package" | "application/vnd.stepmania.stepchart" | "application/vnd.street-stream" | "application/vnd.sun.wadl+xml" | "application/vnd.superfile.super" | "application/vnd.sus-calendar" | "application/vnd.svd" | "application/vnd.swiftview-ics" | "application/vnd.sybyl.mol2" | "application/vnd.sycle+xml" | "application/vnd.syft+json" | "application/vnd.syncml+xml" | "application/vnd.syncml.dm+wbxml" | "application/vnd.syncml.dm+xml" | "application/vnd.syncml.dm.notification" | "application/vnd.syncml.dmddf+wbxml" | "application/vnd.syncml.dmddf+xml" | "application/vnd.syncml.dmtnds+wbxml" | "application/vnd.syncml.dmtnds+xml" | "application/vnd.syncml.ds.notification" | "application/vnd.tableschema+json" | "application/vnd.tao.intent-module-archive" | "application/vnd.tcpdump.pcap" | "application/vnd.think-cell.ppttc+json" | "application/vnd.tmd.mediaflex.api+xml" | "application/vnd.tml" | "application/vnd.tmobile-livetv" | "application/vnd.tri.onesource" | "application/vnd.trid.tpt" | "application/vnd.triscape.mxs" | "application/vnd.trueapp" | "application/vnd.truedoc" | "application/vnd.ubisoft.webplayer" | "application/vnd.ufdl" | "application/vnd.uic.osdm+json" | "application/vnd.uiq.theme" | "application/vnd.umajin" | "application/vnd.unity" | "application/vnd.uoml+xml" | "application/vnd.uplanet.alert" | "application/vnd.uplanet.alert-wbxml" | "application/vnd.uplanet.bearer-choice" | "application/vnd.uplanet.bearer-choice-wbxml" | "application/vnd.uplanet.cacheop" | "application/vnd.uplanet.cacheop-wbxml" | "application/vnd.uplanet.channel" | "application/vnd.uplanet.channel-wbxml" | "application/vnd.uplanet.list" | "application/vnd.uplanet.list-wbxml" | "application/vnd.uplanet.listcmd" | "application/vnd.uplanet.listcmd-wbxml" | "application/vnd.uplanet.signal" | "application/vnd.uri-map" | "application/vnd.valve.source.material" | "application/vnd.vcx" | "application/vnd.vd-study" | "application/vnd.vectorworks" | "application/vnd.vel+json" | "application/vnd.veraison.tsm-report+cbor" | "application/vnd.veraison.tsm-report+json" | "application/vnd.verimatrix.vcas" | "application/vnd.veritone.aion+json" | "application/vnd.veryant.thin" | "application/vnd.ves.encrypted" | "application/vnd.vidsoft.vidconference" | "application/vnd.visio" | "application/vnd.visionary" | "application/vnd.vividence.scriptfile" | "application/vnd.vocalshaper.vsp4" | "application/vnd.vsf" | "application/vnd.wantverse" | "application/vnd.wap.sic" | "application/vnd.wap.slc" | "application/vnd.wap.wbxml" | "application/vnd.wap.wmlc" | "application/vnd.wap.wmlscriptc" | "application/vnd.wasmflow.wafl" | "application/vnd.webturbo" | "application/vnd.wfa.dpp" | "application/vnd.wfa.p2p" | "application/vnd.wfa.wsc" | "application/vnd.windows.devicepairing" | "application/vnd.wmc" | "application/vnd.wmf.bootstrap" | "application/vnd.wolfram.mathematica" | "application/vnd.wolfram.mathematica.package" | "application/vnd.wolfram.player" | "application/vnd.wordlift" | "application/vnd.wordperfect" | "application/vnd.wqd" | "application/vnd.wrq-hp3000-labelled" | "application/vnd.wt.stf" | "application/vnd.wv.csp+wbxml" | "application/vnd.wv.csp+xml" | "application/vnd.wv.ssp+xml" | "application/vnd.xacml+json" | "application/vnd.xara" | "application/vnd.xarin.cpj" | "application/vnd.xecrets-encrypted" | "application/vnd.xfdl" | "application/vnd.xfdl.webform" | "application/vnd.xmi+xml" | "application/vnd.xmpie.cpkg" | "application/vnd.xmpie.dpkg" | "application/vnd.xmpie.plan" | "application/vnd.xmpie.ppkg" | "application/vnd.xmpie.xlim" | "application/vnd.yamaha.hv-dic" | "application/vnd.yamaha.hv-script" | "application/vnd.yamaha.hv-voice" | "application/vnd.yamaha.openscoreformat" | "application/vnd.yamaha.openscoreformat.osfpvg+xml" | "application/vnd.yamaha.remote-setup" | "application/vnd.yamaha.smaf-audio" | "application/vnd.yamaha.smaf-phrase" | "application/vnd.yamaha.through-ngn" | "application/vnd.yamaha.tunnel-udpencap" | "application/vnd.yaoweme" | "application/vnd.yellowriver-custom-menu" | "application/vnd.youtube.yt (OBSOLETED in favor of video/vnd.youtube.yt)" | "application/vnd.zul" | "application/vnd.zzazz.deck+xml" | "application/voicexml+xml" | "application/voucher-cms+json" | "application/voucher-jws+json" | "application/vp" | "application/vp+cose" | "application/vp+jwt" | "application/vq-rtcpxr" | "application/wasm" | "application/watcherinfo+xml" | "application/webpush-options+json" | "application/whoispp-query" | "application/whoispp-response" | "application/widget" | "application/wita" | "application/wordperfect5.1" | "application/wsdl+xml" | "application/wspolicy+xml" | "application/x-pki-message" | "application/x-www-form-urlencoded" | "application/x-x509-ca-cert" | "application/x-x509-ca-ra-cert" | "application/x-x509-next-ca-cert" | "application/x400-bp" | "application/xacml+xml" | "application/xcap-att+xml" | "application/xcap-caps+xml" | "application/xcap-diff+xml" | "application/xcap-el+xml" | "application/xcap-error+xml" | "application/xcap-ns+xml" | "application/xcon-conference-info+xml" | "application/xcon-conference-info-diff+xml" | "application/xenc+xml" | "application/xfdf" | "application/xhtml+xml" | "application/xliff+xml" | "application/xml" | "application/xml-dtd" | "application/xml-external-parsed-entity" | "application/xml-patch+xml" | "application/xmpp+xml" | "application/xop+xml" | "application/xslt+xml" | "application/xv+xml" | "application/yaml" | "application/yang" | "application/yang-data+cbor" | "application/yang-data+json" | "application/yang-data+xml" | "application/yang-patch+json" | "application/yang-patch+xml" | "application/yang-sid+json" | "application/yin+xml" | "application/zip" | "application/zlib" | "application/zstd" | "audio/1d-interleaved-parityfec" | "audio/32kadpcm" | "audio/3gpp" | "audio/3gpp2" | "audio/AMR" | "audio/AMR-WB" | "audio/ATRAC-ADVANCED-LOSSLESS" | "audio/ATRAC-X" | "audio/ATRAC3" | "audio/BV16" | "audio/BV32" | "audio/CN" | "audio/DAT12" | "audio/DV" | "audio/DVI4" | "audio/EVRC" | "audio/EVRC-QCP" | "audio/EVRC0" | "audio/EVRC1" | "audio/EVRCB" | "audio/EVRCB0" | "audio/EVRCB1" | "audio/EVRCNW" | "audio/EVRCNW0" | "audio/EVRCNW1" | "audio/EVRCWB" | "audio/EVRCWB0" | "audio/EVRCWB1" | "audio/EVS" | "audio/G711-0" | "audio/G719" | "audio/G722" | "audio/G7221" | "audio/G723" | "audio/G726-16" | "audio/G726-24" | "audio/G726-32" | "audio/G726-40" | "audio/G728" | "audio/G729" | "audio/G7291" | "audio/G729D" | "audio/G729E" | "audio/GSM" | "audio/GSM-EFR" | "audio/GSM-HR-08" | "audio/L16" | "audio/L20" | "audio/L24" | "audio/L8" | "audio/LPC" | "audio/MELP" | "audio/MELP1200" | "audio/MELP2400" | "audio/MELP600" | "audio/MP4A-LATM" | "audio/MPA" | "audio/PCMA" | "audio/PCMA-WB" | "audio/PCMU" | "audio/PCMU-WB" | "audio/QCELP" | "audio/RED" | "audio/SMV" | "audio/SMV-QCP" | "audio/SMV0" | "audio/TETRA_ACELP" | "audio/TETRA_ACELP_BB" | "audio/TSVCIS" | "audio/UEMCLIP" | "audio/VDVI" | "audio/VMR-WB" | "audio/aac" | "audio/ac3" | "audio/amr-wb+" | "audio/aptx" | "audio/asc" | "audio/basic" | "audio/clearmode" | "audio/dls" | "audio/dsr-es201108" | "audio/dsr-es202050" | "audio/dsr-es202211" | "audio/dsr-es202212" | "audio/eac3" | "audio/encaprtp" | "audio/example" | "audio/flac" | "audio/flexfec" | "audio/fwdred" | "audio/iLBC" | "audio/ip-mr_v2.5" | "audio/matroska" | "audio/mhas" | "audio/midi-clip" | "audio/mobile-xmf" | "audio/mp4" | "audio/mpa-robust" | "audio/mpeg" | "audio/mpeg4-generic" | "audio/ogg" | "audio/opus" | "audio/parityfec" | "audio/prs.sid" | "audio/raptorfec" | "audio/rtp-enc-aescm128" | "audio/rtp-midi" | "audio/rtploopback" | "audio/rtx" | "audio/scip" | "audio/sofa" | "audio/sp-midi" | "audio/speex" | "audio/t140c" | "audio/t38" | "audio/telephone-event" | "audio/tone" | "audio/ulpfec" | "audio/usac" | "audio/vnd.3gpp.iufp" | "audio/vnd.4SB" | "audio/vnd.CELP" | "audio/vnd.audiokoz" | "audio/vnd.cisco.nse" | "audio/vnd.cmles.radio-events" | "audio/vnd.cns.anp1" | "audio/vnd.cns.inf1" | "audio/vnd.dece.audio" | "audio/vnd.digital-winds" | "audio/vnd.dlna.adts" | "audio/vnd.dolby.heaac.1" | "audio/vnd.dolby.heaac.2" | "audio/vnd.dolby.mlp" | "audio/vnd.dolby.mps" | "audio/vnd.dolby.pl2" | "audio/vnd.dolby.pl2x" | "audio/vnd.dolby.pl2z" | "audio/vnd.dolby.pulse.1" | "audio/vnd.dra" | "audio/vnd.dts" | "audio/vnd.dts.hd" | "audio/vnd.dts.uhd" | "audio/vnd.dvb.file" | "audio/vnd.everad.plj" | "audio/vnd.hns.audio" | "audio/vnd.lucent.voice" | "audio/vnd.ms-playready.media.pya" | "audio/vnd.nokia.mobile-xmf" | "audio/vnd.nortel.vbk" | "audio/vnd.nuera.ecelp4800" | "audio/vnd.nuera.ecelp7470" | "audio/vnd.nuera.ecelp9600" | "audio/vnd.octel.sbc" | "audio/vnd.presonus.multitrack" | "audio/vnd.qcelp - DEPRECATED in favor of audio/qcelp" | "audio/vnd.rhetorex.32kadpcm" | "audio/vnd.rip" | "audio/vnd.sealedmedia.softseal.mpeg" | "audio/vnd.vmx.cvsd" | "audio/vorbis" | "audio/vorbis-config" | "font/collection" | "font/otf" | "font/sfnt" | "font/ttf" | "font/woff" | "font/woff2" | "haptics/hjif" | "haptics/hmpg" | "haptics/ivs" | "image/aces" | "image/apng" | "image/avci" | "image/avcs" | "image/avif" | "image/bmp" | "image/cgm" | "image/dicom-rle" | "image/dpx" | "image/emf" | "image/example" | "image/fits" | "image/g3fax" | "image/gif" | "image/heic" | "image/heic-sequence" | "image/heif" | "image/heif-sequence" | "image/hej2k" | "image/hsj2 (OBSOLETE)" | "image/ief" | "image/j2c" | "image/jaii" | "image/jais" | "image/jls" | "image/jp2" | "image/jpeg" | "image/jph" | "image/jphc" | "image/jpm" | "image/jpx" | "image/jxl" | "image/jxr" | "image/jxrA" | "image/jxrS" | "image/jxs" | "image/jxsc" | "image/jxsi" | "image/jxss" | "image/ktx" | "image/ktx2" | "image/naplps" | "image/png" | "image/prs.btif" | "image/prs.pti" | "image/pwg-raster" | "image/svg+xml" | "image/t38" | "image/tiff" | "image/tiff-fx" | "image/vnd.adobe.photoshop" | "image/vnd.airzip.accelerator.azv" | "image/vnd.blockfact.facti" | "image/vnd.clip" | "image/vnd.cns.inf2" | "image/vnd.dece.graphic" | "image/vnd.djvu" | "image/vnd.dvb.subtitle" | "image/vnd.dwg" | "image/vnd.dxf" | "image/vnd.fastbidsheet" | "image/vnd.fpx" | "image/vnd.fst" | "image/vnd.fujixerox.edmics-mmr" | "image/vnd.fujixerox.edmics-rlc" | "image/vnd.globalgraphics.pgb" | "image/vnd.microsoft.icon" | "image/vnd.mix" | "image/vnd.mozilla.apng" | "image/vnd.ms-modi" | "image/vnd.net-fpx" | "image/vnd.pco.b16" | "image/vnd.radiance" | "image/vnd.sealed.png" | "image/vnd.sealedmedia.softseal.gif" | "image/vnd.sealedmedia.softseal.jpg" | "image/vnd.svf" | "image/vnd.tencent.tap" | "image/vnd.valve.source.texture" | "image/vnd.wap.wbmp" | "image/vnd.xiff" | "image/vnd.zbrush.pcx" | "image/webp" | "image/wmf" | "image/x-emf - DEPRECATED in favor of image/emf" | "image/x-wmf - DEPRECATED in favor of image/wmf" | "message/CPIM" | "message/bhttp" | "message/delivery-status" | "message/disposition-notification" | "message/example" | "message/external-body" | "message/feedback-report" | "message/global" | "message/global-delivery-status" | "message/global-disposition-notification" | "message/global-headers" | "message/http" | "message/imdn+xml" | "message/mls" | "message/news (OBSOLETED by [RFC5537])" | "message/ohttp-req" | "message/ohttp-res" | "message/partial" | "message/rfc822" | "message/s-http (OBSOLETE)" | "message/sip" | "message/sipfrag" | "message/tracking-status" | "message/vnd.si.simp (OBSOLETED by request)" | "message/vnd.wfa.wsc" | "model/3mf" | "model/JT" | "model/e57" | "model/example" | "model/gltf+json" | "model/gltf-binary" | "model/iges" | "model/mesh" | "model/mtl" | "model/obj" | "model/prc" | "model/step" | "model/step+xml" | "model/step+zip" | "model/step-xml+zip" | "model/stl" | "model/u3d" | "model/vnd.bary" | "model/vnd.cld" | "model/vnd.collada+xml" | "model/vnd.dwf" | "model/vnd.flatland.3dml" | "model/vnd.gdl" | "model/vnd.gs-gdl" | "model/vnd.gtw" | "model/vnd.moml+xml" | "model/vnd.mts" | "model/vnd.opengex" | "model/vnd.parasolid.transmit.binary" | "model/vnd.parasolid.transmit.text" | "model/vnd.pytha.pyox" | "model/vnd.rosette.annotated-data-model" | "model/vnd.sap.vds" | "model/vnd.usda" | "model/vnd.usdz+zip" | "model/vnd.valve.source.compiled-map" | "model/vnd.vtu" | "model/vrml" | "model/x3d+fastinfoset" | "model/x3d+xml" | "model/x3d-vrml" | "multipart/alternative" | "multipart/appledouble" | "multipart/byteranges" | "multipart/digest" | "multipart/encrypted" | "multipart/example" | "multipart/form-data" | "multipart/header-set" | "multipart/mixed" | "multipart/multilingual" | "multipart/parallel" | "multipart/related" | "multipart/report" | "multipart/signed" | "multipart/vnd.bint.med-plus" | "multipart/voice-message" | "multipart/x-mixed-replace" | "text/1d-interleaved-parityfec" | "text/RED" | "text/SGML" | "text/cache-manifest" | "text/calendar" | "text/cql" | "text/cql-expression" | "text/cql-identifier" | "text/css" | "text/csv" | "text/csv-schema" | "text/directory - DEPRECATED by RFC6350" | "text/dns" | "text/ecmascript (OBSOLETED in favor of text/javascript)" | "text/encaprtp" | "text/enriched" | "text/example" | "text/fhirpath" | "text/flexfec" | "text/fwdred" | "text/gff3" | "text/grammar-ref-list" | "text/hl7v2" | "text/html" | "text/javascript" | "text/jcr-cnd" | "text/markdown" | "text/mizar" | "text/n3" | "text/parameters" | "text/parityfec" | "text/plain" | "text/provenance-notation" | "text/prs.fallenstein.rst" | "text/prs.lines.tag" | "text/prs.prop.logic" | "text/prs.texi" | "text/raptorfec" | "text/rfc822-headers" | "text/richtext" | "text/rtf" | "text/rtp-enc-aescm128" | "text/rtploopback" | "text/rtx" | "text/shaclc" | "text/shex" | "text/spdx" | "text/strings" | "text/t140" | "text/tab-separated-values" | "text/troff" | "text/turtle" | "text/ulpfec" | "text/uri-list" | "text/vcard" | "text/vnd.DMClientScript" | "text/vnd.IPTC.NITF" | "text/vnd.IPTC.NewsML" | "text/vnd.a" | "text/vnd.abc" | "text/vnd.ascii-art" | "text/vnd.curl" | "text/vnd.debian.copyright" | "text/vnd.dvb.subtitle" | "text/vnd.esmertec.theme-descriptor" | "text/vnd.exchangeable" | "text/vnd.familysearch.gedcom" | "text/vnd.ficlab.flt" | "text/vnd.fly" | "text/vnd.fmi.flexstor" | "text/vnd.gml" | "text/vnd.graphviz" | "text/vnd.hans" | "text/vnd.hgl" | "text/vnd.in3d.3dml" | "text/vnd.in3d.spot" | "text/vnd.latex-z" | "text/vnd.motorola.reflex" | "text/vnd.ms-mediapackage" | "text/vnd.net2phone.commcenter.command" | "text/vnd.radisys.msml-basic-layout" | "text/vnd.senx.warpscript" | "text/vnd.si.uricatalogue (OBSOLETED by request)" | "text/vnd.sosi" | "text/vnd.sun.j2me.app-descriptor" | "text/vnd.trolltech.linguist" | "text/vnd.typst" | "text/vnd.vcf" | "text/vnd.wap.si" | "text/vnd.wap.sl" | "text/vnd.wap.wml" | "text/vnd.wap.wmlscript" | "text/vnd.zoo.kcl" | "text/vtt" | "text/wgsl" | "text/xml" | "text/xml-external-parsed-entity" | "video/1d-interleaved-parityfec" | "video/3gpp" | "video/3gpp-tt" | "video/3gpp2" | "video/AV1" | "video/BMPEG" | "video/BT656" | "video/CelB" | "video/DV" | "video/FFV1" | "video/H261" | "video/H263" | "video/H263-1998" | "video/H263-2000" | "video/H264" | "video/H264-RCDO" | "video/H264-SVC" | "video/H265" | "video/H266" | "video/JPEG" | "video/MP1S" | "video/MP2P" | "video/MP2T" | "video/MP4V-ES" | "video/MPV" | "video/SMPTE292M" | "video/VP8" | "video/VP9" | "video/encaprtp" | "video/evc" | "video/example" | "video/flexfec" | "video/iso.segment" | "video/jpeg2000" | "video/jxsv" | "video/lottie+json" | "video/matroska" | "video/matroska-3d" | "video/mj2" | "video/mp4" | "video/mpeg" | "video/mpeg4-generic" | "video/nv" | "video/ogg" | "video/parityfec" | "video/pointer" | "video/quicktime" | "video/raptorfec" | "video/raw" | "video/rtp-enc-aescm128" | "video/rtploopback" | "video/rtx" | "video/scip" | "video/smpte291" | "video/ulpfec" | "video/vc1" | "video/vc2" | "video/vnd.CCTV" | "video/vnd.dece.hd" | "video/vnd.dece.mobile" | "video/vnd.dece.mp4" | "video/vnd.dece.pd" | "video/vnd.dece.sd" | "video/vnd.dece.video" | "video/vnd.directv.mpeg" | "video/vnd.directv.mpeg-tts" | "video/vnd.dlna.mpeg-tts" | "video/vnd.dvb.file" | "video/vnd.fvt" | "video/vnd.hns.video" | "video/vnd.iptvforum.1dparityfec-1010" | "video/vnd.iptvforum.1dparityfec-2005" | "video/vnd.iptvforum.2dparityfec-1010" | "video/vnd.iptvforum.2dparityfec-2005" | "video/vnd.iptvforum.ttsavc" | "video/vnd.iptvforum.ttsmpeg2" | "video/vnd.motorola.video" | "video/vnd.motorola.videop" | "video/vnd.mpegurl" | "video/vnd.ms-playready.media.pyv" | "video/vnd.nokia.interleaved-multimedia" | "video/vnd.nokia.mp4vr" | "video/vnd.nokia.videovoip" | "video/vnd.objectvideo" | "video/vnd.planar" | "video/vnd.radgamettools.bink" | "video/vnd.radgamettools.smacker" | "video/vnd.sealed.mpeg1" | "video/vnd.sealed.mpeg4" | "video/vnd.sealed.swf" | "video/vnd.sealedmedia.softseal.mov" | "video/vnd.uvvu.mp4" | "video/vnd.vivo" | "video/vnd.youtube.yt";
2
2
  /**
3
3
  * A content type that can be either one of the predefined `KnownContentType` values,
4
4
  * or any other custom string.
@@ -0,0 +1 @@
1
+ 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
  }>;
@@ -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};
@@ -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 = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rpc4next",
3
- "version": "0.3.9",
3
+ "version": "0.4.0",
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",
@@ -77,7 +77,7 @@
77
77
  "commander": "^13.1.0"
78
78
  },
79
79
  "devDependencies": {
80
- "@types/node": "^22.15.2",
80
+ "@types/node": "^22.15.3",
81
81
  "@vitest/coverage-v8": "^3.1.2",
82
82
  "@vitest/eslint-plugin": "^1.1.43",
83
83
  "@vitest/ui": "^3.1.2",
@@ -92,7 +92,7 @@
92
92
  "prettier": "^3.5.3",
93
93
  "ts-node": "^10.9.2",
94
94
  "typescript": "^5.8.3",
95
- "typescript-eslint": "^8.31.0",
95
+ "typescript-eslint": "^8.31.1",
96
96
  "vitest": "^3.1.2",
97
97
  "zod": "^3.24.3"
98
98
  },