Skip to content

Commit 32cb70c

Browse files
authored
feat(contract, server)!: rewrite builders (#110)
* wip * types tests * wip * 100% test coverage * fix types * fix types * remove ~type and decorated method * procedure builders * rename * router builders * builder * remove redundant method * wip * router * wip * fix isLazy * procedure tests * router tests * builder tests * 100% test coverage * wip * fixed * fix types tests * wip * fix types * ORPCErrorConstructorMap * improve * wip * improve * improve * wip * improve * improve * fix * prefix lazy * fix * procedure implementer * type tests * tests * index * variants tests * setRouterContract * fix * docs * docs * tests * clear mock before each tests * lint fixed * fix docs * fix restrict context * fix types * improve middlewares
1 parent ed15210 commit 32cb70c

File tree

212 files changed

+6439
-9509
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

212 files changed

+6439
-9509
lines changed

apps/content/content/docs/contract-first.mdx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,15 @@ export type Outputs = InferContractRouterOutputs<typeof contract>
9090
With your contract defined, implement the server logic:
9191
9292
```ts twoslash
93-
import { os, ORPCError } from '@orpc/server'
93+
import { implement, ORPCError } from '@orpc/server'
9494
import { contract } from 'examples/contract'
9595

96-
export const pub = os.contract(contract) // Ensure every implement must be match contract
97-
export const authed = os
96+
export const pub = implement(contract) // Ensure every implement must be match contract
97+
export const authed = pub
9898
.use(({ context, path, next }, input) => {
9999
/** put auth logic here */
100100
return next({})
101101
})
102-
.contract(contract)
103102

104103
export const router = pub.router({
105104
getUser: pub.getUser.handler(({ input, context }) => {

apps/content/content/docs/index.mdx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ import { z } from 'zod'
6262
export type Context = { user?: { id: string } }
6363

6464
// global pub, authed completely optional
65-
export const pub = os.context<Context>()
65+
export const pub = os.$context<Context>()
6666
export const authed = pub.use(({ context, path, next }, input) => {
6767
/** put auth logic here */
6868
return next({})
@@ -98,9 +98,7 @@ export const router = pub.router({
9898
)
9999
.use(async ({ context, path, next }, input) => {
100100
if (!context.user) {
101-
throw new ORPCError({
102-
code: 'UNAUTHORIZED',
103-
})
101+
throw new ORPCError('UNAUTHORIZED')
104102
}
105103

106104
const result = await next({

apps/content/content/docs/openapi/generator.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { z } from 'zod'
1919
export type Context = { user?: { id: string } }
2020

2121
// global pub, authed completely optional
22-
export const pub = os.context<Context>()
22+
export const pub = os.$context<Context>()
2323
export const authed = pub.use(({ context, path, next }, input) => {
2424
/** put auth logic here */
2525
return next({})

apps/content/content/docs/server/context.mdx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ import { z } from 'zod'
1818
import { headers } from 'next/headers'
1919

2020
type ORPCContext = { db: 'fake-db', user?: { id: string } }
21-
const base = os.context<ORPCContext>() // define `initial context`
21+
const base = os.$context<ORPCContext>() // define `initial context`
2222

23-
const pub = os.context<ORPCContext>().use(async ({ context, path, next }, input) => {
23+
const pub = os.$context<ORPCContext>().use(async ({ context, path, next }, input) => {
2424
const headersList = await headers()
2525

2626
// the `user` is `middleware context`, because it is created by middleware
@@ -58,13 +58,13 @@ const base = os.use(async ({ context, path, next }, input) => {
5858
})
5959

6060
const authMid = os
61-
.context<{ db: string }>() // this middleware depends on some context
61+
.$context<{ db: string }>() // this middleware depends on some context
6262
.middleware(async ({ context, next, path }, input) => {
6363
const headersList = await headers()
6464
const user = headersList.get('Authorization') ? { id: 'example' } : undefined
6565

6666
if (!user) {
67-
throw new ORPCError({ code: 'UNAUTHORIZED' })
67+
throw new ORPCError('UNAUTHORIZED')
6868
}
6969

7070
return next({
@@ -108,11 +108,11 @@ import { OpenAPIServerlessHandler, OpenAPIServerHandler } from '@orpc/openapi/fe
108108

109109
type ORPCContext = { user?: { id: string }, db: 'fake-db' }
110110

111-
const base = os.context<ORPCContext>()
111+
const base = os.$context<ORPCContext>()
112112

113113
const authMid = base.middleware(({ context, next, path }, input) => {
114114
if(!context.user) {
115-
throw new ORPCError({ code: 'UNAUTHORIZED' })
115+
throw new ORPCError('UNAUTHORIZED')
116116
}
117117

118118
return next({

apps/content/content/docs/server/contract.mdx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,18 +78,17 @@ export const contract = oc.router({
7878
All `server` features are available, except the input, output, and route parts, which are defined in the contract.
7979

8080
```ts twoslash
81-
import { os } from '@orpc/server'
81+
import { implement } from '@orpc/server'
8282
import { contract } from 'examples/contract'
8383

8484
export type Context = { user?: { id: string } }
85-
export const base = os.context<Context>()
86-
export const pub = base.contract(contract) // Ensure every implement must be match contract
85+
export const base = implement(contract).$context<Context>()
86+
export const pub = base
8787
export const authed = base
8888
.use(({ context, path, next }, input) => {
8989
/** put auth logic here */
9090
return next({})
9191
})
92-
.contract(contract)
9392

9493
export const router = pub.router({
9594
getUser: pub.getUser.handler(({ input, context }) => {

apps/content/content/docs/server/error-handling.mdx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const createPost = os
2626
throw errors.CONFLICT({ data: { why: 'some reason' } })
2727

2828
// is the same as, but this is not typed
29-
throw new ORPCError({ code: 'CONFLICT', data: { why: 'some reason' } })
29+
throw new ORPCError('CONFLICT', { data: { why: 'some reason' } })
3030

3131
// throw errors.ANY_CODE()
3232
})
@@ -82,8 +82,7 @@ const ping = os
8282
}
8383
})
8484
.handler(({ input, context }) => {
85-
throw new ORPCError({
86-
code: 'NOT_FOUND',
85+
throw new ORPCError('NOT_FOUND', {
8786
message: 'Not found',
8887
status: 404, // Optional: custom default behavior
8988
data: { something: 'include in the body and send to the client' } // pass data to the client

apps/content/content/docs/server/lazy.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Here's how you can set up and use them:
1616
```typescript twoslash
1717
import { os, call } from '@orpc/server'
1818

19-
const pub = os.context<{ user?: { id: string } }>()
19+
const pub = os.$context<{ user?: { id: string } }>()
2020

2121
// Define a router with lazy loading
2222
const router = pub.router({
@@ -48,7 +48,7 @@ const output = await call(router.lazy.getUser, { id: '123' })
4848

4949
```ts twoslash
5050
import { os } from '@orpc/server'
51-
const pub = os.context<{ user?: { id: string } }>()
51+
const pub = os.$context<{ user?: { id: string } }>()
5252

5353
const lazy = pub.prefix('/some').lazy(() => import('examples/server'))
5454
```

apps/content/content/docs/server/middleware.mdx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@ import { os, ORPCError } from '@orpc/server'
1212

1313
export type Context = { user?: { id: string } }
1414

15-
export const pub = os.context<Context>()
15+
export const pub = os.$context<Context>()
1616

1717
const authMiddleware = pub.middleware(async ({ context, next, path }, input) => {
1818
if (!context.user) {
19-
throw new ORPCError({
20-
code: 'UNAUTHORIZED',
19+
throw new ORPCError('UNAUTHORIZED', {
2120
message: 'You need to log in first',
2221
})
2322
}
@@ -86,13 +85,13 @@ type Context = {
8685
}
8786
}
8887

89-
export const pub = os.context<Context>()
88+
export const pub = os.$context<Context>()
9089

9190
// Any procedure using this middleware will infer context.user as NonNullable<typeof context['user']>
9291
const authMiddleware = pub
9392
.middleware(async ({ context, next, path }, input) => {
9493
if (!context.user) {
95-
throw new ORPCError({ code: 'UNAUTHORIZED' })
94+
throw new ORPCError('UNAUTHORIZED')
9695
}
9796

9897
return next({

apps/content/content/docs/server/procedure.mdx

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,11 @@ import { os, ORPCError } from '@orpc/server'
2121

2222
// Define context type for full type inference
2323
const pub = os
24-
.context<{user?: {id: string}}>()
25-
.config({ // optional, change some default configuration
26-
initialRoute: {
27-
method: 'DELETE', // change default method to DELETE
28-
inputStructure: 'detailed', // change default input structure to detailed
29-
outputStructure: 'detailed' // change default output structure to detailed
30-
}
24+
.$context<{user?: {id: string}}>() // optional, set config
25+
.$route({ // optional, change initial route
26+
method: 'DELETE', // change default method to DELETE
27+
inputStructure: 'detailed', // change default input structure to detailed
28+
outputStructure: 'detailed' // change default output structure to detailed
3129
})
3230

3331
const getUser = pub
@@ -40,8 +38,7 @@ const getUser = pub
4038

4139
// Example: Authentication check
4240
if (!context.user) {
43-
throw new ORPCError({
44-
code: 'UNAUTHORIZED',
41+
throw new ORPCError('UNAUTHORIZED', {
4542
message: 'Authentication required'
4643
})
4744
}

apps/content/content/docs/server/server-action.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ When calling `.actionable()`, you can pass a context function that provides addi
4343
import { os } from '@orpc/server'
4444
import { z } from 'zod'
4545

46-
const pub = os.context<{ db: string }>()
46+
const pub = os.$context<{ db: string }>()
4747

4848
export const getting = pub
4949
.input(z.object({
@@ -77,7 +77,7 @@ const authed = os.use(async ({ next }) => {
7777
const user = headersList.get('Authorization') ? { id: 'example' } : undefined
7878

7979
if (!user) {
80-
throw new ORPCError({ code: 'UNAUTHORIZED' })
80+
throw new ORPCError('UNAUTHORIZED')
8181
}
8282

8383
return next({

0 commit comments

Comments
 (0)