Repository: honojs/hono
File: src/context.ts (TypeScript)

Code before:
  | Record<string, string>
  | Headers

interface ResponseInit<T extends StatusCode = StatusCode> {
  headers?: ResponseHeadersInit
  status?: T
  statusText?: string
}

type ResponseOrInit<T extends StatusCode = StatusCode> = ResponseInit<T> | Response

export const TEXT_PLAIN = 'text/plain; charset=UTF-8'

const setDefaultContentType = (contentType: string, headers?: HeaderRecord): HeaderRecord => {
  return {
    'Content-Type': contentType,
    ...headers,
  }
}

/**
 * This function ensures that the string is safely encoded,
 * and not double-encoded.
 * The input string may or may not escaped by encodeURI.
 */
const safeEncodeURI = (str: string) => {
  try {
    // decodeURI will throw if str contains %
    // In that case, we can assume that str is not encoded
    return encodeURI(decodeURI(str))
  } catch (e) {
    if (e instanceof URIError) {
      return encodeURI(str)
    }
    throw e
  }
}

export class Context<
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  E extends Env = any,
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  P extends string = any,
  I extends Input = {}
> {
  #rawRequest: Request
  #req: HonoRequest<P, I['out']> | undefined
  /**
   * `.env` can get bindings (environment variables, secrets, KV namespaces, D1 database, R2 bucket etc.) in Cloudflare Workers.
   *
   * @see {@link https://hono.dev/docs/api/context#env}

Review comment (suggestion):
I was a little unsure about this, but I think it would be better to move `safeEncodeURI` to `src/utils/url.ts`. It is only used in `src/contex.ts`, so it is not necessary, but since all other functions related to URL/URI are in that file, it would be better.

In that case, writing unit tests for `safeEncodeURI` in `src/utils/url.test.ts` will be good.

Code after:
  | Record<ResponseHeader, string>
  | Record<string, string>
  | Headers

interface ResponseInit<T extends StatusCode = StatusCode> {
  headers?: ResponseHeadersInit
  status?: T
  statusText?: string
}

type ResponseOrInit<T extends StatusCode = StatusCode> = ResponseInit<T> | Response

export const TEXT_PLAIN = 'text/plain; charset=UTF-8'

const setDefaultContentType = (contentType: string, headers?: HeaderRecord): HeaderRecord => {
  return {
    'Content-Type': contentType,
    ...headers,
  }
}

export class Context<
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  E extends Env = any,
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  P extends string = any,
  I extends Input = {}
> {
  #rawRequest: Request
  #req: HonoRequest<P, I['out']> | undefined
  /**
   * `.env` can get bindings (environment variables, secrets, KV namespaces, D1 database, R2 bucket etc.) in Cloudflare Workers.
   *
   * @see {@link https://hono.dev/docs/api/context#env}
   *
   * @example
   * ```ts
   * // Environment object for Cloudflare Workers
   * app.get('*', async c => {
   *   const counter = c.env.COUNTER
   * })
   * ```
   */
  env: E['Bindings'] = {}
  #var: Map<unknown, unknown> | undefined
  finalized: boolean = false
  /**
   * `.error` can get the error object from the middleware if the Handler throws an error.
   *
   * @see {@link https://hono.dev/docs/api/context#error}
   *