@orpc/openapi 0.0.0-next.0a2672f → 0.0.0-next.0c8e57d

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.
@@ -0,0 +1,25 @@
1
+ import {
2
+ OpenAPIHandler
3
+ } from "./chunk-UG6W4GSA.js";
4
+
5
+ // src/adapters/fetch/openapi-handler-server.ts
6
+ import { TrieRouter } from "hono/router/trie-router";
7
+ var OpenAPIServerHandler = class extends OpenAPIHandler {
8
+ constructor(router, options) {
9
+ super(new TrieRouter(), router, options);
10
+ }
11
+ };
12
+
13
+ // src/adapters/fetch/openapi-handler-serverless.ts
14
+ import { LinearRouter } from "hono/router/linear-router";
15
+ var OpenAPIServerlessHandler = class extends OpenAPIHandler {
16
+ constructor(router, options) {
17
+ super(new LinearRouter(), router, options);
18
+ }
19
+ };
20
+
21
+ export {
22
+ OpenAPIServerHandler,
23
+ OpenAPIServerlessHandler
24
+ };
25
+ //# sourceMappingURL=chunk-GEDPF5HA.js.map
@@ -2,7 +2,7 @@ import {
2
2
  JSONSerializer,
3
3
  forEachContractProcedure,
4
4
  standardizeHTTPPath
5
- } from "./chunk-KNYXLM77.js";
5
+ } from "./chunk-V4HFPIEN.js";
6
6
 
7
7
  // src/adapters/fetch/bracket-notation.ts
8
8
  import { isPlainObject } from "@orpc/shared";
@@ -351,45 +351,58 @@ var OpenAPIPayloadCodec = class {
351
351
  };
352
352
  }
