diff --git a/lib/types/request.d.ts b/lib/types/request.d.ts index c987216db..078fc3c95 100644 --- a/lib/types/request.d.ts +++ b/lib/types/request.d.ts @@ -27,23 +27,24 @@ export interface AppCredentials { * User-extensible type for request.auth credentials. */ export interface AuthCredentials< - AuthUser extends object = UserCredentials, - AuthApp extends object = AppCredentials, + AuthUser = UserCredentials, + AuthApp = AppCredentials > { /** * The application scopes to be granted. * [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-routeoptionsauthaccessscope) */ scope?: string[] | undefined; + /** * If set, will only work with routes that set `access.entity` to `user`. */ - user?: MergeType | undefined; + user?: AuthUser /** * If set, will only work with routes that set `access.entity` to `app`. */ - app?: MergeType | undefined; + app?: AuthApp; } export interface AuthArtifacts { @@ -65,15 +66,20 @@ export type AuthMode = 'required' | 'optional' | 'try'; * [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-requestauth) */ export interface RequestAuth< - AuthUser extends object = UserCredentials, - AuthApp extends object = AppCredentials, - CredentialsExtra extends object = Record, + AuthUser = UserCredentials, + AuthApp = AppCredentials, + CredentialsExtra = Record, ArtifactsExtra = Record > { /** an artifact object received from the authentication strategy and used in authentication-related actions. */ artifacts: ArtifactsExtra; /** the credential object received during the authentication process. The presence of an object does not mean successful authentication. */ - credentials: MergeType>; + credentials: ( + + AuthCredentials & + CredentialsExtra + ); + /** the authentication error is failed and mode set to 'try'. */ error: Error; /** true if the request has been successfully authenticated, otherwise false. */ @@ -89,6 +95,7 @@ export interface RequestAuth< strategy: string; } + /** * 'peek' - emitted for each chunk of payload data read from the client connection. The event method signature is function(chunk, encoding). * 'finish' - emitted when the request payload finished reading. The event method signature is function (). @@ -296,7 +303,12 @@ export type ReqRef = Partial>; /** * Utilities for merging request refs and other things */ -export type MergeType = Omit & U; +export type MergeType = { + [K in keyof T]: K extends keyof U + ? U[K] + : T[K]; +}; + export type MergeRefs = MergeType; /** diff --git a/lib/types/response.d.ts b/lib/types/response.d.ts index 4b19ebc31..f7c131787 100644 --- a/lib/types/response.d.ts +++ b/lib/types/response.d.ts @@ -6,7 +6,6 @@ import { UserCredentials, AppCredentials, AuthArtifacts, - MergeType, AuthCredentials, ReqRef, ReqRefDefaults, @@ -386,19 +385,19 @@ export type ResponseValue = string | object; export interface AuthenticationData< - AuthUser extends object = UserCredentials, - AuthApp extends object = AppCredentials, - CredentialsExtra extends object = Record, + AuthUser = UserCredentials, + AuthApp = AppCredentials, + CredentialsExtra = Record, ArtifactsExtra = AuthArtifacts > { - credentials: MergeType>; + credentials: AuthCredentials & CredentialsExtra; artifacts?: ArtifactsExtra | undefined; } export interface Auth< - AuthUser extends object = UserCredentials, - AuthApp extends object = AppCredentials, - CredentialsExtra extends object = Record, + AuthUser = UserCredentials, + AuthApp = AppCredentials, + CredentialsExtra = Record, ArtifactsExtra = AuthArtifacts > { readonly isAuth: true; @@ -459,9 +458,9 @@ export interface ResponseToolkit { * @return Return value: an internal authentication object. */ authenticated < - AuthUser extends object = MergeRefs['AuthUser'], - AuthApp extends object = MergeRefs['AuthApp'], - CredentialsExtra extends object = MergeRefs['AuthCredentialsExtra'], + AuthUser = MergeRefs['AuthUser'], + AuthApp = MergeRefs['AuthApp'], + CredentialsExtra = MergeRefs['AuthCredentialsExtra'], ArtifactsExtra = MergeRefs['AuthArtifactsExtra'] >( data: ( @@ -537,9 +536,9 @@ export interface ResponseToolkit { * [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-hunauthenticatederror-data) */ unauthenticated < - AuthUser extends object = MergeRefs['AuthUser'], - AuthApp extends object = MergeRefs['AuthApp'], - CredentialsExtra extends object = MergeRefs['AuthCredentialsExtra'], + AuthUser = MergeRefs['AuthUser'], + AuthApp = MergeRefs['AuthApp'], + CredentialsExtra = MergeRefs['AuthCredentialsExtra'], ArtifactsExtra = MergeRefs['AuthArtifactsExtra'] >( error: Error, diff --git a/test/types/index.ts b/test/types/index.ts index 35fd0a49e..724d87283 100644 --- a/test/types/index.ts +++ b/test/types/index.ts @@ -10,6 +10,7 @@ import { Server, ServerRoute, server as createServer, + UserCredentials, ServerRegisterPluginObject, Lifecycle, CachedServerMethod @@ -17,6 +18,20 @@ import { const { expect: check } = lab; +type IsAny = ( + unknown extends T + ? [keyof T] extends [never] ? false : true + : false + ); + + +declare module '../..' { + interface UserCredentials { + someId: string; + someName: string; + } +} + interface ServerAppSpace { multi?: number; } @@ -29,6 +44,21 @@ check.type(server); server.app.multi = 10; +const genericRoute: ServerRoute = { + method: 'GET', + path: '/', + handler: (request, h) => { + + check.type(request.auth.credentials!.user!); + + const y: IsAny = false; + + return 'hello!'; + } +} + +server.route(genericRoute); + interface RequestDecorations { Server: MyServer; RequestApp: { @@ -36,6 +66,22 @@ interface RequestDecorations { }, RouteApp: { prefix: string[]; + }, + AuthUser: { + id: string, + name: string + email: string + }, + AuthCredentialsExtra: { + test: number + } + AuthApp: { + key: string + name: string + }, + AuthArtifactsExtra: { + some: string + thing: number } } @@ -63,6 +109,21 @@ const route: ServerRoute = { check.type(request.server.app.multi!); check.type(request.route.settings.app!.prefix); + check.type(request.auth.credentials!.test); + + check.type(request.auth.credentials!.user!.email); + check.type(request.auth.credentials!.user!.id); + check.type(request.auth.credentials!.user!.name); + + check.type(request.auth.credentials!.app!.name); + check.type(request.auth.credentials!.app!.key); + + check.type(request.auth.artifacts.some); + check.type(request.auth.artifacts.thing); + + const y: IsAny = false; + const z: IsAny = false; + return 'hello!' } }; @@ -135,7 +196,6 @@ server.method('test.add', (a: number, b: number) => a + b, { generateKey: (a: number, b: number) => `${a}${b}` }); - server.methods.test.add.cache?.drop(1, 2); declare module '../..' {