Weird Wide Web tools
GitHub Stars
Go to latest
import * as cav from "https://deno.land/x/cav@0.0.21/mod.ts";



An error class for describing exceptions during HTTP processing.



Serves HTTP requests with the given handler. (Stacks and Rpcs are handlers.) You can specify an object with a port and hostname option, which is the address to listen on. The default is port 8000 on hostname "". This is a re-export of the serve() function from https://deno.land/std/http/server.ts.



Creates a cookie tied to the given request and response headers. The keys provided will be used for cookie signing; if no keys are provided, a random fallback key will be used. Keys need to be provided in an array, making key rotation easier.


Constructs a new Client tied to a given base URL. The provided set of packers will be used everywhere that data is packed/unpacked when using this client, including web sockets.


Deserializes a value returned by serialize() into the original input value. Referential equality will be restored on the output object. An error will be thrown if a value was serialized with an unknown/unused serializer.


Deserializes a Request or Response object whose body was serialized with serializeBody(). Any Serializers used outside of the library defaults during serialization need to be provided here as well, or an error may be thrown.


Creates an EndpointResponse from the provided body, which is serialized using the top-level serializeBody function. If the provided body is already a Response object, it will be returned with the init headers applied (if there are any). In that case, the status and statusText init options will be ignored. Extra serializers can be used to extend the data types that can be serialized.


Utility function used in the serial functions that determines if an object is a plain object or not. Because this is such a common operation when checking and serializing unknown objects, it's being exported as part of the API.


Asset preparation procedure that does the following:


Returns a parsed body from a given request after checking size constraints. Uses deserializeBody to deserialize the request body.


Generates or returns a previously generated RequestContext for a given request. If this is the first time requestContext is being called for the given request, the RequestContext object is generated and returned. Every other time the request passes through this function, the same object generated on the first call is returned without further modification.


Creates an endpoint handler for resolving Requests into Responses.


Constructs a new RpcInit. This simply returns the first argument, it's only provided for typing purposes so that you don't need to manually specify the types when extracting out an spreadable RpcInit object. Use this to stay DRY.


Serializes a value recursively until it's JSON-compatible. Serializers can be plugged in to extend the accepted types beyond what Cav supports by default. Referential equality will be preserved whenever the same object or symbol value is encountered more than once. If a value isn't recognized by any of the provided serializers or the default serializers, an error is thrown.


Serializes a value into a type that is compatible with a Response BodyInit, making it easy to serialize values for sending to an external host/client via HTTP. If a provided value is already compatible with BodyInit, it will be returned with an appropriate mime type, skipping the serialization process. During serialization, this function extends the default supported types to include Blobs and Files. If a Blob is encountered during serialization, the resulting body will be a multipart FormData that encodes the shape of the input as well as the blobs that were encountered. Otherwise, a regular JSON string will be returned. Blobs and Files can be placed anywhere on the input value, even if they are nested.


Constructs a Serializer. This simply returns the first argument, it's only used for type annotations.


Response factory for serving static assets. Asset resolution uses the provided ServeAssetOptions, the Request is only used for caching headers like ETag etc.


Constructs a new server instance. This is a simple function wrapper around the Server constructor from https://deno.land/std/http/server.ts.


Constructs a new Stack handler using the provided routes object. Keys can be a subset of the URLPattern syntax when group capturing is desired. See the documentation for more information about how Stack routing works. TODO: the documentation about how Stack routing works


The server-side equivalent of the wrapWebSocket function in the client module. Returns the Socket instance and a Response which should be returned by the handler for the socket upgrade to complete successfully.


Wraps a regular WebSocket with serializer functionality and type support.



Cav's cookie interface. This interface provides synchronous access to cookie values. The actual signing of signed cookies needs to be asynchronous, however. Once you are done accessing and modifying the cookie, you need to call the async "flush()" to sync cookie updates to the response headers that were provided when the cookie was initialized.


Limits what paths/domains a cookie should be deleted for.


Extends the Deno default cookie set options to include the "signed" flag.


In Cav, there is no middleware. To fill the gap, Rpcs can leverage Ctx functions to create context-dependent data related to a request. These functions are where you'd set up databases, create session objects, etc. The value returned from this function is available as the ctx property for an Rpc's resolve and resolveError functions.


Arguments available to the Ctx function of an Rpc.


An endpoint handler can use this Request type to ferry type information to the client from the server about what client arguments are acceptable.


Response type used to ferry the type of the deserialized response to the client from the server. If a server handler doesn't return this type, the response type of the corresponding client call will be "unknown".


Initializer options for the endpointResponse() function.


Initializer arguments for constructing HttpErrors, which can expose arbitrary data and status codes during de/serialization.


