Skip to content

Commit 7a2230f

Browse files
committed
feat: checkContext type safety
1 parent 3d11d33 commit 7a2230f

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed

src/utils/check-context/check-context.util.test-d.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,22 @@ type User = {
88
name: string
99
}
1010

11+
type Message = {
12+
id: number
13+
text: string
14+
}
15+
1116
const app = feathers<{
1217
users: MemoryService<User>
13-
messages: MemoryService
18+
messages: MemoryService<Message>
1419
}>()
1520

1621
type App = typeof app
17-
type Ctx = HookContext<App, MemoryService<User>>
22+
type AppCtx = HookContext<App>
23+
type UserCtx = HookContext<App, MemoryService<User>>
1824

19-
const context = {} as Ctx
25+
const context = {} as UserCtx
26+
const appContext = {} as AppCtx
2027

2128
it('options overload accepts valid options', () => {
2229
checkContext(context, { type: 'before' })
@@ -34,6 +41,22 @@ it('options overload rejects invalid type', () => {
3441
checkContext(context, { type: 'invalid' })
3542
})
3643

44+
it('options overload accepts valid path for app-level context', () => {
45+
checkContext(appContext, { path: 'users' })
46+
checkContext(appContext, { path: 'messages' })
47+
checkContext(appContext, { path: ['users', 'messages'] })
48+
})
49+
50+
it('options overload rejects invalid path for service-specific context', () => {
51+
// @ts-expect-error "messages" is not valid when context is narrowed to MemoryService<User>
52+
checkContext(context, { path: 'messages' })
53+
})
54+
55+
it('options overload rejects invalid path for app-level context', () => {
56+
// @ts-expect-error "nonExistent" is not a valid service path
57+
checkContext(appContext, { path: 'nonExistent' })
58+
})
59+
3760
it('positional overload accepts valid args', () => {
3861
checkContext(context, 'before')
3962
checkContext(context, ['before', 'after'])

src/utils/check-context/check-context.util.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ import {
55
type IsContextOptions,
66
} from '../../predicates/is-context/is-context.predicate.js'
77

8-
export type CheckContextOptions = IsContextOptions & {
9-
label?: string
10-
}
8+
export type CheckContextOptions<H extends HookContext = HookContext> =
9+
IsContextOptions<H> & {
10+
label?: string
11+
}
1112

1213
/**
1314
* Validates that the hook context matches the expected type(s) and method(s).
@@ -30,7 +31,7 @@ export type CheckContextOptions = IsContextOptions & {
3031
*/
3132
export function checkContext<H extends HookContext = HookContext>(
3233
context: H,
33-
options: CheckContextOptions,
34+
options: CheckContextOptions<NoInfer<H>>,
3435
): void
3536
export function checkContext<H extends HookContext = HookContext>(
3637
context: H,
@@ -40,7 +41,11 @@ export function checkContext<H extends HookContext = HookContext>(
4041
): void
4142
export function checkContext<H extends HookContext = HookContext>(
4243
context: H,
43-
typeOrOptions?: HookType | HookType[] | CheckContextOptions | null,
44+
typeOrOptions?:
45+
| HookType
46+
| HookType[]
47+
| CheckContextOptions<NoInfer<H>>
48+
| null,
4449
methods?: MethodName | MethodName[] | null,
4550
label = 'anonymous',
4651
): void {

0 commit comments

Comments
 (0)