-
-
Notifications
You must be signed in to change notification settings - Fork 141
feat(nest, contract): prefer import populateContractRouterPaths from @orpc/contract
#1312
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,8 @@ import type { ErrorMap, MergedErrorMap } from './error' | |
| import type { AnyContractProcedure } from './procedure' | ||
| import type { EnhanceRouteOptions } from './route' | ||
| import type { AnyContractRouter } from './router' | ||
| import { toHttpPath } from '@orpc/client/standard' | ||
| import { toArray } from '@orpc/shared' | ||
| import { mergeErrorMap } from './error' | ||
| import { ContractProcedure, isContractProcedure } from './procedure' | ||
| import { enhanceRoute } from './route' | ||
|
|
@@ -89,3 +91,48 @@ export function minifyContractRouter(router: AnyContractRouter): AnyContractRout | |
|
|
||
| return json | ||
| } | ||
|
|
||
| export type PopulatedContractRouterPaths<T extends AnyContractRouter> | ||
| = T extends ContractProcedure<infer UInputSchema, infer UOutputSchema, infer UErrors, infer UMeta> | ||
| ? ContractProcedure<UInputSchema, UOutputSchema, UErrors, UMeta> | ||
| : { | ||
| [K in keyof T]: T[K] extends AnyContractRouter ? PopulatedContractRouterPaths<T[K]> : never | ||
| } | ||
|
|
||
| export interface PopulateContractRouterPathsOptions { | ||
| path?: readonly string[] | ||
| } | ||
|
|
||
| /** | ||
| * Automatically populates missing route paths using the router's nested keys. | ||
| * | ||
| * Constructs paths by joining router keys with `/`. | ||
| * Useful for NestJS integration that require explicit route paths. | ||
| * | ||
| * @see {@link https://orpc.dev/docs/openapi/integrations/implement-contract-in-nest#define-your-contract NestJS Implement Contract Docs} | ||
| */ | ||
| export function populateContractRouterPaths<T extends AnyContractRouter>(router: T, options: PopulateContractRouterPathsOptions = {}): PopulatedContractRouterPaths<T> { | ||
| const path = toArray(options.path) | ||
|
|
||
| if (isContractProcedure(router)) { | ||
| if (router['~orpc'].route.path === undefined) { | ||
| return new ContractProcedure({ | ||
| ...router['~orpc'], | ||
| route: { | ||
| ...router['~orpc'].route, | ||
| path: toHttpPath(path), | ||
| }, | ||
| }) as any | ||
| } | ||
|
|
||
| return router as any | ||
| } | ||
|
|
||
| const populated: Record<string, any> = {} | ||
|
|
||
| for (const key in router) { | ||
| populated[key] = populateContractRouterPaths(router[key]!, { ...options, path: [...path, key] }) | ||
| } | ||
|
|
||
| return populated as any | ||
| } | ||
|
Comment on lines
+114
to
+138
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The function |
||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,56 +1,8 @@ | ||
| import type { AnyContractRouter, HTTPPath } from '@orpc/contract' | ||
| import { toHttpPath } from '@orpc/client/standard' | ||
| import { ContractProcedure, isContractProcedure } from '@orpc/contract' | ||
| import type { HTTPPath } from '@orpc/contract' | ||
| import { standardizeHTTPPath } from '@orpc/openapi-client/standard' | ||
| import { toArray } from '@orpc/shared' | ||
|
|
||
| export function toNestPattern(path: HTTPPath): string { | ||
| return standardizeHTTPPath(path) | ||
| .replace(/\/\{\+([^}]+)\}/g, '/*$1') | ||
| .replace(/\/\{([^}]+)\}/g, '/:$1') | ||
| } | ||
|
|
||
| export type PopulatedContractRouterPaths<T extends AnyContractRouter> | ||
| = T extends ContractProcedure<infer UInputSchema, infer UOutputSchema, infer UErrors, infer UMeta> | ||
| ? ContractProcedure<UInputSchema, UOutputSchema, UErrors, UMeta> | ||
| : { | ||
| [K in keyof T]: T[K] extends AnyContractRouter ? PopulatedContractRouterPaths<T[K]> : never | ||
| } | ||
|
|
||
| export interface PopulateContractRouterPathsOptions { | ||
| path?: readonly string[] | ||
| } | ||
|
|
||
| /** | ||
| * populateContractRouterPaths is completely optional, | ||
| * because the procedure's path is required for NestJS implementation. | ||
| * This utility automatically populates any missing paths | ||
| * Using the router's keys + `/`. | ||
| * | ||
| * @see {@link https://orpc.dev/docs/openapi/integrations/implement-contract-in-nest#define-your-contract NestJS Implement Contract Docs} | ||
| */ | ||
| export function populateContractRouterPaths<T extends AnyContractRouter>(router: T, options: PopulateContractRouterPathsOptions = {}): PopulatedContractRouterPaths<T> { | ||
| const path = toArray(options.path) | ||
|
|
||
| if (isContractProcedure(router)) { | ||
| if (router['~orpc'].route.path === undefined) { | ||
| return new ContractProcedure({ | ||
| ...router['~orpc'], | ||
| route: { | ||
| ...router['~orpc'].route, | ||
| path: toHttpPath(path), | ||
| }, | ||
| }) as any | ||
| } | ||
|
|
||
| return router as any | ||
| } | ||
|
|
||
| const populated: Record<string, any> = {} | ||
|
|
||
| for (const key in router) { | ||
| populated[key] = populateContractRouterPaths(router[key]!, { ...options, path: [...path, key] }) | ||
| } | ||
|
|
||
| return populated as any | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
for...inloop iterates over all enumerable properties of an object, including those on its prototype chain. To ensure you're only processing properties of therouterobject itself, it's a good practice to include ahasOwnPropertycheck.