@temporary-name/server 1.9.3-alpha.f9f5ce625d5edee78250b87b3a64f1d9760c2244 → 1.9.3-alpha.fb7e3a67f82deaeffad5063e136b2f3c03c4b5b3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/adapters/aws-lambda/index.d.mts +5 -6
  2. package/dist/adapters/aws-lambda/index.d.ts +5 -6
  3. package/dist/adapters/aws-lambda/index.mjs +5 -6
  4. package/dist/adapters/fetch/index.d.mts +8 -85
  5. package/dist/adapters/fetch/index.d.ts +8 -85
  6. package/dist/adapters/fetch/index.mjs +17 -157
  7. package/dist/adapters/node/index.d.mts +9 -63
  8. package/dist/adapters/node/index.d.ts +9 -63
  9. package/dist/adapters/node/index.mjs +15 -122
  10. package/dist/handler/index.d.mts +28 -0
  11. package/dist/handler/index.d.ts +28 -0
  12. package/dist/handler/index.mjs +8 -0
  13. package/dist/helpers/index.mjs +3 -29
  14. package/dist/index.d.mts +356 -206
  15. package/dist/index.d.ts +356 -206
  16. package/dist/index.mjs +466 -163
  17. package/dist/openapi/index.d.mts +18 -53
  18. package/dist/openapi/index.d.ts +18 -53
  19. package/dist/openapi/index.mjs +391 -368
  20. package/dist/shared/server.-tR-4rQ5.mjs +523 -0
  21. package/dist/shared/server.BwcJq6aP.d.mts +808 -0
  22. package/dist/shared/server.BwcJq6aP.d.ts +808 -0
  23. package/dist/shared/server.C1RJffw4.mjs +30 -0
  24. package/dist/shared/server.CjPiuQYH.d.mts +51 -0
  25. package/dist/shared/server.CjPiuQYH.d.ts +51 -0
  26. package/dist/shared/server.D2NXNHIf.mjs +156 -0
  27. package/dist/shared/server.Deg5phAY.d.ts +39 -0
  28. package/dist/shared/server.DvgWQUGK.mjs +496 -0
  29. package/dist/shared/server.hAH-LVh_.d.mts +39 -0
  30. package/dist/shared/server.n1y5fcVQ.mjs +315 -0
  31. package/package.json +13 -31
  32. package/dist/adapters/standard/index.d.mts +0 -30
  33. package/dist/adapters/standard/index.d.ts +0 -30
  34. package/dist/adapters/standard/index.mjs +0 -9
  35. package/dist/plugins/index.d.mts +0 -84
  36. package/dist/plugins/index.d.ts +0 -84
  37. package/dist/plugins/index.mjs +0 -122
  38. package/dist/shared/server.7aL9gcoU.d.mts +0 -23
  39. package/dist/shared/server.BL2R5jcp.d.mts +0 -228
  40. package/dist/shared/server.BL2R5jcp.d.ts +0 -228
  41. package/dist/shared/server.CVBLzkro.mjs +0 -255
  42. package/dist/shared/server.ClhVCxfg.mjs +0 -413
  43. package/dist/shared/server.D6Qs_UcF.d.mts +0 -55
  44. package/dist/shared/server.DFptr1Nz.d.ts +0 -23
  45. package/dist/shared/server.DpoO_ER_.d.ts +0 -55
  46. package/dist/shared/server.JtIZ8YG7.mjs +0 -237
@@ -1,10 +1,12 @@
1
- import { isProcedure, resolveContractProcedures, ORPCError, createRouterClient } from '@temporary-name/server';
2
- import { standardizeHTTPPath, fallbackContractConfig, getDynamicParams, getEventIteratorSchemaDetails } from '@temporary-name/contract';
3
- import { isObject, stringifyJSON, findDeepMatches, toArray, clone, value, toHttpPath, isORPCErrorStatus, fallbackORPCErrorStatus, fallbackORPCErrorMessage, resolveMaybeOptionalOptions, createORPCErrorFromJson } from '@temporary-name/shared';
4
- import { j as jsonSerialize, d as deserialize, s as serialize } from '../shared/server.JtIZ8YG7.mjs';
5
- import '@temporary-name/standard-server';
1
+ import { isObject, stringifyJSON, findDeepMatches, clone, value, fallbackContractConfig, toHttpPath, assertNever } from '@temporary-name/shared';
2
+ import * as z from '@temporary-name/zod';
3
+ import { s as standardizeHTTPPath, r as resolveContractProcedures, g as getDynamicParams, i as isAPIErrorStatus } from '../shared/server.DvgWQUGK.mjs';
4
+ import { Z as ZodToJsonSchemaConverter, g as getEventIteratorSchemaDetails } from '../shared/server.-tR-4rQ5.mjs';
6
5
  import { TypeName } from '@temporary-name/interop/json-schema-typed/draft-2020-12';
7
6
  export { ContentEncoding as JSONSchemaContentEncoding, Format as JSONSchemaFormat, TypeName as JSONSchemaTypeName } from '@temporary-name/interop/json-schema-typed/draft-2020-12';
7
+ import '@temporary-name/standard-server';
8
+ import '@temporary-name/server/openapi';
9
+ import 'zod/v4/core';
8
10
 
