Skip to content

Our docs' function signatures can get unreadable in a hurry. #21

@dead-claudia

Description

@dead-claudia

Currently, we use a relatively unusual signature mechanism to document how our functions are called. It's nice and concise for a few simple cases, but it has a habit of getting in the way of readability and accuracy in the more complicated scenarios:

I've only covered about a third of the signatures in links above, and only individual bits of them in the bulleted list. But if you actually look at how it renders, I'd estimate about half of them have issues generated from the signature format itself.


What I'm really proposing here is that we should change our signature format to be much more readable. I'm thinking of something like this, using m() as an example:

### Signature

```js
vnode = m(selector, attrs = {}, ...children)
vnode = m(selector, attrs = {}, [...children])
```

- `selector` - A component or [simple CSS selector](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors#Simple_selectors) string.
- `attrs` - A key/value map of HTML attributes, element properties, and/or [lifecycle methods](https://mithril.js.org/hyperscript.html#lifecycle-methods).
- `children` - A list of vnode children, including strings, numbers, vnodes, or arrays of vnode children. `null`, `undefined`, and `false` represent holes.

Returns a hyperscript vnode for Mithril to later [render](https://mithril.js.org/render.html).

[*How to read signatures*](https://mithril.js.org/signatures.md)

Rendered:

Signature

vnode = m(selector, attrs = {}, ...children)
vnode = m(selector, attrs = {}, [...children])
  • selector - A component or simple CSS selector string.
  • attrs - A key/value map of HTML attributes, element properties, and/or lifecycle methods.
  • children - A list of vnode children, including strings, numbers, vnodes, or arrays of vnode children. null, undefined, and false represent holes.

Returns a hyperscript vnode for Mithril to later render.

How to read signatures

For comparison, here's the existing docs:

`vnode = m(selector, attrs, children)`

Argument     | Type                                       | Required | Description
------------ | ------------------------------------------ | -------- | ---
`selector`   | `String|Object`                            | Yes      | A CSS selector or a [component](components.md)
`attrs`      | `Object`                                   | No       | HTML attributes or element properties
`children`   | `Array<Vnode>|String|Number|Boolean`       | No       | Child [vnodes](vnodes.md#structure). Can be written as [splat arguments](signatures.md#splats)
**returns**  | `Vnode`                                    |          | A [vnode](vnodes.md#structure)

[How to read signatures](signatures.md)

Rendered:

vnode = m(selector, attrs, children)

Argument Type Required Description
selector String|Object Yes A CSS selector or a component
attrs Object No HTML attributes or element properties
children Array<Vnode>|String|Number|Boolean No Child vnodes. Can be written as splat arguments
returns Vnode A vnode

How to read signatures

I'm open to other ideas, like using TypeScript types, as long as they're an improvement over what we currently have.

In case you're curious how I'd change m.request, here's how I'd do that:
### Signature

```js
promise = m.request(url, options = {})
promise = m.request({url, ...options})

promise.then(
    function(result) { ... },
    function(error) { ... }
)
```

- `url` - The URL to send the request to. It may be either absolute or relative, and it may contain [interpolations](#dynamic-urls).
- Options:
    - `options.method = "GET"` - The [HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) to use.
    - `options.data = undefined` - The data to be interpolated into the URL and serialized into the querystring (for GET requests) or body (for other types of requests).
    - `options.async = true` - Whether the request should be fired asynchronously.
    - `options.user = null` - The username for [HTTP basic authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication).
    - `options.password = null` - The password for [HTTP basic authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication).
    - `options.withCredentials = false` - Whether to send cookies to 3rd party domains.
    - `options.timeout = undefined` - The amount of milliseconds a request can take before automatically being [terminated](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/timeout).
    - `options.responseType = undefined` - The expected [type](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType) of the response.
    - `options.config(xhr) -> newXhr = function(x) { return x }` - Exposes the underlying XMLHttpRequest object for low-level configuration.
    - `options.headers = {}` - Headers to append to the request before sending it, applied right before `options.config`.
    - `new options.type(response) -> result = ...` - A constructor to be applied to each object in the response if it's an array or the response itself otherwise. By default, the response is used directly.
    - `options.serialize(options.data) -> string = ...` - Serialize the data into a string. By default, this returns `options.data` if it's an instance of [`FormData`](https://developer.mozilla.org/en/docs/Web/API/FormData) or `JSON.stringify(options.data)` otherwise.
    - `options.deserialize(responseText) -> response = ...` - Deserialize `xhr.responseText` into the response data. By default, this returns `null` for empty responses and `JSON.parse(responseText)` otherwise.
    - `options.extract(xhr, options) -> response = ...` - A hook to specify how the [`XMLHttpRequest`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) response should be read, useful for processing response data, reading headers, and cookies. By default, this returns `options.deserialize(xhr.responseText)` for requests that were successful (status either between 200 and 299 or 304), throws an error for requests that were not.
    - `options.useBody = (options.method !== "GET")` - Force the use of the HTTP body section for `data` in `GET` requests when set to `true`, or the use of querystring for other HTTP methods when set to `false`.
    - `options.background = false` - If `false`, redraws mounted components upon completion of the request. If `true`, it does not.

Returns a promise to the response, after it's been piped through `options.extract`, `options.deserialize`, and `options.type` as appropriate. Promise rejections outside the above hooks model request errors, and have a few special properties:

- `error.message` - The raw response text
- `error.code` - The server status code
- `error.response` - The parsed response

If a custom `options.extract` is provided, `deserialize` will be skipped and the value returned from the extract callback will be left as-is when the promise resolves. Furthermore, exceptions are *not* thrown when the server response status code indicates an error. Instead, it's expected that you determine in the callback whether the error was in fact a server error or a normal response.

[How to read signatures](https://mithril.js.org/signatures.md)

Rendered:

Signature

promise = m.request(url, options = {})
promise = m.request({url, ...options})

promise.then(
    function(result) { ... },
    function(error) { ... }
)
  • url - The URL to send the request to. It may be either absolute or relative, and it may contain interpolations.
  • Options:
    • options.method = "GET" - The HTTP method to use.
    • options.data = undefined - The data to be interpolated into the URL and serialized into the querystring (for GET requests) or body (for other types of requests).
    • options.async = true - Whether the request should be fired asynchronously.
    • options.user = null - The username for HTTP basic authentication.
    • options.password = null - The password for HTTP basic authentication.
    • options.withCredentials = false - Whether to send cookies to 3rd party domains.
    • options.timeout = undefined - The amount of milliseconds a request can take before automatically being terminated.
    • options.responseType = undefined - The expected type of the response.
    • options.config(xhr) -> newXhr = function(x) { return x } - Exposes the underlying XMLHttpRequest object for low-level configuration.
    • options.headers = {} - Headers to append to the request before sending it, applied right before options.config.
    • new options.type(response) -> result = ... - A constructor to be applied to each object in the response if it's an array or the response itself otherwise. By default, the response is used directly.
    • options.serialize(options.data) -> string = ... - Serialize the data into a string. By default, this returns options.data if it's an instance of FormData or JSON.stringify(options.data) otherwise.
    • options.deserialize(responseText) -> response = ... - Deserialize xhr.responseText into the response data. By default, this returns null for empty responses and JSON.parse(responseText) otherwise.
    • options.extract(xhr, options) -> response = ... - A hook to specify how the XMLHttpRequest response should be read, useful for processing response data, reading headers, and cookies. By default, this returns options.deserialize(xhr.responseText) for requests that were successful (status either between 200 and 299 or 304), throws an error for requests that were not.
    • options.useBody = (options.method !== "GET") - Force the use of the HTTP body section for data in GET requests when set to true, or the use of querystring for other HTTP methods when set to false.
    • options.background = false - If false, redraws mounted components upon completion of the request. If true, it does not.

Returns a promise to the response, after it's been piped through options.extract, options.deserialize, and options.type as appropriate. Promise rejections outside the above hooks model request errors, and have a few special properties:

  • error.message - The raw response text
  • error.code - The server status code
  • error.response - The parsed response

If a custom options.extract is provided, deserialize will be skipped and the value returned from the extract callback will be left as-is when the promise resolves. Furthermore, exceptions are not thrown when the server response status code indicates an error. Instead, it's expected that you determine in the callback whether the error was in fact a server error or a normal response.

How to read signatures

For comparison, here's the original docs:

### Signature

`promise = m.request([url,] options)`

Argument                  | Type                              | Required | Description
------------------------- | --------------------------------- | -------- | ---
`url`                     | `String`                          | No       | If present, it's equivalent to having the options `{method: "GET", url: url}`. Values passed to the `options` argument override options set via this shorthand.
`options.method`          | `String`                          | No       | The HTTP method to use. This value should be one of the following: `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD` or `OPTIONS`. Defaults to `GET`.
`options.url`             | `String`                          | Yes      | The URL to send the request to. The URL may be either absolute or relative, and it may contain [interpolations](#dynamic-urls).
`options.data`            | `any`                             | No       | The data to be interpolated into the URL and serialized into the querystring (for GET requests) or body (for other types of requests).
`options.async`           | `Boolean`                         | No       | Whether the request should be asynchronous. Defaults to `true`.
`options.user`            | `String`                          | No       | A username for HTTP authorization. Defaults to `undefined`.
`options.password`        | `String`                          | No       | A password for HTTP authorization. Defaults to `undefined`. This option is provided for `XMLHttpRequest` compatibility, but you should avoid using it because it sends the password in plain text over the network.
`options.withCredentials` | `Boolean`                         | No       | Whether to send cookies to 3rd party domains. Defaults to `false`
`options.timeout`         | `Number`                          | No       | The amount of milliseconds a request can take before automatically being [terminated](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/timeout).  Defaults to `undefined`.
`options.responseType`    | `String`                          | No       | The expected [type](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType) of the response. Defaults to `undefined`.
`options.config`          | `xhr = Function(xhr)`             | No       | Exposes the underlying XMLHttpRequest object for low-level configuration. Defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function).
`options.headers`         | `Object`                          | No       | Headers to append to the request before sending it (applied right before `options.config`).
`options.type`            | `any = Function(any)`             | No       | A constructor to be applied to each object in the response. Defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function).
`options.serialize`       | `string = Function(any)`          | No       | A serialization method to be applied to `data`. Defaults to `JSON.stringify`, or if `options.data` is an instance of [`FormData`](https://developer.mozilla.org/en/docs/Web/API/FormData), defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function) (i.e. `function(value) {return value}`).
`options.deserialize`     | `any = Function(string)`          | No       | A deserialization method to be applied to the `xhr.responseText`. Defaults to a small wrapper around `JSON.parse` that returns `null` for empty responses. If `extract` is defined, `deserialize` will be skipped.
`options.extract`         | `any = Function(xhr, options)`    | No       | A hook to specify how the XMLHttpRequest response should be read. Useful for processing response data, reading headers and cookies. By default this is a function that returns `xhr.responseText`, which is in turn passed to `deserialize`. If a custom `extract` callback is provided, the `xhr` parameter is the XMLHttpRequest instance used for the request, and `options` is the object that was passed to the `m.request` call. Additionally, `deserialize` will be skipped and the value returned from the extract callback will be left as-is when the promise resolves. Furthermore, when an extract callback is provided, exceptions are *not* thrown when the server response status code indicates an error.
`options.useBody`         | `Boolean`                         | No       | Force the use of the HTTP body section for `data` in `GET` requests when set to `true`, or the use of querystring for other HTTP methods when set to `false`. Defaults to `false` for `GET` requests and `true` for other methods.
`options.background`      | `Boolean`                         | No       | If `false`, redraws mounted components upon completion of the request. If `true`, it does not. Defaults to `false`.
**returns**               | `Promise`                         |          | A promise that resolves to the response data, after it has been piped through the `extract`, `deserialize` and `type` methods

[How to read signatures](signatures.md)

Rendered:

Signature

promise = m.request([url,] options)

Argument Type Required Description
url String No If present, it's equivalent to having the options {method: "GET", url: url}. Values passed to the options argument override options set via this shorthand.
options.method String No The HTTP method to use. This value should be one of the following: GET, POST, PUT, PATCH, DELETE, HEAD or OPTIONS. Defaults to GET.
options.url String Yes The URL to send the request to. The URL may be either absolute or relative, and it may contain interpolations.
options.data any No The data to be interpolated into the URL and serialized into the querystring (for GET requests) or body (for other types of requests).
options.async Boolean No Whether the request should be asynchronous. Defaults to true.
options.user String No A username for HTTP authorization. Defaults to undefined.
options.password String No A password for HTTP authorization. Defaults to undefined. This option is provided for XMLHttpRequest compatibility, but you should avoid using it because it sends the password in plain text over the network.
options.withCredentials Boolean No Whether to send cookies to 3rd party domains. Defaults to false
options.timeout Number No The amount of milliseconds a request can take before automatically being terminated. Defaults to undefined.
options.responseType String No The expected type of the response. Defaults to undefined.
options.config xhr = Function(xhr) No Exposes the underlying XMLHttpRequest object for low-level configuration. Defaults to the identity function.
options.headers Object No Headers to append to the request before sending it (applied right before options.config).
options.type any = Function(any) No A constructor to be applied to each object in the response. Defaults to the identity function.
options.serialize string = Function(any) No A serialization method to be applied to data. Defaults to JSON.stringify, or if options.data is an instance of FormData, defaults to the identity function (i.e. function(value) {return value}).
options.deserialize any = Function(string) No A deserialization method to be applied to the xhr.responseText. Defaults to a small wrapper around JSON.parse that returns null for empty responses. If extract is defined, deserialize will be skipped.
options.extract any = Function(xhr, options) No A hook to specify how the XMLHttpRequest response should be read. Useful for processing response data, reading headers and cookies. By default this is a function that returns xhr.responseText, which is in turn passed to deserialize. If a custom extract callback is provided, the xhr parameter is the XMLHttpRequest instance used for the request, and options is the object that was passed to the m.request call. > Additionally, deserialize will be skipped and the value returned from the extract callback will be left as-is when the promise resolves. Furthermore, when an extract callback is provided, exceptions are not thrown when the server response status code indicates an error.
options.useBody Boolean No Force the use of the HTTP body section for data in GET requests when set to true, or the use of querystring for other HTTP methods when set to false. Defaults to false for GET requests and true for other methods.
options.background Boolean No If false, redraws mounted components upon completion of the request. If true, it does not. Defaults to false.
returns Promise A promise that resolves to the response data, after it has been piped through the extract, deserialize and type methods

How to read signatures

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Low priority

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions