Skip to content

Commit

Permalink
perf(types): add type annotations (#2663)
Browse files Browse the repository at this point in the history
* feat(jsr): reduce slow types (#2369)

* feat(jsr): reduce slow types

* fix: use allow function

* chore: format code

* chore: denoify

* use `fn = () => {}` syntax for backwards compatible

* add type annotations and denoify

* add type annotations for helpers and denoify

* tweak

---------

Co-authored-by: Shotaro Nakamura <79000684+nakasyou@users.noreply.github.com>
  • Loading branch information
yusukebe and nakasyou committed May 12, 2024
1 parent 6db1cc6 commit e5975ed
Show file tree
Hide file tree
Showing 50 changed files with 228 additions and 114 deletions.
13 changes: 10 additions & 3 deletions deno_dist/context.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { HonoRequest } from './request.ts'
import type { Env, FetchEventLike, NotFoundHandler, Input, TypedResponse } from './types.ts'
import { resolveCallback, HtmlEscapedCallbackPhase } from './utils/html.ts'
import type { Env, FetchEventLike, Input, NotFoundHandler, TypedResponse } from './types.ts'
import { HtmlEscapedCallbackPhase, resolveCallback } from './utils/html.ts'
import type { RedirectStatusCode, StatusCode } from './utils/http-status.ts'
import type { JSONValue, JSONParsed, IsAny, Simplify } from './utils/types.ts'

Expand Down Expand Up @@ -224,7 +224,14 @@ export class Context<
*/
render: Renderer = (...args) => this.renderer(...args)

setLayout = (layout: Layout<PropsForRenderer & { Layout: Layout }>) => (this.layout = layout)
setLayout = (
layout: Layout<PropsForRenderer & { Layout: Layout }>
): Layout<
PropsForRenderer & {
Layout: Layout
}
> => (this.layout = layout)

getLayout = () => this.layout

/**
Expand Down
6 changes: 3 additions & 3 deletions deno_dist/helper/accepts/accepts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface acceptsOptions extends acceptsConfig {
match?: (accepts: Accept[], config: acceptsConfig) => string
}

export const parseAccept = (acceptHeader: string) => {
export const parseAccept = (acceptHeader: string): Accept[] => {
// Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
const accepts = acceptHeader.split(',') // ['text/html', 'application/xhtml+xml', 'application/xml;q=0.9', 'image/webp', '*/*;q=0.8']
return accepts.map((accept) => {
Expand All @@ -42,7 +42,7 @@ export const parseAccept = (acceptHeader: string) => {
})
}

export const defaultMatch = (accepts: Accept[], config: acceptsConfig) => {
export const defaultMatch = (accepts: Accept[], config: acceptsConfig): string => {
const { supports, default: defaultSupport } = config
const accept = accepts.sort((a, b) => b.q - a.q).find((accept) => supports.includes(accept.type))
return accept ? accept.type : defaultSupport
Expand All @@ -61,7 +61,7 @@ export const defaultMatch = (accepts: Accept[], config: acceptsConfig) => {
* })
* ```
*/
export const accepts = (c: Context, options: acceptsOptions) => {
export const accepts = (c: Context, options: acceptsOptions): string => {
const acceptHeader = c.req.header(options.header)
if (!acceptHeader) {
return options.default
Expand Down
2 changes: 1 addition & 1 deletion deno_dist/helper/adapter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const env = <T extends Record<string, unknown>, C extends Context = Conte
return runtimeEnvHandlers[runtime]()
}

export const getRuntimeKey = () => {
export const getRuntimeKey = (): Runtime => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const global = globalThis as any

Expand Down
2 changes: 1 addition & 1 deletion deno_dist/helper/cookie/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export const setSignedCookie = async (
c.header('set-cookie', cookie, { append: true })
}

export const deleteCookie = (c: Context, name: string, opt?: CookieOptions) => {
export const deleteCookie = (c: Context, name: string, opt?: CookieOptions): string | undefined => {
const deletedCookie = getCookie(c, name)
setCookie(c, name, '', { ...opt, maxAge: 0 })
return deletedCookie
Expand Down
16 changes: 8 additions & 8 deletions deno_dist/helper/css/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ export const PSEUDO_GLOBAL_SELECTOR = ':-hono-global'
export const isPseudoGlobalSelectorRe = new RegExp(`^${PSEUDO_GLOBAL_SELECTOR}{(.*)}$`)
export const DEFAULT_STYLE_ID = 'hono-css'

export const SELECTOR = Symbol()
export const CLASS_NAME = Symbol()
export const STYLE_STRING = Symbol()
export const SELECTORS = Symbol()
export const EXTERNAL_CLASS_NAMES = Symbol()
const CSS_ESCAPED = Symbol()
export const SELECTOR: unique symbol = Symbol()
export const CLASS_NAME: unique symbol = Symbol()
export const STYLE_STRING: unique symbol = Symbol()
export const SELECTORS: unique symbol = Symbol()
export const EXTERNAL_CLASS_NAMES: unique symbol = Symbol()
const CSS_ESCAPED: unique symbol = Symbol()

export interface CssClassName {
[SELECTOR]: string
Expand Down Expand Up @@ -49,12 +49,12 @@ const toHash = (str: string): string => {
return 'css-' + out
}

const cssStringReStr = [
const cssStringReStr: string = [
'"(?:(?:\\\\[\\s\\S]|[^"\\\\])*)"', // double quoted string
// eslint-disable-next-line quotes
"'(?:(?:\\\\[\\s\\S]|[^'\\\\])*)'", // single quoted string
].join('|')
const minifyCssRe = new RegExp(
const minifyCssRe: RegExp = new RegExp(
[
'(' + cssStringReStr + ')', // $1: quoted string

Expand Down
53 changes: 40 additions & 13 deletions deno_dist/helper/css/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,36 @@ type usedClassNameData = [
Record<string, true> // class name already added
]

interface CssType {
(strings: TemplateStringsArray, ...values: CssVariableType[]): Promise<string>
}

interface CxType {
(
...args: (CssClassName | Promise<string> | string | boolean | null | undefined)[]
): Promise<string>
}

interface KeyframesType {
(strings: TemplateStringsArray, ...values: CssVariableType[]): CssClassNameCommon
}

interface ViewTransitionType {
(strings: TemplateStringsArray, ...values: CssVariableType[]): Promise<string>
(content: Promise<string>): Promise<string>
(): Promise<string>
}

interface StyleType {
(args?: { children?: Promise<string> }): HtmlEscapedString
}

/**
* @experimental
* `createCssContext` is an experimental feature.
* The API might be changed.
*/
export const createCssContext = ({ id }: { id: Readonly<string> }) => {
export const createCssContext = ({ id }: { id: Readonly<string> }): DefaultContextType => {
const [cssJsxDomObject, StyleRenderToDom] = createCssJsxDomObjects({ id })

const contextMap: WeakMap<object, usedClassNameData> = new WeakMap()
Expand Down Expand Up @@ -106,13 +130,11 @@ export const createCssContext = ({ id }: { id: Readonly<string> }) => {
return promise
}

const css = (strings: TemplateStringsArray, ...values: CssVariableType[]): Promise<string> => {
const css: CssType = (strings, ...values) => {
return newCssClassNameObject(cssCommon(strings, values))
}

const cx = (
...args: (CssClassName | Promise<string> | string | boolean | null | undefined)[]
): Promise<string> => {
const cx: CxType = (...args) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
args = cxCommon(args as any) as any
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -121,20 +143,15 @@ export const createCssContext = ({ id }: { id: Readonly<string> }) => {

const keyframes = keyframesCommon

type ViewTransitionType = {
(strings: TemplateStringsArray, ...values: CssVariableType[]): Promise<string>
(content: Promise<string>): Promise<string>
(): Promise<string>
}
const viewTransition: ViewTransitionType = ((
strings: TemplateStringsArray | Promise<string> | undefined,
...values: CssVariableType[]
): Promise<string> => {
) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return newCssClassNameObject(viewTransitionCommon(strings as any, values))
}) as ViewTransitionType

const Style = ({ children }: { children?: Promise<string> } = {}) =>
const Style: StyleType = ({ children } = {}) =>
children
? raw(`<style id="${id}">${(children as unknown as CssClassName)[STYLE_STRING]}</style>`)
: raw(`<style id="${id}"></style>`)
Expand All @@ -150,7 +167,17 @@ export const createCssContext = ({ id }: { id: Readonly<string> }) => {
}
}

const defaultContext = createCssContext({ id: DEFAULT_STYLE_ID })
interface DefaultContextType {
css: CssType
cx: CxType
keyframes: KeyframesType
viewTransition: ViewTransitionType
Style: StyleType
}

const defaultContext: DefaultContextType = createCssContext({
id: DEFAULT_STYLE_ID,
})

/**
* @experimental
Expand Down
4 changes: 2 additions & 2 deletions deno_dist/helper/dev/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ interface RouteData {
isMiddleware: boolean
}

const handlerName = (handler: Function) => {
const handlerName = (handler: Function): string => {
return handler.name || (isMiddleware(handler) ? '[middleware]' : '[handler]')
}

Expand Down Expand Up @@ -68,7 +68,7 @@ export const showRoutes = <E extends Env>(hono: Hono<E>, opts?: ShowRoutesOption
})
}

export const getRouterName = <E extends Env>(app: Hono<E>) => {
export const getRouterName = <E extends Env>(app: Hono<E>): string => {
app.router.match('GET', '/')
return app.router.name
}
6 changes: 3 additions & 3 deletions deno_dist/helper/factory/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ export class Factory<E extends Env = any, P extends string = any> {
* @experimental
* `createApp` is an experimental feature.
*/
createApp = () => {
createApp = (): Hono<E> => {
const app = new Hono<E>()
if (this.initApp) {
this.initApp(app)
Expand All @@ -234,8 +234,8 @@ export class Factory<E extends Env = any, P extends string = any> {

export const createFactory = <E extends Env = any, P extends string = any>(init?: {
initApp?: InitApp<E>
}) => new Factory<E, P>(init)
}): Factory<E, P> => new Factory<E, P>(init)

export const createMiddleware = <E extends Env = any, P extends string = any, I extends Input = {}>(
middleware: MiddlewareHandler<E, P, I>
) => createFactory<E, P>().createMiddleware<I>(middleware)
): MiddlewareHandler<E, P, I> => createFactory<E, P>().createMiddleware<I>(middleware)
2 changes: 1 addition & 1 deletion deno_dist/helper/streaming/sse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export const streamSSE = (
c: Context,
cb: (stream: SSEStreamingApi) => Promise<void>,
onError?: (e: Error, stream: SSEStreamingApi) => Promise<void>
) => {
): Response => {
const { readable, writable } = new TransformStream()
const stream = new SSEStreamingApi(writable, readable)

Expand Down
4 changes: 3 additions & 1 deletion deno_dist/helper/testing/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { hc } from '../../client/index.ts'
import type { Client } from '../../client/types.ts'
import type { ExecutionContext } from '../../context.ts'
import type { Hono } from '../../hono.ts'
import type { UnionToIntersection } from '../../utils/types.ts'

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type ExtractEnv<T> = T extends Hono<infer E, any, any> ? E : never
Expand All @@ -10,7 +12,7 @@ export const testClient = <T extends Hono<any, any, any>>(
app: T,
Env?: ExtractEnv<T>['Bindings'] | {},
executionCtx?: ExecutionContext
) => {
): UnionToIntersection<Client<T>> => {
const customFetch = (input: RequestInfo | URL, init?: RequestInit) => {
return app.request(input, init, Env, executionCtx)
}
Expand Down
6 changes: 3 additions & 3 deletions deno_dist/hono-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ class Hono<
* })
* ```
*/
onError = (handler: ErrorHandler<E>) => {
onError = (handler: ErrorHandler<E>): Hono<E, S, BasePath> => {
this.errorHandler = handler
return this
}
Expand All @@ -247,7 +247,7 @@ class Hono<
* ```
* @see https://hono.dev/api/hono#not-found
*/
notFound = (handler: NotFoundHandler<E>) => {
notFound = (handler: NotFoundHandler<E>): Hono<E, S, BasePath> => {
this.notFoundHandler = handler
return this
}
Expand Down Expand Up @@ -396,7 +396,7 @@ class Hono<
requestInit?: RequestInit,
Env?: E['Bindings'] | {},
executionCtx?: ExecutionContext
) => {
): Response | Promise<Response> => {
if (input instanceof Request) {
if (requestInit !== undefined) {
input = new Request(input, requestInit)
Expand Down
2 changes: 1 addition & 1 deletion deno_dist/jsx/dom/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { globalContexts } from '../context.ts'
import { Fragment } from './jsx-runtime.ts'
import { setInternalTagFlag } from './utils.ts'

export const createContextProviderFunction = <T>(values: T[]) =>
export const createContextProviderFunction = <T>(values: T[]): Function =>
setInternalTagFlag(({ value, children }: { value: T; children: Child[] }) => {
if (!children) {
return undefined
Expand Down
11 changes: 10 additions & 1 deletion deno_dist/jsx/dom/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,16 @@ const splitRule = (rule: string): string[] => {
return result
}

export const createCssJsxDomObjects = ({ id }: { id: Readonly<string> }) => {
interface CreateCssJsxDomObjectsType {
(args: { id: Readonly<string> }): readonly [
{
toString(this: CssClassName): string
},
FC<PropsWithChildren<void>>
]
}

export const createCssJsxDomObjects: CreateCssJsxDomObjectsType = ({ id }) => {
let styleSheet: CSSStyleSheet | null | undefined = undefined
const findStyleSheet = (): [CSSStyleSheet, Set<string>] | [] => {
if (!styleSheet) {
Expand Down
2 changes: 1 addition & 1 deletion deno_dist/jsx/dom/jsx-dev-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ export const jsxDEV = (tag: string | Function, props: Props, key?: string): JSXN
) as JSXNode
}

export const Fragment = (props: Record<string, unknown>) => jsxDEV('', props, undefined)
export const Fragment = (props: Record<string, unknown>): JSXNode => jsxDEV('', props, undefined)
2 changes: 1 addition & 1 deletion deno_dist/jsx/dom/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DOM_INTERNAL_TAG } from '../constants.ts'

export const setInternalTagFlag = (fn: Function) => {
export const setInternalTagFlag = (fn: Function): Function => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
;(fn as any)[DOM_INTERNAL_TAG] = true
return fn
Expand Down
5 changes: 4 additions & 1 deletion deno_dist/jsx/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ export type EffectData = [
(() => void) | undefined // effect
]

const resolvedPromiseValueMap = new WeakMap<Promise<unknown>, unknown>()
const resolvedPromiseValueMap: WeakMap<Promise<unknown>, unknown> = new WeakMap<
Promise<unknown>,
unknown
>()

const isDepsChanged = (
prevDeps: readonly unknown[] | undefined,
Expand Down
6 changes: 5 additions & 1 deletion deno_dist/jsx/jsx-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ export { jsxDEV as jsx, Fragment } from './jsx-dev-runtime.ts'
export { jsxDEV as jsxs } from './jsx-dev-runtime.ts'

import { raw, html } from '../helper/html/index.ts'
import type { HtmlEscapedString } from '../utils/html.ts'
export { html as jsxTemplate }
export const jsxAttr = (name: string, value: string | Promise<string>) =>
export const jsxAttr = (
name: string,
value: string | Promise<string>
): HtmlEscapedString | Promise<HtmlEscapedString> =>
typeof value === 'string' ? raw(name + '="' + html`${value}` + '"') : html`${name}="${value}"`
export const jsxEscape = (value: string) => value
4 changes: 3 additions & 1 deletion deno_dist/middleware/jsx-renderer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import type { Context, PropsForRenderer } from '../../context.ts'
import { html, raw } from '../../helper/html/index.ts'
import { jsx, createContext, useContext, Fragment } from '../../jsx/index.ts'
import type { FC, PropsWithChildren, JSXNode } from '../../jsx/index.ts'
import type { Context as JSXContext } from '../../jsx/index.ts'
import { renderToReadableStream } from '../../jsx/streaming.ts'
import type { Env, Input, MiddlewareHandler } from '../../types.ts'
import type { HtmlEscapedString } from '../../utils/html.ts'

export const RequestContext = createContext<Context | null>(null)
export const RequestContext: JSXContext<Context<any, any, {}> | null> =
createContext<Context | null>(null)

type RendererOptions = {
docType?: boolean | string
Expand Down
2 changes: 1 addition & 1 deletion deno_dist/middleware/timing/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ interface TimingOptions {
crossOrigin: boolean | string | ((c: Context) => boolean | string)
}

const getTime = () => {
const getTime = (): number => {
try {
return performance.now()
} catch {}
Expand Down
4 changes: 2 additions & 2 deletions deno_dist/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ export class HonoRequest<P extends string = '/', I extends Input['out'] = {}> {
* ```
* @see https://hono.dev/api/request#url
*/
get url() {
get url(): string {
return this.raw.url
}

Expand All @@ -303,7 +303,7 @@ export class HonoRequest<P extends string = '/', I extends Input['out'] = {}> {
* ```
* @see https://hono.dev/api/request#method
*/
get method() {
get method(): string {
return this.raw.method
}

Expand Down

0 comments on commit e5975ed

Please sign in to comment.