9
11
  const OPERATION_EXTENDER_SYMBOL = Symbol("ORPC_OPERATION_EXTENDER");
10
12
  function customOpenAPIOperation(o, extend) {
@@ -22,20 +24,12 @@ function getCustomOpenAPIOperation(o) {
22
24
  }
23
25
  function applyCustomOpenAPIOperation(operation, contract) {
24
26
  const operationCustoms = [];
25
- for (const errorItem of Object.values(contract["~orpc"].errorMap)) {
26
- const maybeExtender = errorItem ? getCustomOpenAPIOperation(errorItem) : void 0;
27
+ for (const middleware of contract["~orpc"].middlewares) {
28
+ const maybeExtender = getCustomOpenAPIOperation(middleware);
27
29
  if (maybeExtender) {
28
30
  operationCustoms.push(maybeExtender);
29
31
  }
30
32
  }
31
- if (isProcedure(contract)) {
32
- for (const middleware of contract["~orpc"].middlewares) {
33
- const maybeExtender = getCustomOpenAPIOperation(middleware);
34
- if (maybeExtender) {
35
- operationCustoms.push(maybeExtender);
36
- }
37
- }
38
- }
39
33
  let currentOperation = operation;
40
34
  for (const custom of operationCustoms) {
41
35
  if (typeof custom === "function") {
@@ -362,398 +356,427 @@ function resolveOpenAPIJsonSchemaRef(doc, schema) {
362
356
  return resolved ?? schema;
363
357
  }
364
358
 
365
- class CompositeSchemaConverter {
366
- converters;
367
- constructor(converters) {
368
- this.converters = converters;
369
- }
370
- async convert(schema, options) {
371
- for (const converter of this.converters) {
372
- if (await converter.condition(schema, options)) {
373
- return converter.convert(schema, options);
374
- }
375
- }
376
- return [false, {}];
377
- }
378
- }
379
-
380
359
  class OpenAPIGeneratorError extends Error {
381
360
  }
382
- class OpenAPIGenerator {
383
- converter;
384
- constructor(options = {}) {
385
- this.converter = new CompositeSchemaConverter(toArray(options.schemaConverters));
386
- }
387
- /**
388
- * Generates OpenAPI specifications from oRPC routers/contracts.
389
- *
390
- * @see {@link https://orpc.unnoq.com/docs/openapi/openapi-specification OpenAPI Specification Docs}
391
- */
392
- async generate(router, options = {}) {
393
- const filter = options.filter ?? (({ contract, path }) => {
394
- return !(options.exclude?.(contract, path) ?? false);
395
- });
396
- const doc = {
397
- ...clone(options),
398
- info: options.info ?? { title: "API Reference", version: "0.0.0" },
399
- openapi: "3.1.1",
400
- exclude: void 0,
401
- filter: void 0,
402
- commonSchemas: void 0
403
- };
404
- const { baseSchemaConvertOptions, undefinedErrorJsonSchema } = await this.#resolveCommonSchemas(
405
- doc,
406
- options.commonSchemas
407
- );
408
- const contracts = [];
409
- await resolveContractProcedures({ path: [], router }, (traverseOptions) => {
410
- if (!value(filter, traverseOptions)) {
411
- return;
361
+ async function generateOpenApiSpec(router, options = {}) {
362
+ const converter = typeof options.schemaConverter === "function" ? options.schemaConverter : new ZodToJsonSchemaConverter(options.schemaConverter ?? {}).convert;
363
+ const filter = options.filter ?? (({ contract, path }) => {
364
+ return !(options.exclude?.(contract, path) ?? false);
365
+ });
366
+ const doc = {
367
+ ...clone(options.spec),
368
+ info: options.spec?.info ?? { title: "API Reference", version: "0.0.0" },
369
+ openapi: "3.1.1"
370
+ };
371
+ const { baseSchemaConvertOptions } = await resolveCommonSchemas(doc, options.commonSchemas, converter);
372
+ const contracts = [];
373
+ await resolveContractProcedures({ path: [], router }, (traverseOptions) => {
374
+ if (!value(filter, traverseOptions)) {
375
+ return;
376
+ }
377
+ contracts.push(traverseOptions);
378
+ });
379
+ const namesByAuthConfig = /* @__PURE__ */ new Map();
380
+ const authConfigNames = /* @__PURE__ */ new Set();
381
+ for (const { contract } of contracts) {
382
+ for (const authConfig of contract["~orpc"].authConfigs) {
383
+ if (authConfig.type === "none" || namesByAuthConfig.has(authConfig)) {
384
+ continue;
412
385
  }
413
- contracts.push(traverseOptions);
414
- });
415
- const errors = [];
416
- for (const { contract, path } of contracts) {
417
- const stringPath = path.join(".");
418
- try {
419
- const def = contract["~orpc"];
420
- const method = toOpenAPIMethod(fallbackContractConfig("defaultMethod", def.route.method));
421
- const httpPath = toOpenAPIPath(def.route.path ?? toHttpPath(path));
422
- let operationObjectRef;
423
- if (def.route.spec !== void 0 && typeof def.route.spec !== "function") {
424
- operationObjectRef = def.route.spec;
425
- } else {
426
- operationObjectRef = {
427
- operationId: def.route.operationId ?? stringPath,
428
- summary: def.route.summary,
429
- description: def.route.description,
430
- deprecated: def.route.deprecated,
431
- tags: def.route.tags?.map((tag) => tag)
432
- };
433
- await this.#request(doc, operationObjectRef, def, baseSchemaConvertOptions);
434
- await this.#successResponse(doc, operationObjectRef, def, baseSchemaConvertOptions);
435
- await this.#errorResponse(
436
- operationObjectRef,
437
- def,
438
- baseSchemaConvertOptions,
439
- undefinedErrorJsonSchema
440
- );
441
- }
442
- if (typeof def.route.spec === "function") {
443
- operationObjectRef = def.route.spec(operationObjectRef);
444
- }
445
- doc.paths ??= {};
446
- doc.paths[httpPath] ??= {};
447
- doc.paths[httpPath][method] = applyCustomOpenAPIOperation(operationObjectRef, contract);
448
- } catch (e) {
449
- if (!(e instanceof OpenAPIGeneratorError)) {
450
- throw e;
451
- }
452
- errors.push(
453
- `[OpenAPIGenerator] Error occurred while generating OpenAPI for procedure at path: ${stringPath}
454
- ${e.message}`
455
- );
386
+ const oasNameBase = authConfig.oasName ?? `${authConfig.type}Auth`;
387
+ let oasName = oasNameBase;
388
+ for (let i = 2; authConfigNames.has(oasName); i++) {
389
+ oasName = `${oasNameBase}${i}`;
456
390
  }
391
+ namesByAuthConfig.set(authConfig, oasName);
392
+ authConfigNames.add(oasName);
457
393
  }
458
- if (errors.length) {
459
- throw new OpenAPIGeneratorError(
460
- `Some error occurred during OpenAPI generation:
461
-
462
- ${errors.join("\n\n")}`
463
- );
394
+ }
395
+ if (namesByAuthConfig.size > 0) {
396
+ doc.components ??= {};
397
+ const schemes = doc.components.securitySchemes ??= {};
398
+ for (const [authConfig, name] of namesByAuthConfig) {
399
+ schemes[name] ??= authConfigToSecurityScheme(authConfig);
464
400
  }
465
- return jsonSerialize(doc)[0];
466
401
  }
467
- async #resolveCommonSchemas(doc, commonSchemas) {
468
- let undefinedErrorJsonSchema = {
469
- type: "object",
470
- properties: {
471
- defined: { const: false },
472
- code: { type: "string" },
473
- status: { type: "number" },
474
- message: { type: "string" },
475
- data: {}
476
- },
477
- required: ["defined", "code", "status", "message"]
478
- };
479
- const baseSchemaConvertOptions = {};
480
- if (commonSchemas) {
481
- baseSchemaConvertOptions.components = [];
482
- for (const key in commonSchemas) {
483
- const options = commonSchemas[key];
484
- if (options.schema === void 0) {
485
- continue;
486
- }
487
- const { schema, strategy = "input" } = options;
488
- const [required, json] = await this.converter.convert(schema, { strategy });
489
- const allowedStrategies = [strategy];
490
- if (strategy === "input") {
491
- const [outputRequired, outputJson] = await this.converter.convert(schema, { strategy: "output" });
492
- if (outputRequired === required && stringifyJSON(outputJson) === stringifyJSON(json)) {
493
- allowedStrategies.push("output");
494
- }
495
- } else if (strategy === "output") {
496
- const [inputRequired, inputJson] = await this.converter.convert(schema, { strategy: "input" });
497
- if (inputRequired === required && stringifyJSON(inputJson) === stringifyJSON(json)) {
498
- allowedStrategies.push("input");
499
- }
402
+ const errors = [];
403
+ for (const { contract, path } of contracts) {
404
+ const stringPath = path.join(".");
405
+ try {
406
+ const def = contract["~orpc"];
407
+ const method = toOpenAPIMethod(fallbackContractConfig("defaultMethod", def.route.method));
408
+ const httpPath = toOpenAPIPath(def.route.path ?? toHttpPath(path));
409
+ let operationObjectRef;
410
+ if (def.route.spec !== void 0 && typeof def.route.spec !== "function") {
411
+ operationObjectRef = def.route.spec;
412
+ } else {
413
+ operationObjectRef = {
414
+ operationId: def.route.operationId ?? stringPath,
415
+ summary: def.route.summary,
416
+ description: def.route.description,
417
+ deprecated: def.route.deprecated,
418
+ tags: def.route.tags?.map((tag) => tag)
419
+ };
420
+ const security = def.authConfigs.map(
421
+ (authConfig) => authConfig.type === "none" ? {} : { [namesByAuthConfig.get(authConfig)]: [] }
422
+ );
423
+ if (security.length > 0) {
424
+ operationObjectRef.security = security;
500
425
  }
501
- baseSchemaConvertOptions.components.push({
502
- schema,
503
- required,
504
- ref: `#/components/schemas/${key}`,
505
- allowedStrategies
506
- });
426
+ await handleRequest(doc, operationObjectRef, def, baseSchemaConvertOptions, converter);
427
+ await handleSuccessResponse(doc, operationObjectRef, def, baseSchemaConvertOptions, converter);
428
+ await handleErrorResponse(doc, operationObjectRef, def, baseSchemaConvertOptions, converter);
507
429
  }
508
- doc.components ??= {};
509
- doc.components.schemas ??= {};
510
- for (const key in commonSchemas) {
511
- const options = commonSchemas[key];
512
- if (options.schema === void 0) {
513
- if (options.error === "UndefinedError") {
514
- doc.components.schemas[key] = toOpenAPISchema(undefinedErrorJsonSchema);
515
- undefinedErrorJsonSchema = { $ref: `#/components/schemas/${key}` };
516
- }
517
- continue;
518
- }
519
- const { schema, strategy = "input" } = options;
520
- const [, json] = await this.converter.convert(schema, {
521
- ...baseSchemaConvertOptions,
522
- strategy,
523
- minStructureDepthForRef: 1
524
- // not allow use $ref for root schemas
525
- });
526
- doc.components.schemas[key] = toOpenAPISchema(json);
430
+ if (typeof def.route.spec === "function") {
431
+ operationObjectRef = def.route.spec(operationObjectRef);
527
432
  }
433
+ doc.paths ??= {};
434
+ doc.paths[httpPath] ??= {};
435
+ doc.paths[httpPath][method] = applyCustomOpenAPIOperation(operationObjectRef, contract);
436
+ } catch (e) {
437
+ if (!(e instanceof OpenAPIGeneratorError)) {
438
+ throw e;
439
+ }
440
+ errors.push(
441
+ `[OpenAPIGenerator] Error occurred while generating OpenAPI for procedure at path: ${stringPath}
442
+ ${e.message}`
443
+ );
528
444
  }
529
- return { baseSchemaConvertOptions, undefinedErrorJsonSchema };
530
445
  }
531
- async #request(doc, ref, def, baseSchemaConvertOptions) {
532
- const method = fallbackContractConfig("defaultMethod", def.route.method);
533
- const dynamicParams = getDynamicParams(def.route.path)?.map((v) => v.name);
534
- const [_pathRequired, pathSchema] = await this.converter.convert(def.schemas.pathSchema, {
535
- ...baseSchemaConvertOptions,
536
- strategy: "input",
537
- minStructureDepthForRef: 1
538
- });
539
- if (dynamicParams?.length) {
540
- const error = new OpenAPIGeneratorError(
541
- // TODO: fix this error
542
- 'When input structure is "compact", and path has dynamic params, input schema must be an object with all dynamic params as required.'
543
- );
544
- if (!isObjectSchema(pathSchema)) {
545
- throw error;
546
- }
547
- if (!checkParamsSchema(pathSchema, dynamicParams)) {
548
- throw error;
549
- }
550
- ref.parameters ??= [];
551
- ref.parameters.push(...toOpenAPIParameters(pathSchema, "path"));
552
- } else {
553
- const error = new OpenAPIGeneratorError("Params set via path do not match those on the route");
554
- if (!isObjectSchema(pathSchema)) {
555
- console.log("FOO", pathSchema);
556
- throw error;
446
+ if (errors.length) {
447
+ throw new OpenAPIGeneratorError(
448
+ `Some error occurred during OpenAPI generation:
449
+
450
+ ${errors.join("\n\n")}`
451
+ );
452
+ }
453
+ return doc;
454
+ }
455
+ async function resolveCommonSchemas(doc, commonSchemas, converter) {
456
+ let undefinedErrorJsonSchema = {
457
+ type: "object",
458
+ properties: {
459
+ code: { type: "string" },
460
+ status: { type: "number" },
461
+ message: { type: "string" },
462
+ data: {}
463
+ },
464
+ required: ["code", "status", "message"]
465
+ };
466
+ const baseSchemaConvertOptions = {};
467
+ if (commonSchemas) {
468
+ baseSchemaConvertOptions.components = [];
469
+ for (const key in commonSchemas) {
470
+ const options = commonSchemas[key];
471
+ if (options.schema === void 0) {
472
+ continue;
557
473
  }
558
- if (!checkParamsSchema(pathSchema, [])) {
559
- console.log("BAR", pathSchema);
560
- throw error;
474
+ const { schema, strategy = "input" } = options;
475
+ const [required, json] = await converter(schema, { strategy });
476
+ const allowedStrategies = [strategy];
477
+ if (strategy === "input") {
478
+ const [outputRequired, outputJson] = await converter(schema, { strategy: "output" });
479
+ if (outputRequired === required && stringifyJSON(outputJson) === stringifyJSON(json)) {
480
+ allowedStrategies.push("output");
481
+ }
482
+ } else if (strategy === "output") {
483
+ const [inputRequired, inputJson] = await converter(schema, { strategy: "input" });
484
+ if (inputRequired === required && stringifyJSON(inputJson) === stringifyJSON(json)) {
485
+ allowedStrategies.push("input");
486
+ }
561
487
  }
488
+ baseSchemaConvertOptions.components.push({
489
+ schema,
490
+ required,
491
+ ref: `#/components/schemas/${key}`,
492
+ allowedStrategies
493
+ });
562
494
  }
563
- const [_queryRequired, querySchema] = await this.converter.convert(def.schemas.querySchema, {
564
- ...baseSchemaConvertOptions,
565
- strategy: "input",
566
- minStructureDepthForRef: 0
567
- });
568
- if (!isAnySchema(querySchema)) {
569
- const resolvedSchema = resolveOpenAPIJsonSchemaRef(doc, querySchema);
570
- if (!isObjectSchema(resolvedSchema)) {
571
- throw new OpenAPIGeneratorError("Query param schema must satisfy: object | any | unknown");
572
- }
573
- ref.parameters ??= [];
574
- ref.parameters.push(...toOpenAPIParameters(resolvedSchema, "query"));
575
- }
576
- if (method !== "GET") {
577
- const details = getEventIteratorSchemaDetails(def.schemas.bodySchema);
578
- if (details) {
579
- ref.requestBody = {
580
- required: true,
581
- content: toOpenAPIEventIteratorContent(
582
- await this.converter.convert(details.yields, { ...baseSchemaConvertOptions, strategy: "input" }),
583
- await this.converter.convert(details.returns, { ...baseSchemaConvertOptions, strategy: "input" })
584
- )
585
- };
586
- } else {
587
- const [bodyRequired, bodySchema] = await this.converter.convert(def.schemas.bodySchema, {
588
- ...baseSchemaConvertOptions,
589
- strategy: "input",
590
- minStructureDepthForRef: 0
591
- });
592
- if (isAnySchema(bodySchema)) {
593
- return;
495
+ doc.components ??= {};
496
+ doc.components.schemas ??= {};
497
+ for (const key in commonSchemas) {
498
+ const options = commonSchemas[key];
499
+ if (options.schema === void 0) {
500
+ if (options.error === "UndefinedError") {
501
+ doc.components.schemas[key] = toOpenAPISchema(undefinedErrorJsonSchema);
502
+ undefinedErrorJsonSchema = { $ref: `#/components/schemas/${key}` };
594
503
  }
595
- ref.requestBody = {
596
- required: bodyRequired,
597
- content: toOpenAPIContent(bodySchema)
598
- };
504
+ continue;
599
505
  }
506
+ const { schema, strategy = "input" } = options;
507
+ const [, json] = await converter(schema, {
508
+ ...baseSchemaConvertOptions,
509
+ strategy,
510
+ minStructureDepthForRef: 1
511
+ // not allow use $ref for root schemas
512
+ });
513
+ doc.components.schemas[key] = toOpenAPISchema(json);
600
514
  }
601
515
  }
602
- async #successResponse(doc, ref, def, baseSchemaConvertOptions) {
603
- const outputSchema = def.schemas.outputSchema;
604
- const status = fallbackContractConfig("defaultSuccessStatus", def.route.successStatus);
605
- const description = fallbackContractConfig("defaultSuccessDescription", def.route?.successDescription);
606
- const eventIteratorSchemaDetails = getEventIteratorSchemaDetails(outputSchema);
607
- const outputStructure = fallbackContractConfig("defaultOutputStructure", def.route.outputStructure);
608
- if (eventIteratorSchemaDetails) {
609
- ref.responses ??= {};
610
- ref.responses[status] = {
611
- description,
516
+ return { baseSchemaConvertOptions, undefinedErrorJsonSchema };
517
+ }
518
+ async function handleRequest(doc, ref, def, baseSchemaConvertOptions, converter) {
519
+ const method = fallbackContractConfig("defaultMethod", def.route.method);
520
+ const dynamicParams = getDynamicParams(def.route.path)?.map((v) => v.name);
521
+ const [_pathRequired, pathSchema] = await converter(def.schemas.pathSchema, {
522
+ ...baseSchemaConvertOptions,
523
+ strategy: "input",
524
+ minStructureDepthForRef: 1
525
+ });
526
+ if (dynamicParams?.length) {
527
+ const error = new OpenAPIGeneratorError(
528
+ // TODO: fix this error
529
+ 'When input structure is "compact", and path has dynamic params, input schema must be an object with all dynamic params as required.'
530
+ );
531
+ if (!isObjectSchema(pathSchema)) {
532
+ throw error;
533
+ }
534
+ if (!checkParamsSchema(pathSchema, dynamicParams)) {
535
+ throw error;
536
+ }
537
+ ref.parameters ??= [];
538
+ ref.parameters.push(...toOpenAPIParameters(pathSchema, "path"));
539
+ } else {
540
+ const error = new OpenAPIGeneratorError("Params set via path do not match those on the route");
541
+ if (!isObjectSchema(pathSchema)) {
542
+ throw error;
543
+ }
544
+ if (!checkParamsSchema(pathSchema, [])) {
545
+ throw error;
546
+ }
547
+ }
548
+ const [_queryRequired, querySchema] = await converter(def.schemas.querySchema, {
549
+ ...baseSchemaConvertOptions,
550
+ strategy: "input",
551
+ minStructureDepthForRef: 0
552
+ });
553
+ if (!isAnySchema(querySchema)) {
554
+ const resolvedSchema = resolveOpenAPIJsonSchemaRef(doc, querySchema);
555
+ if (!isObjectSchema(resolvedSchema)) {
556
+ throw new OpenAPIGeneratorError("Query param schema must satisfy: object | any | unknown");
557
+ }
558
+ ref.parameters ??= [];
559
+ ref.parameters.push(...toOpenAPIParameters(resolvedSchema, "query"));
560
+ }
561
+ if (method !== "GET") {
562
+ const details = getEventIteratorSchemaDetails(def.schemas.bodySchema);
563
+ if (details) {
564
+ ref.requestBody = {
565
+ required: true,
612
566
  content: toOpenAPIEventIteratorContent(
613
- await this.converter.convert(eventIteratorSchemaDetails.yields, {
614
- ...baseSchemaConvertOptions,
615
- strategy: "output"
616
- }),
617
- await this.converter.convert(eventIteratorSchemaDetails.returns, {
618
- ...baseSchemaConvertOptions,
619
- strategy: "output"
620
- })
567
+ await converter(details.yields, { ...baseSchemaConvertOptions, strategy: "input" }),
568
+ await converter(details.returns, { ...baseSchemaConvertOptions, strategy: "input" })
621
569
  )
622
570
  };
623
- return;
624
- }
625
- const [required, json] = await this.converter.convert(outputSchema, {
626
- ...baseSchemaConvertOptions,
627
- strategy: "output",
628
- minStructureDepthForRef: outputStructure === "detailed" ? 1 : 0
629
- });
630
- if (outputStructure === "compact") {
631
- ref.responses ??= {};
632
- ref.responses[status] = {
633
- description
571
+ } else {
572
+ const [bodyRequired, bodySchema] = await converter(def.schemas.bodySchema, {
573
+ ...baseSchemaConvertOptions,
574
+ strategy: "input",
575
+ minStructureDepthForRef: 0
576
+ });
577
+ if (isAnySchema(bodySchema)) {
578
+ return;
579
+ }
580
+ ref.requestBody = {
581
+ required: bodyRequired,
582
+ content: toOpenAPIContent(bodySchema)
634
583
  };
635
- ref.responses[status].content = toOpenAPIContent(applySchemaOptionality(required, json));
636
- return;
637
584
  }
638
- const handledStatuses = /* @__PURE__ */ new Set();
639
- for (const item of expandUnionSchema(json)) {
640
- const error = new OpenAPIGeneratorError(`
641
- When output structure is "detailed", output schema must satisfy:
642
- {
643
- status?: number, // must be a literal number and in the range of 200-399
644
- headers?: Record<string, unknown>,
645
- body?: unknown
646
- }
585
+ }
586
+ }
587
+ async function handleSuccessResponse(doc, ref, def, baseSchemaConvertOptions, converter) {
588
+ const outputSchema = def.schemas.outputSchema;
589
+ const status = fallbackContractConfig("defaultSuccessStatus", def.route.successStatus);
590
+ const description = fallbackContractConfig("defaultSuccessDescription", def.route?.successDescription);
591
+ const eventIteratorSchemaDetails = getEventIteratorSchemaDetails(outputSchema);
592
+ const outputStructure = fallbackContractConfig("defaultOutputStructure", def.route.outputStructure);
593
+ if (eventIteratorSchemaDetails) {
594
+ ref.responses ??= {};
595
+ ref.responses[status] = {
596
+ description,
597
+ content: toOpenAPIEventIteratorContent(
598
+ await converter(eventIteratorSchemaDetails.yields, {
599
+ ...baseSchemaConvertOptions,
600
+ strategy: "output"
601
+ }),
602
+ await converter(eventIteratorSchemaDetails.returns, {
603
+ ...baseSchemaConvertOptions,
604
+ strategy: "output"
605
+ })
606
+ )
607
+ };
608
+ return;
609
+ }
610
+ const [required, json] = await converter(outputSchema, {
611
+ ...baseSchemaConvertOptions,
612
+ strategy: "output",
613
+ minStructureDepthForRef: outputStructure === "detailed" ? 1 : 0
614
+ });
615
+ if (outputStructure === "compact") {
616
+ ref.responses ??= {};
617
+ ref.responses[status] = {
618
+ description
619
+ };
620
+ ref.responses[status].content = toOpenAPIContent(applySchemaOptionality(required, json));
621
+ return;
622
+ }
623
+ const handledStatuses = /* @__PURE__ */ new Set();
624
+ for (const item of expandUnionSchema(json)) {
625
+ const error = new OpenAPIGeneratorError(`
626
+ When output structure is "detailed", output schema must satisfy:
627
+ {
628
+ status?: number, // must be a literal number and in the range of 200-399
629
+ headers?: Record<string, unknown>,
630
+ body?: unknown
631
+ }
647
632
 
648
- But got: ${stringifyJSON(item)}
649
- `);
650
- if (!isObjectSchema(item)) {
633
+ But got: ${stringifyJSON(item)}
634
+ `);
635
+ if (!isObjectSchema(item)) {
636
+ throw error;
637
+ }
638
+ let schemaStatus;
639
+ let schemaDescription;
640
+ if (item.properties?.status !== void 0) {
641
+ const statusSchema = resolveOpenAPIJsonSchemaRef(doc, item.properties.status);
642
+ if (typeof statusSchema !== "object" || statusSchema.const === void 0 || typeof statusSchema.const !== "number" || !Number.isInteger(statusSchema.const) || isAPIErrorStatus(statusSchema.const)) {
651
643
  throw error;
652
644
  }
653
- let schemaStatus;
654
- let schemaDescription;
655
- if (item.properties?.status !== void 0) {
656
- const statusSchema = resolveOpenAPIJsonSchemaRef(doc, item.properties.status);
657
- if (typeof statusSchema !== "object" || statusSchema.const === void 0 || typeof statusSchema.const !== "number" || !Number.isInteger(statusSchema.const) || isORPCErrorStatus(statusSchema.const)) {
658
- throw error;
659
- }
660
- schemaStatus = statusSchema.const;
661
- schemaDescription = statusSchema.description;
662
- }
663
- const itemStatus = schemaStatus ?? status;
664
- const itemDescription = schemaDescription ?? description;
665
- if (handledStatuses.has(itemStatus)) {
666
- throw new OpenAPIGeneratorError(`
667
- When output structure is "detailed", each success status must be unique.
668
- But got status: ${itemStatus} used more than once.
669
- `);
645
+ schemaStatus = statusSchema.const;
646
+ schemaDescription = statusSchema.description;
647
+ }
648
+ const itemStatus = schemaStatus ?? status;
649
+ const itemDescription = schemaDescription ?? description;
650
+ if (handledStatuses.has(itemStatus)) {
651
+ throw new OpenAPIGeneratorError(`
652
+ When output structure is "detailed", each success status must be unique.
653
+ But got status: ${itemStatus} used more than once.
654
+ `);
655
+ }
656
+ handledStatuses.add(itemStatus);
657
+ ref.responses ??= {};
658
+ ref.responses[itemStatus] = {
659
+ description: itemDescription
660
+ };
661
+ if (item.properties?.headers !== void 0) {
662
+ const headersSchema = resolveOpenAPIJsonSchemaRef(doc, item.properties.headers);
663
+ if (!isObjectSchema(headersSchema)) {
664
+ throw error;
670
665
  }
671
- handledStatuses.add(itemStatus);
672
- ref.responses ??= {};
673
- ref.responses[itemStatus] = {
674
- description: itemDescription
675
- };
676
- if (item.properties?.headers !== void 0) {
677
- const headersSchema = resolveOpenAPIJsonSchemaRef(doc, item.properties.headers);
678
- if (!isObjectSchema(headersSchema)) {
679
- throw error;
680
- }
681
- for (const key in headersSchema.properties) {
682
- const headerSchema = headersSchema.properties[key];
683
- if (headerSchema !== void 0) {
684
- ref.responses[itemStatus].headers ??= {};
685
- ref.responses[itemStatus].headers[key] = {
686
- schema: toOpenAPISchema(headerSchema),
687
- required: item.required?.includes("headers") && headersSchema.required?.includes(key)
688
- };
689
- }
666
+ for (const key in headersSchema.properties) {
667
+ const headerSchema = headersSchema.properties[key];
668
+ if (headerSchema !== void 0) {
669
+ ref.responses[itemStatus].headers ??= {};
670
+ ref.responses[itemStatus].headers[key] = {
671
+ schema: toOpenAPISchema(headerSchema),
672
+ required: item.required?.includes("headers") && headersSchema.required?.includes(key)
673
+ };
690
674
  }
691
675
  }
692
- if (item.properties?.body !== void 0) {
693
- ref.responses[itemStatus].content = toOpenAPIContent(
694
- applySchemaOptionality(item.required?.includes("body") ?? false, item.properties.body)
695
- );
696
- }
697
676
  }
698
- }
699
- async #errorResponse(ref, def, baseSchemaConvertOptions, undefinedErrorSchema) {
700
- const errorMap = def.errorMap;
701
- const errors = {};
702
- for (const code in errorMap) {
703
- const config = errorMap[code];
704
- if (!config) {
705
- continue;
706
- }
707
- const status = fallbackORPCErrorStatus(code, config.status);
708
- const message = fallbackORPCErrorMessage(code, config.message);
709
- const [dataRequired, dataSchema] = await this.converter.convert(config.data, {
710
- ...baseSchemaConvertOptions,
711
- strategy: "output"
712
- });
713
- errors[status] ??= [];
714
- errors[status].push({
715
- type: "object",
716
- properties: {
717
- defined: { const: true },
718
- code: { const: code },
719
- status: { const: status },
720
- message: { type: "string", default: message },
721
- data: dataSchema
722
- },
723
- required: dataRequired ? ["defined", "code", "status", "message", "data"] : ["defined", "code", "status", "message"]
724
- });
677
+ if (item.properties?.body !== void 0) {
678
+ ref.responses[itemStatus].content = toOpenAPIContent(
679
+ applySchemaOptionality(item.required?.includes("body") ?? false, item.properties.body)
680
+ );
725
681
  }
726
- ref.responses ??= {};
727
- for (const status in errors) {
728
- const schemas = errors[status];
729
- ref.responses[status] = {
730
- description: status,
731
- content: toOpenAPIContent({
732
- oneOf: [...schemas, undefinedErrorSchema]
733
- })
682
+ }
683
+ }
684
+ function authConfigToSecurityScheme(authConfig) {
685
+ switch (authConfig.type) {
686
+ case "basic":
687
+ return {
688
+ type: "http",
689
+ scheme: "basic",
690
+ description: authConfig.oasDescription
734
691
  };
735
- }
692
+ case "bearer":
693
+ return {
694
+ type: "http",
695
+ scheme: "bearer",
696
+ description: authConfig.oasDescription,
697
+ bearerFormat: authConfig.oasBearerFormat
698
+ };
699
+ case "header":
700
+ return {
701
+ type: "apiKey",
702
+ in: "header",
703
+ name: authConfig.name,
704
+ description: authConfig.oasDescription
705
+ };
706
+ case "query":
707
+ return {
708
+ type: "apiKey",
709
+ in: "query",
710
+ name: authConfig.name,
711
+ description: authConfig.oasDescription
712
+ };
713
+ case "cookie":
714
+ return {
715
+ type: "apiKey",
716
+ in: "cookie",
717
+ name: authConfig.name,
718
+ description: authConfig.oasDescription
719
+ };
720
+ default:
721
+ assertNever(authConfig, `Unsupported auth config type: ${authConfig.type}`);
736
722
  }
737
723
  }
738
-
739
- function createJsonifiedRouterClient(router, ...rest) {
740
- const options = resolveMaybeOptionalOptions(rest);
741
- options.interceptors ??= [];
742
- options.interceptors.unshift(async (options2) => {
743
- try {
744
- return deserialize(serialize(await options2.next()));
745
- } catch (e) {
746
- if (e instanceof ORPCError) {
747
- throw createORPCErrorFromJson(deserialize(serialize(e.toJSON(), { outputFormat: "plain" })));
748
- }
749
- throw e;
724
+ async function handleErrorResponse(doc, ref, def, baseSchemaConvertOptions, converter) {
725
+ const errorMap = def.errorMap;
726
+ const errorResponsesByStatus = {};
727
+ for (const code in errorMap) {
728
+ const errorClass = errorMap[code];
729
+ if (!errorClass) {
730
+ continue;
750
731
  }
751
- });
752
- return createRouterClient(router, options);
732
+ const status = errorClass.status;
733
+ const type = errorClass.type;
734
+ const defaultMessage = errorClass.defaultMessage;
735
+ errorResponsesByStatus[status] ??= { status, errorSchemaVariants: [] };
736
+ const extraZod = z.object(errorClass.extraSchema).strict();
737
+ const [, extraSchema] = await converter(extraZod, {
738
+ ...baseSchemaConvertOptions,
739
+ strategy: "output"
740
+ });
741
+ if (!isObjectSchema(extraSchema)) {
742
+ throw new OpenAPIGeneratorError(
743
+ `Error response extra schema must be an object, but got: ${stringifyJSON(extraSchema)}`
744
+ );
745
+ }
746
+ errorResponsesByStatus[status].errorSchemaVariants.push({
747
+ type: "object",
748
+ properties: {
749
+ type: { const: type },
750
+ message: { type: "string", default: defaultMessage },
751
+ ...extraSchema.properties
752
+ },
753
+ required: ["type", "message", ...extraSchema.required ?? []]
754
+ });
755
+ }
756
+ ref.responses ??= {};
757
+ for (const statusString in errorResponsesByStatus) {
758
+ const errorResponse = errorResponsesByStatus[statusString];
759
+ if (statusString === "500") {
760
+ console.log(
761
+ errorResponse.errorSchemaVariants,
762
+ toOpenAPIContent({
763
+ oneOf: errorResponse.errorSchemaVariants
764
+ })
765
+ );
766
+ }
767
+ ref.responses[statusString] = {
768
+ description: statusString,
769
+ content: toOpenAPIContent(
770
+ errorResponse.errorSchemaVariants.length === 1 ? errorResponse.errorSchemaVariants[0] : {
771
+ oneOf: errorResponse.errorSchemaVariants
772
+ }
773
+ )
774
+ };
775
+ }
753
776
  }
754
777
 
755
778
  const oo = {
756
779
  spec: customOpenAPIOperation
757
780
  };
758
781
 
759
- export { CompositeSchemaConverter, LOGIC_KEYWORDS, OpenAPIGenerator, applyCustomOpenAPIOperation, applySchemaOptionality, checkParamsSchema, createJsonifiedRouterClient, customOpenAPIOperation, expandArrayableSchema, expandUnionSchema, filterSchemaBranches, getCustomOpenAPIOperation, isAnySchema, isFileSchema, isObjectSchema, isPrimitiveSchema, oo, resolveOpenAPIJsonSchemaRef, separateObjectSchema, toOpenAPIContent, toOpenAPIEventIteratorContent, toOpenAPIMethod, toOpenAPIParameters, toOpenAPIPath, toOpenAPISchema };
782
+ export { LOGIC_KEYWORDS, applyCustomOpenAPIOperation, applySchemaOptionality, checkParamsSchema, customOpenAPIOperation, expandArrayableSchema, expandUnionSchema, filterSchemaBranches, generateOpenApiSpec, getCustomOpenAPIOperation, isAnySchema, isFileSchema, isObjectSchema, isPrimitiveSchema, oo, resolveOpenAPIJsonSchemaRef, separateObjectSchema, toOpenAPIContent, toOpenAPIEventIteratorContent, toOpenAPIMethod, toOpenAPIParameters, toOpenAPIPath, toOpenAPISchema };