Skip to content

Instantly share code, notes, and snippets.

@cristianoc
Forked from zth/bun-headers.md
Created November 1, 2023 13:57

Revisions

  1. @zth zth revised this gist Nov 1, 2023. 2 changed files with 241 additions and 0 deletions.
    142 changes: 142 additions & 0 deletions bun-headers.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,142 @@
    TypeScript:
    ```typescript
    /**
    * This Fetch API interface allows you to perform various actions on HTTP
    * request and response headers. These actions include retrieving, setting,
    * adding to, and removing. A Headers object has an associated header list,
    * which is initially empty and consists of zero or more name and value
    * pairs.
    *
    * You can add to this using methods like append()
    *
    * In all methods of this interface, header names are matched by
    * case-insensitive byte sequence.
    */
    interface Headers {
    append(name: string, value: string): void;
    delete(name: string): void;
    get(name: string): string | null;
    has(name: string): boolean;
    set(name: string, value: string): void;
    entries(): IterableIterator<[string, string]>;
    keys(): IterableIterator<string>;
    values(): IterableIterator<string>;
    [Symbol.iterator](): IterableIterator<[string, string]>;
    forEach(
    callbackfn: (value: string, key: string, parent: Headers) => void,
    thisArg?: any,
    ): void;

    /**
    * Convert {@link Headers} to a plain JavaScript object.
    *
    * About 10x faster than `Object.fromEntries(headers.entries())`
    *
    * Called when you run `JSON.stringify(headers)`
    *
    * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is.
    */
    toJSON(): Record<string, string>;

    /**
    * Get the total number of headers
    */
    readonly count: number;

    /**
    * Get all headers matching the name
    *
    * Only supports `"Set-Cookie"`. All other headers are empty arrays.
    *
    * @param name - The header name to get
    *
    * @returns An array of header values
    *
    * @example
    * ```ts
    * const headers = new Headers();
    * headers.append("Set-Cookie", "foo=bar");
    * headers.append("Set-Cookie", "baz=qux");
    * headers.getAll("Set-Cookie"); // ["foo=bar", "baz=qux"]
    * ```
    */
    getAll(name: "set-cookie" | "Set-Cookie"): string[];
    }

    declare var Headers: {
    prototype: Headers;
    new (init?: HeadersInit): Headers;
    };
    ```

    ReScript:
    ```rescript
    module HeadersInit = {
    @unboxed type t = FromArray(array<(string, string)>) | FromDict(Js.Dict.t<string>)
    }
    /**
    * This Fetch API interface allows you to perform various actions on HTTP
    * request and response headers. These actions include retrieving, setting,
    * adding to, and removing. A Headers object has an associated header list,
    * which is initially empty and consists of zero or more name and value
    * pairs.
    *
    * You can add to this using methods like append()
    *
    * In all methods of this interface, header names are matched by
    * case-insensitive byte sequence.
    */
    module Headers = {
    type t
    @new external make: unit => t = "Headers"
    @new external makeWithInit: HeadersInit.t => t = "Headers"
    @send external append: (t, string, string) => unit = "append"
    @send external delete: (t, string) => unit = "delete"
    @return(nullable) @send external get: (t, string) => option<string> = "get"
    @send external has: (t, string) => bool = "has"
    @send external set: (t, string, string) => unit = "set"
    @send external entries: t => Iterator.t<(string, string)> = "entries"
    @send external keys: t => Iterator.t<string> = "keys"
    @send external values: t => Iterator.t<string> = "values"
    @send external forEach: (t, (string, string, t) => unit) => unit = "forEach"
    /**
    * Convert {@link Headers} to a plain JavaScript object.
    *
    * About 10x faster than `Object.fromEntries(headers.entries())`
    *
    * Called when you run `JSON.stringify(headers)`
    *
    * Does not preserve insertion order. Well-known header names are lowercased. Other header names are left as-is.
    */
    @send
    external toJSON: t => Dict.t<string> = "toJSON"
    /**
    * Get the total number of headers
    */
    @get
    external count: t => int = "count"
    /**
    * Get all headers matching "Set-Cookie"
    *
    * Only supports `"Set-Cookie"`. All other headers are empty arrays.
    *
    * @returns An array of header values
    *
    * @example
    * ```rescript
    * let headers = Headers.make()
    * headers->Headers.append("Set-Cookie", "foo=bar")
    * headers->Headers.append("Set-Cookie", "baz=qux")
    * let cookies = headers->Headers.getAllCookies // ["foo=bar", "baz=qux"]
    * ```
    */
    @send
    external getAllCookies: (t, @as("Set-Cookie") _) => array<string> = "getAll"
    }
    ```
    99 changes: 99 additions & 0 deletions bun-urlsearchparams.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,99 @@
    TypeScript:
    ```typescript
    interface URLSearchParams {
    /** Appends a specified key/value pair as a new search parameter. */
    append(name: string, value: string): void;
    /** Deletes the given search parameter, and its associated value, from the list of all search parameters. */
    delete(name: string): void;
    /** Returns the first value associated to the given search parameter. */
    get(name: string): string | null;
    /** Returns all the values association with a given search parameter. */
    getAll(name: string): string[];
    /** Returns a Boolean indicating if such a search parameter exists. */
    has(name: string): boolean;
    /** Sets the value associated to a given search parameter to the given value. If there were several values, delete the others. */
    set(name: string, value: string): void;
    sort(): void;
    entries(): IterableIterator<[string, string]>;
    /** Returns an iterator allowing to go through all keys of the key/value pairs of this search parameter. */
    keys(): IterableIterator<string>;
    /** Returns an iterator allowing to go through all values of the key/value pairs of this search parameter. */
    values(): IterableIterator<string>;
    forEach(
    callbackfn: (value: string, key: string, parent: URLSearchParams) => void,
    thisArg?: any,
    ): void;
    /** Returns a string containing a query string suitable for use in a URL. Does not include the question mark. */
    toString(): string;
    [Symbol.iterator](): IterableIterator<[string, string]>;
    }

    declare var URLSearchParams: {
    prototype: URLSearchParams;
    new (
    init?: string[][] | Record<string, string> | string | URLSearchParams,
    ): URLSearchParams;
    toString(): string;
    };
    ```

    ReScript:
    ```rescript
    module URLSearchParams = {
    type t
    @unboxed type init = Object(Dict.t<string>) | String(string) | Array(array<array<string>>)
    @new external make: unit => t = "URLSearchParams"
    @new external makeWithInit: init => t = "URLSearchParams"
    /** Appends a specified key/value pair as a new search parameter. */
    @send
    external append: (t, string, string) => unit = "append"
    /** Deletes the given search parameter, and its associated value, from the list of all search parameters. */
    @send
    external delete: (t, string) => unit = "delete"
    /** Returns the first value associated to the given search parameter. */
    @send
    @return(nullable)
    external get: (t, string) => option<string> = "get"
    /** Returns all the values association with a given search parameter. */
    @send
    external getAll: (t, string) => array<string> = "getAll"
    /** Returns a Boolean indicating if such a search parameter exists. */
    @send
    external has: (t, string) => bool = "has"
    /** Sets the value associated to a given search parameter to the given value. If there were several values, delete the others. */
    @send
    external set: (t, string, string) => unit = "set"
    /** Sorts all key/value pairs, if any, by their keys. */
    @send
    external sort: t => unit = "sort"
    /** Returns an iterator allowing to go through all entries of the key/value pairs. */
    @send
    external entries: t => Iterator.t<(string, string)> = "entries"
    /** Returns an iterator allowing to go through all keys of the key/value pairs of this search parameter. */
    @send
    external keys: t => Iterator.t<string> = "keys"
    /** Returns an iterator allowing to go through all values of the key/value pairs of this search parameter. */
    @send
    external values: t => Iterator.t<string> = "values"
    /** Executes a provided function once for each key/value pair. */
    @send
    external forEach: (t, (string, string, t) => unit) => unit = "forEach"
    /** Returns a string containing a query string suitable for use in a URL. Does not include the question mark. */
    @send
    external toString: t => string = "toString"
    }
    ```
  2. @zth zth revised this gist Nov 1, 2023. 1 changed file with 21 additions and 0 deletions.
    21 changes: 21 additions & 0 deletions untagged-variants.md
    Original file line number Diff line number Diff line change
    @@ -79,6 +79,14 @@ export type BatchingOptions =
    export type YogaLogger = Record<LogLevel, (...args: any[]) => void>;

    export type LogLevel = 'debug' | 'info' | 'warn' | 'error';

    export type YogaMaskedErrorOpts = {
    maskError: MaskError;
    errorMessage: string;
    isDev?: boolean;
    };

    export type MaskError = (error: unknown, message: string, isDev?: boolean) => Error;
    ```
    ReScript:
    ```rescript
    @@ -106,6 +114,19 @@ type batchingOptions = {
    @unboxed type batchingConfig = | @as(true) True | @as(false) False | Options(batchingOptions)
    type maskErrorFn = (~error: unknown, ~message: string, ~isDev: option<bool>) => Exn.t
    type maskedErrorOpts = {
    maskError?: maskErrorFn,
    errorMessage?: string,
    isDev?: bool,
    }
    @unboxed
    type maskedErrors =
    | @as(true) True
    | @as(false) False
    | Options(maskedErrorOpts)
    /**
    * Configuration options for the server
    */
  3. @zth zth revised this gist Nov 1, 2023. 1 changed file with 15 additions and 0 deletions.
    15 changes: 15 additions & 0 deletions untagged-variants.md
    Original file line number Diff line number Diff line change
    @@ -64,6 +64,21 @@ export type YogaServerOptions<TServerContext, TUserContext> = {
    */
    batching?: BatchingOptions | undefined;
    };

    export type BatchingOptions =
    | boolean
    | {
    /**
    * You can limit the number of batched operations per request.
    *
    * @default 10
    */
    limit?: number;
    };

    export type YogaLogger = Record<LogLevel, (...args: any[]) => void>;

    export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
    ```
    ReScript:
    ```rescript
  4. @zth zth created this gist Nov 1, 2023.
    160 changes: 160 additions & 0 deletions untagged-variants.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,160 @@
    TypeScript:
    ```typescript
    export type YogaServerOptions<TServerContext, TUserContext> = {
    schema?: YogaSchemaDefinition<TServerContext, TUserContext> | undefined;

    /**
    * Enable/disable logging or provide a custom logger.
    * @default true
    */
    logging?: boolean | YogaLogger | LogLevel | undefined;
    /**
    * Prevent leaking unexpected errors to the client. We highly recommend enabling this in production.
    * If you throw `EnvelopError`/`GraphQLError` within your GraphQL resolvers then that error will be sent back to the client.
    *
    * You can lean more about this here:
    * @see https://graphql-yoga.vercel.app/docs/features/error-masking
    *
    * @default true
    */
    maskedErrors?: boolean | Partial<YogaMaskedErrorOpts> | undefined;

    /**
    * GraphQL endpoint
    * So you need to define it explicitly if GraphQL API lives in a different path other than `/graphql`
    *
    * @default "/graphql"
    */
    graphqlEndpoint?: string | undefined;

    /**
    * Readiness check endpoint
    *
    * @default "/health"
    */
    healthCheckEndpoint?: string | undefined;

    /**
    * Whether the landing page should be shown.
    */
    landingPage?: boolean | undefined;

    /**
    * GraphiQL options
    *
    * @default true
    */
    graphiql?: GraphiQLOptionsOrFactory<TServerContext> | undefined;

    /**
    * GraphQL Multipart Request spec support
    *
    * @see https://github.com/jaydenseric/graphql-multipart-request-spec
    *
    * @default true
    */
    multipart?: boolean | undefined;
    id?: string | undefined;
    /**
    * Batching RFC Support configuration
    *
    * @see https://github.com/graphql/graphql-over-http/blob/main/rfcs/Batching.md
    *
    * @default false
    */
    batching?: BatchingOptions | undefined;
    };
    ```
    ReScript:
    ```rescript
    type logFn = unknown => unit
    type yogaLogger = {debug: logFn, info: logFn, warn: logFn, error: logFn}
    @unboxed
    type logging =
    | @as(true) True
    | @as(false) False
    | YogaLogger(yogaLogger)
    | @as("debug") LogLevelDebug
    | @as("info") LogLevelInfo
    | @as("warn") LogLevelWarn
    | @as("error") LogLevelError
    type batchingOptions = {
    /**
    * You can limit the number of batched operations per request.
    *
    * @default 10
    */
    limit?: int,
    }
    @unboxed type batchingConfig = | @as(true) True | @as(false) False | Options(batchingOptions)
    /**
    * Configuration options for the server
    */
    type yogaServerOptions<'tServerContext, 'tUserContext> = {
    schema: YogaSchemaDefinition.t<'tServerContext, 'tUserContext>,
    /**
    * Enable/disable logging or provide a custom logger.
    * @default true
    */
    logging?: logging,
    /**
    * Prevent leaking unexpected errors to the client. We highly recommend enabling this in production.
    * If you throw `EnvelopError`/`GraphQLError` within your GraphQL resolvers then that error will be sent back to the client.
    *
    * You can lean more about this here:
    * @see https://graphql-yoga.vercel.app/docs/features/error-masking
    *
    * @default true
    */
    maskedErrors?: maskedErrors,
    /**
    * GraphQL endpoint
    * So you need to define it explicitly if GraphQL API lives in a different path other than `/graphql`
    *
    * @default "/graphql"
    */
    graphqlEndpoint?: string,
    /**
    * Readiness check endpoint
    *
    * @default "/health"
    */
    healthCheckEndpoint?: string,
    /**
    * Whether the landing page should be shown.
    */
    landingPage?: bool,
    parserCache?: bool,
    validationCache?: bool,
    /**
    * GraphQL Multipart Request spec support
    *
    * @see https://github.com/jaydenseric/graphql-multipart-request-spec
    *
    * @default true
    */
    multipart?: bool,
    id?: string,
    /**
    * Batching RFC Support configuration
    *
    * @see https://github.com/graphql/graphql-over-http/blob/main/rfcs/Batching.md
    *
    * @default false
    */
    batching?: batchingConfig,
    /**
    * Whether to use the legacy Yoga Server-Sent Events and not
    * the GraphQL over SSE spec's distinct connection mode.
    *
    * @default true
    *
    * @deprecated Consider using GraphQL over SSE spec instead by setting this to `false`. Starting with the next major release, this flag will default to `false`.
    */
    legacySse?: bool,
    }
    ```