353
353
  async decode(re) {
354
- if (re instanceof Headers || re instanceof URLSearchParams || re instanceof FormData) {
355
- return deserialize([...re.entries()]);
356
- }
357
- const contentType = re.headers.get("content-type");
358
- const contentDisposition = re.headers.get("content-disposition");
359
- const fileName = contentDisposition ? cd.parse(contentDisposition).parameters.filename : void 0;
360
- if (fileName) {
361
- const blob2 = await re.blob();
362
- const file = new File([blob2], fileName, {
363
- type: blob2.type
364
- });
365
- return file;
366
- }
367
- if (!contentType || contentType.startsWith("application/json")) {
368
- if (!re.body) {
369
- return void 0;
354
+ try {
355
+ if (re instanceof Headers || re instanceof URLSearchParams || re instanceof FormData) {
356
+ return deserialize([...re.entries()]);
370
357
  }
371
- return await re.json();
372
- }
373
- if (contentType.startsWith("application/x-www-form-urlencoded")) {
374
- const params = new URLSearchParams(await re.text());
375
- return this.decode(params);
376
- }
377
- if (contentType.startsWith("text/")) {
378
- const text = await re.text();
379
- return text;
380
- }
381
- if (contentType.startsWith("multipart/form-data")) {
382
- const form = await re.formData();
383
- return this.decode(form);
358
+ const contentType = re.headers.get("content-type");
359
+ const contentDisposition = re.headers.get("content-disposition");
360
+ const fileName = contentDisposition ? cd.parse(contentDisposition).parameters.filename : void 0;
361
+ if (fileName) {
362
+ const blob2 = await re.blob();
363
+ const file = new File([blob2], fileName, {
364
+ type: blob2.type
365
+ });
366
+ return file;
367
+ }
368
+ if (!contentType || contentType.startsWith("application/json")) {
369
+ if (!re.body) {
370
+ return void 0;
371
+ }
372
+ const text = await re.text();
373
+ if (!text) {
374
+ return void 0;
375
+ }
376
+ return JSON.parse(text);
377
+ }
378
+ if (contentType.startsWith("application/x-www-form-urlencoded")) {
379
+ const params = new URLSearchParams(await re.text());
380
+ return this.decode(params);
381
+ }
382
+ if (contentType.startsWith("text/")) {
383
+ const text = await re.text();
384
+ return text;
385
+ }
386
+ if (contentType.startsWith("multipart/form-data")) {
387
+ const form = await re.formData();
388
+ return this.decode(form);
389
+ }
390
+ const blob = await re.blob();
391
+ return new File([blob], "blob", {
392
+ type: blob.type
393
+ });
394
+ } catch (e) {
395
+ throw new ORPCError({
396
+ code: "BAD_REQUEST",
397
+ message: "Cannot parse request/response. Please check the request/response body and Content-Type header.",
398
+ cause: e
399
+ });
384
400
  }
385
- const blob = await re.blob();
386
- return new File([blob], "blob", {
387
- type: blob.type
388
- });
389
401
  }
390
402
  };
391
403
 
392
404
  // src/adapters/fetch/openapi-procedure-matcher.ts
405
+ import { fallbackContractConfig } from "@orpc/contract";
393
406
  import { getLazyRouterPrefix, getRouterChild, isProcedure, unlazy } from "@orpc/server";
394
407
  import { mapValues } from "@orpc/shared";
395
408
  var OpenAPIProcedureMatcher = class {
@@ -434,7 +447,7 @@ var OpenAPIProcedureMatcher = class {
434
447
  }
435
448
  add(path, router) {
436
449
  const lazies = forEachContractProcedure({ path, router }, ({ path: path2, contract }) => {
437
- const method = contract["~orpc"].route?.method ?? "POST";
450
+ const method = fallbackContractConfig("defaultMethod", contract["~orpc"].route?.method);
438
451
  const httpPath = contract["~orpc"].route?.path ? this.convertOpenAPIPathToRouterPath(contract["~orpc"].route?.path) : `/${path2.map(encodeURIComponent).join("/")}`;
439
452
  this.hono.add(method, httpPath, [httpPath, path2]);
440
453
  });
@@ -473,8 +486,9 @@ var CompositeSchemaCoercer = class {
473
486
  };
474
487
 
475
488
  // src/adapters/fetch/openapi-handler.ts
489
+ import { fallbackContractConfig as fallbackContractConfig2 } from "@orpc/contract";
476
490
  import { createProcedureClient, ORPCError as ORPCError2 } from "@orpc/server";
477
- import { executeWithHooks, isPlainObject as isPlainObject3, ORPC_HANDLER_HEADER, trim } from "@orpc/shared";
491
+ import { executeWithHooks, isPlainObject as isPlainObject3, trim } from "@orpc/shared";
478
492
  var OpenAPIHandler = class {
479
493
  constructor(hono, router, options) {
480
494
  this.options = options;
@@ -490,13 +504,10 @@ var OpenAPIHandler = class {
490
504
  inputStructureCompact;
491
505
  inputStructureDetailed;
492
506
  compositeSchemaCoercer;
493
- condition(request) {
494
- return request.headers.get(ORPC_HANDLER_HEADER) === null;
495
- }
496
- async fetch(request, ...[options]) {
507
+ async handle(request, ...[options]) {
497
508
  const context = options?.context;
498
509
  const headers = request.headers;
499
- const accept = headers.get("Accept") || void 0;
510
+ const accept = headers.get("accept") || void 0;
500
511
  const execute = async () => {
501
512
  const url = new URL(request.url);
502
513
  const pathname = `/${trim(url.pathname.replace(options?.prefix ?? "", ""), "/")}`;
@@ -505,22 +516,22 @@ var OpenAPIHandler = class {
505
516
  const matchedMethod = customMethod || request.method;
506
517
  const matched = await this.procedureMatcher.match(matchedMethod, pathname);
507
518
  if (!matched) {
508
- throw new ORPCError2({ code: "NOT_FOUND", message: "Not found" });
519
+ return { matched: false, response: void 0 };
509
520
  }
510
521
  const contractDef = matched.procedure["~orpc"].contract["~orpc"];
511
522
  const input = await this.decodeInput(matched.procedure, matched.params, request);
512
523
  const coercedInput = this.compositeSchemaCoercer.coerce(contractDef.InputSchema, input);
513
- const client = createProcedureClient({
524
+ const client = createProcedureClient(matched.procedure, {
514
525
  context,
515
- procedure: matched.procedure,
516
526
  path: matched.path
517
527
  });
518
- const output = await client(coercedInput, { signal: options?.signal });
528
+ const output = await client(coercedInput, { signal: request.signal });
519
529
  const { body, headers: resHeaders } = this.encodeOutput(matched.procedure, output, accept);
520
- return new Response(body, {
530
+ const response = new Response(body, {
521
531
  headers: resHeaders,
522
- status: contractDef.route?.successStatus ?? 200
532
+ status: fallbackContractConfig2("defaultSuccessStatus", contractDef.route?.successStatus)
523
533
  });
534
+ return { matched: true, response };
524
535
  };
525
536
  try {
526
537
  return await executeWithHooks({
@@ -529,50 +540,50 @@ var OpenAPIHandler = class {
529
540
  input: request,
530
541
  hooks: this.options,
531
542
  meta: {
532
- signal: options?.signal
543
+ signal: request.signal
533
544
  }
534
545
  });
535
546
  } catch (e) {
536
547
  const error = this.convertToORPCError(e);
537
548
  try {
538
549
  const { body, headers: headers2 } = this.payloadCodec.encode(error.toJSON(), accept);
539
- return new Response(body, {
550
+ const response = new Response(body, {
540
551
  status: error.status,
541
552
  headers: headers2
542
553
  });
554
+ return { matched: true, response };
543
555
  } catch (e2) {
544
556
  const error2 = this.convertToORPCError(e2);
545
557
  const { body, headers: headers2 } = this.payloadCodec.encode(error2.toJSON(), void 0);
546
- return new Response(body, {
558
+ const response = new Response(body, {
547
559
  status: error2.status,
548
560
  headers: headers2
549
561
  });
562
+ return { matched: true, response };
550
563
  }
551
564
  }
552
565
  }
553
566
  async decodeInput(procedure, params, request) {
554
- const inputStructure = procedure["~orpc"].contract["~orpc"].route?.inputStructure;
567
+ const inputStructure = fallbackContractConfig2("defaultInputStructure", procedure["~orpc"].contract["~orpc"].route?.inputStructure);
555
568
  const url = new URL(request.url);
556
569
  const query = url.searchParams;
557
570
  const headers = request.headers;
558
- if (!inputStructure || inputStructure === "compact") {
571
+ if (inputStructure === "compact") {
559
572
  return this.inputStructureCompact.build(
560
573
  params,
561
574
  request.method === "GET" ? await this.payloadCodec.decode(query) : await this.payloadCodec.decode(request)
562
575
  );
563
576
  }
564
- const _expect = inputStructure;
565
577
  const decodedQuery = await this.payloadCodec.decode(query);
566
578
  const decodedHeaders = await this.payloadCodec.decode(headers);
567
579
  const decodedBody = await this.payloadCodec.decode(request);
568
580
  return this.inputStructureDetailed.build(params, decodedQuery, decodedHeaders, decodedBody);
569
581
  }
570
582
  encodeOutput(procedure, output, accept) {
571
- const outputStructure = procedure["~orpc"].contract["~orpc"].route?.outputStructure;
572
- if (!outputStructure || outputStructure === "compact") {
583
+ const outputStructure = fallbackContractConfig2("defaultOutputStructure", procedure["~orpc"].contract["~orpc"].route?.outputStructure);
584
+ if (outputStructure === "compact") {
573
585
  return this.payloadCodec.encode(output, accept);
574
586
  }
575
- const _expect = outputStructure;
576
587
  this.assertDetailedOutput(output);
577
588
  const headers = new Headers();
578
589
  if (output.headers) {
@@ -639,4 +650,4 @@ export {
639
650
  CompositeSchemaCoercer,
640
651
  OpenAPIHandler
641
652
  };
642
- //# sourceMappingURL=chunk-YXHH6XHB.js.map
653
+ //# sourceMappingURL=chunk-UG6W4GSA.js.map
@@ -104,4 +104,4 @@ export {
104
104
  forEachAllContractProcedure,
105
105
  standardizeHTTPPath
106
106
  };
107
- //# sourceMappingURL=chunk-KNYXLM77.js.map
107
+ //# sourceMappingURL=chunk-V4HFPIEN.js.map
package/dist/fetch.js CHANGED
@@ -1,3 +1,7 @@
1
+ import {
2
+ OpenAPIServerHandler,
3
+ OpenAPIServerlessHandler
4
+ } from "./chunk-GEDPF5HA.js";
1
5
  import {
2
6
  CompositeSchemaCoercer,
3
7
  InputStructureCompact,
@@ -10,24 +14,8 @@ import {
10
14
  parsePath,
11
15
  serialize,
12
16
  stringifyPath
13
- } from "./chunk-YXHH6XHB.js";
14
- import "./chunk-KNYXLM77.js";
15
-
16
- // src/adapters/fetch/openapi-handler-server.ts
17
- import { TrieRouter } from "hono/router/trie-router";
18
- var OpenAPIServerHandler = class extends OpenAPIHandler {
19
- constructor(router, options) {
20
- super(new TrieRouter(), router, options);
21
- }
22
- };
23
-
24
- // src/adapters/fetch/openapi-handler-serverless.ts
25
- import { LinearRouter } from "hono/router/linear-router";
26
- var OpenAPIServerlessHandler = class extends OpenAPIHandler {
27
- constructor(router, options) {
28
- super(new LinearRouter(), router, options);
29
- }
30
- };
17
+ } from "./chunk-UG6W4GSA.js";
18
+ import "./chunk-V4HFPIEN.js";
31
19
  export {
32
20
  CompositeSchemaCoercer,
33
21
  InputStructureCompact,
package/dist/hono.js ADDED
@@ -0,0 +1,34 @@
1
+ import {
2
+ OpenAPIServerHandler,
3
+ OpenAPIServerlessHandler
4
+ } from "./chunk-GEDPF5HA.js";
5
+ import {
6
+ CompositeSchemaCoercer,
7
+ InputStructureCompact,
8
+ InputStructureDetailed,
9
+ OpenAPIHandler,
10
+ OpenAPIPayloadCodec,
11
+ OpenAPIProcedureMatcher,
12
+ deserialize,
13
+ escapeSegment,
14
+ parsePath,
15
+ serialize,
16
+ stringifyPath
17
+ } from "./chunk-UG6W4GSA.js";
18
+ import "./chunk-V4HFPIEN.js";
19
+ export {
20
+ CompositeSchemaCoercer,
21
+ InputStructureCompact,
22
+ InputStructureDetailed,
23
+ OpenAPIHandler,
24
+ OpenAPIPayloadCodec,
25
+ OpenAPIProcedureMatcher,
26
+ OpenAPIServerHandler,
27
+ OpenAPIServerlessHandler,
28
+ deserialize,
29
+ escapeSegment,
30
+ parsePath,
31
+ serialize,
32
+ stringifyPath
33
+ };
34
+ //# sourceMappingURL=hono.js.map
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  forEachAllContractProcedure,
4
4
  forEachContractProcedure,
5
5
  standardizeHTTPPath
6
- } from "./chunk-KNYXLM77.js";
6
+ } from "./chunk-V4HFPIEN.js";
7
7
 
8
8
  // src/openapi.ts
9
9
  import { OpenApiBuilder } from "openapi3-ts/oas31";
@@ -35,11 +35,16 @@ var OpenAPIContentBuilder = class {
35
35
  }
36
36
  };
37
37
 
38
+ // src/openapi-generator.ts
39
+ import { fallbackContractConfig as fallbackContractConfig2, fallbackORPCErrorStatus } from "@orpc/contract";
40
+ import { group } from "@orpc/shared";
41
+
38
42
  // src/openapi-error.ts
39
43
  var OpenAPIError = class extends Error {
40
44
  };
41
45
 
42
46
  // src/openapi-input-structure-parser.ts
47
+ import { fallbackContractConfig } from "@orpc/contract";
43
48
  var OpenAPIInputStructureParser = class {
44
49
  constructor(schemaConverter, schemaUtils, pathParser) {
45
50
  this.schemaConverter = schemaConverter;
@@ -48,7 +53,7 @@ var OpenAPIInputStructureParser = class {
48
53
  }
49
54
  parse(contract, structure) {
50
55
  const inputSchema = this.schemaConverter.convert(contract["~orpc"].InputSchema, { strategy: "input" });
51
- const method = contract["~orpc"].route?.method ?? "POST";
56
+ const method = fallbackContractConfig("defaultMethod", contract["~orpc"].route?.method);
52
57
  const httpPath = contract["~orpc"].route?.path;
53
58
  if (this.schemaUtils.isAnySchema(inputSchema)) {
54
59
  return {
@@ -289,14 +294,14 @@ var SchemaUtils = class {
289
294
  return typeof schema === "object" && schema.type === "object";
290
295
  }
291
296
  isAnySchema(schema) {
292
- return schema === true || Object.keys(schema).length === 0;
297
+ return schema === true || Object.keys(schema).filter((key) => !NON_LOGIC_KEYWORDS.includes(key)).length === 0;
293
298
  }
294
299
  isUndefinableSchema(schema) {
295
300
  const [matches] = this.filterSchemaBranches(schema, (schema2) => {
296
301
  if (typeof schema2 === "boolean") {
297
302
  return schema2;
298
303
  }
299
- return Object.keys(schema2).length === 0;
304
+ return Object.keys(schema2).filter((key) => !NON_LOGIC_KEYWORDS.includes(key)).length === 0;
300
305
  });
301
306
  return matches.length > 0;
302
307
  }
@@ -380,6 +385,7 @@ var OpenAPIGenerator = class {
380
385
  errorHandlerStrategy;
381
386
  ignoreUndefinedPathProcedures;
382
387
  considerMissingTagDefinitionAsError;
388
+ strictErrorResponses;
383
389
  constructor(options) {
384
390
  this.parametersBuilder = options?.parametersBuilder ?? new OpenAPIParametersBuilder();
385
391
  this.schemaConverter = new CompositeSchemaConverter(options?.schemaConverters ?? []);
@@ -392,6 +398,7 @@ var OpenAPIGenerator = class {
392
398
  this.errorHandlerStrategy = options?.errorHandlerStrategy ?? "throw";
393
399
  this.ignoreUndefinedPathProcedures = options?.ignoreUndefinedPathProcedures ?? false;
394
400
  this.considerMissingTagDefinitionAsError = options?.considerMissingTagDefinitionAsError ?? false;
401
+ this.strictErrorResponses = options?.strictErrorResponses ?? true;
395
402
  }
396
403
  async generate(router, doc) {
397
404
  const builder = new OpenApiBuilder({
@@ -405,10 +412,12 @@ var OpenAPIGenerator = class {
405
412
  if (this.ignoreUndefinedPathProcedures && def.route?.path === void 0) {
406
413
  return;
407
414
  }
408
- const method = def.route?.method ?? "POST";
415
+ const method = fallbackContractConfig2("defaultMethod", def.route?.method);
409
416
  const httpPath = def.route?.path ? standardizeHTTPPath(def.route?.path) : `/${path.map(encodeURIComponent).join("/")}`;
410
- const { paramsSchema, querySchema, headersSchema, bodySchema } = this.inputStructureParser.parse(contract, def.route?.inputStructure ?? "compact");
411
- const { headersSchema: resHeadersSchema, bodySchema: resBodySchema } = this.outputStructureParser.parse(contract, def.route?.outputStructure ?? "compact");
417
+ const inputStructure = fallbackContractConfig2("defaultInputStructure", def.route?.inputStructure);
418
+ const outputStructure = fallbackContractConfig2("defaultOutputStructure", def.route?.outputStructure);
419
+ const { paramsSchema, querySchema, headersSchema, bodySchema } = this.inputStructureParser.parse(contract, inputStructure);
420
+ const { headersSchema: resHeadersSchema, bodySchema: resBodySchema } = this.outputStructureParser.parse(contract, outputStructure);
412
421
  const params = paramsSchema ? this.parametersBuilder.build("path", paramsSchema, {
413
422
  required: true
414
423
  }) : [];
@@ -419,8 +428,9 @@ var OpenAPIGenerator = class {
419
428
  required: this.schemaUtils.isUndefinableSchema(bodySchema),
420
429
  content: this.contentBuilder.build(bodySchema)
421
430
  } : void 0;
422
- const successResponse = {
423
- description: "OK",
431
+ const responses = {};
432
+ responses[fallbackContractConfig2("defaultSuccessStatus", def.route?.successStatus)] = {
433
+ description: fallbackContractConfig2("defaultSuccessDescription", def.route?.successDescription),
424
434
  content: resBodySchema !== void 0 ? this.contentBuilder.build(resBodySchema, {
425
435
  example: def.outputExample
426
436
  }) : void 0,
@@ -428,6 +438,58 @@ var OpenAPIGenerator = class {
428
438
  example: def.outputExample
429
439
  }) : void 0
430
440
  };
441
+ const errors = group(Object.entries(def.errorMap ?? {}).filter(([_, config]) => config).map(([code, config]) => ({
442
+ ...config,
443
+ code,
444
+ status: fallbackORPCErrorStatus(code, config?.status)
445
+ })), (error) => error.status);
446
+ for (const status in errors) {
447
+ const configs = errors[status];
448
+ if (!configs || configs.length === 0) {
449
+ continue;
450
+ }
451
+ const schemas = configs.map(({ data, code, message }) => {
452
+ const json = {
453
+ type: "object",
454
+ properties: {
455
+ defined: { const: true },
456
+ code: { const: code },
457
+ status: { const: Number(status) },
458
+ message: { type: "string", default: message },
459
+ data: {}
460
+ },
461
+ required: ["defined", "code", "status", "message"]
462
+ };
463
+ if (data) {
464
+ const dataJson = this.schemaConverter.convert(data, { strategy: "output" });
465
+ json.properties.data = dataJson;
466
+ if (!this.schemaUtils.isUndefinableSchema(dataJson)) {
467
+ json.required.push("data");
468
+ }
469
+ }
470
+ return json;
471
+ });
472
+ if (this.strictErrorResponses) {
473
+ schemas.push({
474
+ type: "object",
475
+ properties: {
476
+ defined: { const: false },
477
+ code: { type: "string" },
478
+ status: { type: "number" },
479
+ message: { type: "string" },
480
+ data: {}
481
+ },
482
+ required: ["defined", "code", "status", "message"]
483
+ });
484
+ }
485
+ const contentSchema = schemas.length === 1 ? schemas[0] : {
486
+ oneOf: schemas
487
+ };
488
+ responses[status] = {
489
+ description: status,
490
+ content: this.contentBuilder.build(contentSchema)
491
+ };
492
+ }
431
493
  if (this.considerMissingTagDefinitionAsError && def.route?.tags) {
432
494
  const missingTag = def.route?.tags.find((tag) => !rootTags.includes(tag));
433
495
  if (missingTag !== void 0) {
@@ -444,9 +506,7 @@ var OpenAPIGenerator = class {
444
506
  operationId: path.join("."),
445
507
  parameters: parameters.length ? parameters : void 0,
446
508
  requestBody,
447
- responses: {
448
- [def.route?.successStatus ?? 200]: successResponse
449
- }
509
+ responses
450
510
  };
451
511
  builder.addPath(httpPath, {
452
512
  [method.toLocaleLowerCase()]: operation
package/dist/next.js ADDED
@@ -0,0 +1,34 @@
1
+ import {
2
+ OpenAPIServerHandler,
3
+ OpenAPIServerlessHandler
4
+ } from "./chunk-GEDPF5HA.js";
5
+ import {
6
+ CompositeSchemaCoercer,
7
+ InputStructureCompact,
8
+ InputStructureDetailed,
9
+ OpenAPIHandler,
10
+ OpenAPIPayloadCodec,
11
+ OpenAPIProcedureMatcher,
12
+ deserialize,
13
+ escapeSegment,
14
+ parsePath,
15
+ serialize,
16
+ stringifyPath
17
+ } from "./chunk-UG6W4GSA.js";
18
+ import "./chunk-V4HFPIEN.js";
19
+ export {
20
+ CompositeSchemaCoercer,
21
+ InputStructureCompact,
22
+ InputStructureDetailed,
23
+ OpenAPIHandler,
24
+ OpenAPIPayloadCodec,
25
+ OpenAPIProcedureMatcher,
26
+ OpenAPIServerHandler,
27
+ OpenAPIServerlessHandler,
28
+ deserialize,
29
+ escapeSegment,
30
+ parsePath,
31
+ serialize,
32
+ stringifyPath
33
+ };
34
+ //# sourceMappingURL=next.js.map
package/dist/node.js CHANGED
@@ -1,25 +1,25 @@
1
1
  import {
2
2
  OpenAPIHandler
3
- } from "./chunk-YXHH6XHB.js";
4
- import "./chunk-KNYXLM77.js";
3
+ } from "./chunk-UG6W4GSA.js";
4
+ import "./chunk-V4HFPIEN.js";
5
5
 
6
6
  // src/adapters/node/openapi-handler.ts
7
- import { createRequest, sendResponse } from "@mjackson/node-fetch-server";
8
- import { ORPC_HANDLER_HEADER } from "@orpc/shared";
7
+ import { createRequest, sendResponse } from "@orpc/server/node";
9
8
  var OpenAPIHandler2 = class {
10
9
  openapiFetchHandler;
11
10
  constructor(hono, router, options) {
12
11
  this.openapiFetchHandler = new OpenAPIHandler(hono, router, options);
13
12
  }
14
- condition(request) {
15
- return request.headers[ORPC_HANDLER_HEADER] === void 0;
16
- }
17
13
  async handle(req, res, ...[options]) {
18
- const request = createRequest(req, res, options);
14
+ const request = createRequest(req, res);
19
15
  const castedOptions = options ?? {};
20
- const response = await this.openapiFetchHandler.fetch(request, castedOptions);
21
- await options?.beforeSend?.(response, castedOptions.context);
22
- return await sendResponse(res, response);
16
+ const result = await this.openapiFetchHandler.handle(request, castedOptions);
17
+ if (result.matched === false) {
18
+ return { matched: false };
19
+ }
20
+ await options?.beforeSend?.(result.response, castedOptions.context);
21
+ await sendResponse(res, result.response);
22
+ return { matched: true };
23
23
  }
24
24
  };
25
25
 
@@ -1,5 +1,5 @@
1
1
  import type { Context, Router, WithSignal } from '@orpc/server';
2
- import type { ConditionalFetchHandler, FetchOptions } from '@orpc/server/fetch';
2
+ import type { FetchHandler, FetchHandleRest, FetchHandleResult } from '@orpc/server/fetch';
3
3
  import type { PublicInputStructureCompact } from './input-structure-compact';
4
4
  import { type Hooks } from '@orpc/shared';
5
5
  import { type PublicJSONSerializer } from '../../json-serializer';
@@ -7,7 +7,7 @@ import { type PublicInputStructureDetailed } from './input-structure-detailed';
7
7
  import { type PublicOpenAPIPayloadCodec } from './openapi-payload-codec';
8
8
  import { type Hono, type PublicOpenAPIProcedureMatcher } from './openapi-procedure-matcher';
9
9
  import { type SchemaCoercer } from './schema-coercer';
10
- export type OpenAPIHandlerOptions<T extends Context> = Hooks<Request, Response, T, WithSignal> & {
10
+ export type OpenAPIHandlerOptions<T extends Context> = Hooks<Request, FetchHandleResult, T, WithSignal> & {
11
11
  jsonSerializer?: PublicJSONSerializer;
12
12
  procedureMatcher?: PublicOpenAPIProcedureMatcher;
13
13
  payloadCodec?: PublicOpenAPIPayloadCodec;
@@ -15,7 +15,7 @@ export type OpenAPIHandlerOptions<T extends Context> = Hooks<Request, Response,
15
15
  inputBuilderFull?: PublicInputStructureDetailed;
16
16
  schemaCoercers?: SchemaCoercer[];
17
17
  };
18
- export declare class OpenAPIHandler<T extends Context> implements ConditionalFetchHandler<T> {
18
+ export declare class OpenAPIHandler<T extends Context> implements FetchHandler<T> {
19
19
  private readonly options?;
20
20
  private readonly procedureMatcher;
21
21
  private readonly payloadCodec;
@@ -23,8 +23,7 @@ export declare class OpenAPIHandler<T extends Context> implements ConditionalFet
23
23
  private readonly inputStructureDetailed;
24
24
  private readonly compositeSchemaCoercer;
25
25
  constructor(hono: Hono, router: Router<T, any>, options?: NoInfer<OpenAPIHandlerOptions<T>> | undefined);
26
- condition(request: Request): boolean;
27
- fetch(request: Request, ...[options]: [options: FetchOptions<T>] | (undefined extends T ? [] : never)): Promise<Response>;
26
+ handle(request: Request, ...[options]: FetchHandleRest<T>): Promise<FetchHandleResult>;
28
27
  private decodeInput;
29
28
  private encodeOutput;
30
29
  private assertDetailedOutput;
@@ -0,0 +1,2 @@
1
+ export * from '../fetch';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ export * from '../fetch';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -1,12 +1,11 @@
1
1
  import type { Context, Router } from '@orpc/server';
2
- import type { ConditionalRequestHandler, RequestOptions } from '@orpc/server/node';
3
2
  import type { IncomingMessage, ServerResponse } from 'node:http';
4
3
  import type { OpenAPIHandlerOptions } from '../fetch/openapi-handler';
5
4
  import type { Hono } from '../fetch/openapi-procedure-matcher';
6
- export declare class OpenAPIHandler<T extends Context> implements ConditionalRequestHandler<T> {
5
+ import { type RequestHandler, type RequestHandleRest, type RequestHandleResult } from '@orpc/server/node';
6
+ export declare class OpenAPIHandler<T extends Context> implements RequestHandler<T> {
7
7
  private readonly openapiFetchHandler;
8
8
  constructor(hono: Hono, router: Router<T, any>, options?: NoInfer<OpenAPIHandlerOptions<T>>);
9
- condition(request: IncomingMessage): boolean;
10
- handle(req: IncomingMessage, res: ServerResponse, ...[options]: [options: RequestOptions<T>] | (undefined extends T ? [] : never)): Promise<void>;
9
+ handle(req: IncomingMessage, res: ServerResponse, ...[options]: RequestHandleRest<T>): Promise<RequestHandleResult>;
11
10
  }
12
11
  //# sourceMappingURL=openapi-handler.d.ts.map
@@ -1,9 +1,9 @@
1
- import type { ContractRouter } from '@orpc/contract';
2
1
  import type { ANY_ROUTER } from '@orpc/server';
3
2
  import type { PublicOpenAPIInputStructureParser } from './openapi-input-structure-parser';
4
3
  import type { PublicOpenAPIOutputStructureParser } from './openapi-output-structure-parser';
5
4
  import type { PublicOpenAPIPathParser } from './openapi-path-parser';
6
5
  import type { SchemaConverter } from './schema-converter';
6
+ import { type ContractRouter } from '@orpc/contract';
7
7
  import { type PublicJSONSerializer } from './json-serializer';
8
8
  import { type OpenAPI } from './openapi';
9
9
  import { type PublicOpenAPIContentBuilder } from './openapi-content-builder';
@@ -40,6 +40,12 @@ export interface OpenAPIGeneratorOptions {
40
40
  * @default 'throw'
41
41
  */
42
42
  errorHandlerStrategy?: ErrorHandlerStrategy;
43
+ /**
44
+ * Strict error response
45
+ *
46
+ * @default true
47
+ */
48
+ strictErrorResponses?: boolean;
43
49
  }
44
50
  export declare class OpenAPIGenerator {
45
51
  private readonly contentBuilder;
@@ -53,8 +59,9 @@ export declare class OpenAPIGenerator {
53
59
  private readonly errorHandlerStrategy;
54
60
  private readonly ignoreUndefinedPathProcedures;
55
61
  private readonly considerMissingTagDefinitionAsError;
62
+ private readonly strictErrorResponses;
56
63
  constructor(options?: OpenAPIGeneratorOptions);
57
- generate(router: ContractRouter | ANY_ROUTER, doc: Omit<OpenAPI.OpenAPIObject, 'openapi'>): Promise<OpenAPI.OpenAPIObject>;
64
+ generate(router: ContractRouter<any> | ANY_ROUTER, doc: Omit<OpenAPI.OpenAPIObject, 'openapi'>): Promise<OpenAPI.OpenAPIObject>;
58
65
  }
59
66
  export {};
60
67
  //# sourceMappingURL=openapi-generator.d.ts.map
@@ -1,8 +1,8 @@
1
- import type { ANY_CONTRACT_PROCEDURE } from '@orpc/contract';
2
1
  import type { PublicOpenAPIPathParser } from './openapi-path-parser';
3
2
  import type { JSONSchema, ObjectSchema } from './schema';
4
3
  import type { SchemaConverter } from './schema-converter';
5
4
  import type { PublicSchemaUtils } from './schema-utils';
5
+ import { type ANY_CONTRACT_PROCEDURE } from '@orpc/contract';
6
6
  export interface OpenAPIInputStructureParseResult {
7
7
  paramsSchema: ObjectSchema | undefined;
8
8
  querySchema: ObjectSchema | undefined;
@@ -8,5 +8,5 @@ export type FileSchema = JSONSchema.JSONSchema & {
8
8
  type: 'string';
9
9
  contentMediaType: string;
10
10
  } & object;
11
- export declare const NON_LOGIC_KEYWORDS: ("$anchor" | "$comment" | "$defs" | "$dynamicAnchor" | "$dynamicRef" | "$id" | "$schema" | "$vocabulary" | "contentEncoding" | "contentMediaType" | "default" | "definitions" | "deprecated" | "description" | "examples" | "format" | "readOnly" | "title" | "writeOnly")[];
11
+ export declare const NON_LOGIC_KEYWORDS: string[];
12
12
  //# sourceMappingURL=schema.d.ts.map
@@ -1,7 +1,7 @@
1
1
  import type { ContractRouter, HTTPPath, WELL_CONTRACT_PROCEDURE } from '@orpc/contract';
2
2
  import type { ANY_PROCEDURE, ANY_ROUTER, Lazy } from '@orpc/server';
3
3
  export interface EachLeafOptions {
4
- router: ContractRouter | ANY_ROUTER;
4
+ router: ContractRouter<any> | ANY_ROUTER;
5
5
  path: string[];
6
6
  }
7
7
  export interface EachLeafCallbackOptions {
@@ -13,6 +13,6 @@ export interface EachContractLeafResultItem {
13
13
  path: string[];
14
14
  }
15
15
  export declare function forEachContractProcedure(options: EachLeafOptions, callback: (options: EachLeafCallbackOptions) => void, result?: EachContractLeafResultItem[], isCurrentRouterContract?: boolean): EachContractLeafResultItem[];
16
- export declare function forEachAllContractProcedure(router: ContractRouter | ANY_ROUTER, callback: (options: EachLeafCallbackOptions) => void): Promise<void>;
16
+ export declare function forEachAllContractProcedure(router: ContractRouter<any> | ANY_ROUTER, callback: (options: EachLeafCallbackOptions) => void): Promise<void>;
17
17
  export declare function standardizeHTTPPath(path: HTTPPath): HTTPPath;
18
18
  //# sourceMappingURL=utils.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/openapi",
3
3
  "type": "module",
4
- "version": "0.0.0-next.0a2672f",
4
+ "version": "0.0.0-next.0c8e57d",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.unnoq.com",
7
7
  "repository": {
@@ -24,6 +24,16 @@
24
24
  "import": "./dist/fetch.js",
25
25
  "default": "./dist/fetch.js"
26
26
  },
27
+ "./hono": {
28
+ "types": "./dist/src/adapters/hono/index.d.ts",
29
+ "import": "./dist/hono.js",
30
+ "default": "./dist/hono.js"
31
+ },
32
+ "./next": {
33
+ "types": "./dist/src/adapters/next/index.d.ts",
34
+ "import": "./dist/next.js",
35
+ "default": "./dist/next.js"
36
+ },
27
37
  "./node": {
28
38
  "types": "./dist/src/adapters/node/index.d.ts",
29
39
  "import": "./dist/node.js",
@@ -39,7 +49,6 @@
39
49
  "dist"
40
50
  ],
41
51
  "dependencies": {
42
- "@mjackson/node-fetch-server": "^0.5.0",
43
52
  "@standard-schema/spec": "1.0.0-beta.4",
44
53
  "@types/content-disposition": "^0.5.8",
45
54
  "content-disposition": "^0.5.4",
@@ -49,16 +58,16 @@
49
58
  "json-schema-typed": "^8.0.1",
50
59
  "openapi3-ts": "^4.4.0",
51
60
  "wildcard-match": "^5.1.3",
52
- "@orpc/contract": "0.0.0-next.0a2672f",
53
- "@orpc/server": "0.0.0-next.0a2672f",
54
- "@orpc/shared": "0.0.0-next.0a2672f"
61
+ "@orpc/contract": "0.0.0-next.0c8e57d",
62
+ "@orpc/server": "0.0.0-next.0c8e57d",
63
+ "@orpc/shared": "0.0.0-next.0c8e57d"
55
64
  },
56
65
  "devDependencies": {
57
66
  "@readme/openapi-parser": "^2.6.0",
58
67
  "zod": "^3.24.1"
59
68
  },
60
69
  "scripts": {
61
- "build": "tsup --clean --sourcemap --entry.index=src/index.ts --entry.fetch=src/adapters/fetch/index.ts --entry.node=src/adapters/node/index.ts --format=esm --onSuccess='tsc -b --noCheck'",
70
+ "build": "tsup --onSuccess='tsc -b --noCheck'",
62
71
  "build:watch": "pnpm run build --watch",
63
72
  "type:check": "tsc -b"
64
73
  }