A function that parses data. If data is not shaped as expected, an error should be thrown.


An object with a ParserFunction as its "parse" property. Zod compatible.


A metadata cache object generated once for every Request handled with a Cav handler (Stacks and Rpcs).


After an Rpc matches with an incoming request, the Resolve function is responsible for resolving the request data into a response to send back to the client. The value returned from the Resolver will be packed with the top-level response() function, i.e. it undergoes packing via packBody().


Arguments available to a Resolver function.


Handler for handling errors that occur during response resolution. Meant to turn the errors into responses to send back to the client, using the same serialization process and utilties available in the resolve function. If an error is re-thrown, that error will be serialized as the response.


Arguments available to the resolveError() function of an Rpc.


A router handler on the server can use this Request type to ferry type information about valid routes to the client. The client uses the provided RouterShape to infer which property accesses are valid.


Type constraint for the Shape parameter of a RouterRequest. The shape describes the client property accesses that would result in a valid endpoint call.


Cav's endpoint HTTP handler. Rpcs are one of two fundamental building blocks of Cav server applications, the other being Stacks. Stacks are responsible for routing a request, Rpcs are responsible for handling them.


Initializer options for constructing Rpcs.


A group of functions used to recognize (check), serialize, and deserialize objects and special values that are not strings, basic numbers, booleans, or nulls into objects that are JSON compatible.


Options controlling how assets are found and served.


Cav's WebSocket wrapper interface.


Initializer options to use when upgrading a request into a web socket using the upgradeWebSocket function.


Handler that routes requests to Rpcs (endpoints) or other Stacks (routers).

Type Aliases


Matches any valid context function. Useful for type constraints.


Matches any kind of parser. Useful for type constraints.


Alias for an Rpc with any init type. Useful for type constraints.


Matches any RpcInit. Useful for type constraints.


Type alias representing a Serializer with any input or output type. Useful for type constraints.


Type that matches any socket. Useful for type constraints.


A function that wraps fetch() with a tailored process for making requests to a Cav server. Each property access on the function itself returns a new Client that extends the URL of the original Client. The periods represent path dividers and the accessed properties are path segments, like this: client("http://localhost/base").nested["pa.th"]() will result in a request to "http://localhost/base/nested/pa.th".


Arguments for the client function when its internal path points to an endpoint.


Generic handler type for server-defined Request handlers.


An object or function responsible for parsing data or throwing errors if the data isn't shaped as expected. These can either be functions with a single data argument that return the parsed data or an object with a parse(data): unknown function property that does the same. Cav is specifically tuned to be compatible with (but not dependent on) Zod, a schema-based data parsing library. However, any parsing library can be used, as long as its parsers satisfy this Parser interface. (Let me know if more shapes should be supported in a github issue.) You can also write strongly-typed parsing functions and objects by hand if you don't want to use a third-party parsing library.


Extracts the input type of a given Parser.


Extracts the output type of a given Parser.


A group of named Serializer objects. Serializer keys are used to tag serialized values on the output JSON, which is required in order to correctly deserialize the value on the other side.


Options for serving an http handler. This is a re-export of the ServeInit type from https://deno.land/std/server.ts.


An http server. This is a re-export of the Server type from https://deno.land/std/http/server.ts.


Options for running an http server. This is a re-export of the ServerInit type from https://deno.land/std/http/server.ts.


Type for a web socket event listener. The shape of the listener depends on the event type. For the "message" event, the message type may be provided as the second type parameter.


A Serializer's deserialize() function receives the raw serialized JSON value as its first argument and this registration function as the second. Functions registered with whenDone will be run last-in-first-out (stack order) when the raw JSON has been processed into the final object instance. WhenDone functions are needed whenever the serialized data is more complex than simple JSON values, for example when referential equality needs to be maintained or when the serialize function returns anything that needs to be re-serialized by some other serializer. Referenced objects may not be fully initialized when the registered function is called, but its instance will be instantiated so that references can be fixed.


NOTE: This is new and probably broken somehow, don't use it in production. (Unless you're me lol)

Cav is an experimental full stack web framework for Deno. Here's some notable features:

  • Compatible with Zod parsers, enabling end-to-end type safety
  • Serves static assets and serializes (nearly) any JavaScript type to JSON
  • Web socket support
  • Zero config (i.e. good defaults), and zero third-party dependencies
  • Dev-time bundling for frontend TypeScript assets
  • Compatible with frontend frameworks like Preact
  • Deno Deploy without a build step





Cav requires Deno v1.21.2 or higher. If you're new to Deno, read the manual to get up to speed.

A simple "hello world" app in Cav looks like this:

TODO: Start with the smallest hello world possible, introduce other features step by step, building it out into a full blown app