• Stars
    star
    194
  • Rank 199,425 (Top 4 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 3 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Cloudflare Durable Objects + Itty Router = shorter code

itty-durable

npm package Build Status Open Issues

Simplifies usage of Cloudflare Durable Objects, allowing lightweight object definitions and direct access to object methods from within Workers (no need for request building/handling).

Features

  • Removes nearly all boilerplate from writing and using Durable Objects.
  • Optional automatic non-blocking persistance layer
  • Optionally return contents from methods without explicit return (convenience feature)
  • Control how contents of object looks to outside requests
  • Control exactly what, if anything, is persisted
  • Already being used in production on high-availability/throughput apps like the Retheme browser extension!

Installation

npm install itty-router itty-durable

Example

Counter.js (your Durable Object class)
import { createDurable } from 'itty-durable'

export class Counter extends createDurable({ autoReturn: true }) {
  constructor(state, env) {
    super(state, env)

    // anything defined here is only used for initialization (if not loaded from storage)
    this.counter = 0
  }

  // Because this function does not return anything, it will return the entire contents
  // Example: { counter: 1 }
  increment() {
    this.counter++
  }

  // Any explicit return will honored, despite the autoReturn flag.
  // Note that any serializable params can passed through from the Worker without issue.
  add(a, b) {
    return a + b
  }
}
Worker.js (your CF Worker function)
import { ThrowableRouter, missing, withParams } from 'itty-router-extras'
import { withDurables } from 'itty-durable'

// export the durable class, per spec
export { Counter } from './Counter'

const router = ThrowableRouter({ base: '/counter' })

router
  // add upstream middleware, allowing Durable access off the request
  .all('*', withDurables())

  // get the durable itself... returns json response, so no need to wrap
  .get('/', ({ Counter }) => Counter.get('test').toJSON())

  // By using { autoReturn: true } in createDurable(), this method returns the contents
  .get('/increment', ({ Counter }) => Counter.get('test').increment())

  // you can pass any serializable params to a method... (e.g. /counter/add/3/4 => 7)
  .get('/add/:a?/:b?', withParams,
    ({ Counter, a, b }) => Counter.get('test').add(Number(a), Number(b))
  )

  // reset the durable
  .get('/reset', ({ Counter }) => Counter.get('test').reset())

  // 404 for everything else
  .all('*', () => missing('Are you sure about that?'))

// with itty, and using ES6 module syntax (required for DO), this is all you need
export default {
  fetch: router.handle
}

/*
Example Interactions:

GET /counter                                => { counter: 0 }
GET /counter/increment                      => { counter: 1 }
GET /counter/increment                      => { counter: 2 }
GET /counter/increment                      => { counter: 3 }
GET /counter/reset                          => { counter: 0 }
GET /counter/add/20/3                       => 23
*/

How it Works

This library works via a two part process:

  1. First of all, we create a base class for your Durable Objects to extend (through createDurable()). This embeds the persistance layer, a few convenience functions, and most importantly, a tiny internal itty-router to handle fetch requests. Using this removes the boilerplate from your objects themselves, allowing them to be only business logic.

  2. Next, we expose the withDurables() middleware for use within your Workers (it is designed for drop-in use with itty-router, but should work with virtually any typical Worker router). This embeds proxied stubs (translation: "magic stubs") into the Request. Using these stubs, you can call methods on the Durable Object directly, rather than manually creating fetch requests to do so (that's all handled internally, communicating with the embedded router within the Durable Objects themselves).

Installation

npm install itty-durable

API

createDurable(options?: object): class

Factory function to create the IttyDurable class (with options) for your Durable Object to extend.

Option Type(s) Default Description
autoPersist boolean false By default, all contents are stored in-memory only, and are cleared when the DO evacuates from memory (unless explicitly asked to persist). By setting this to true, each request to the DO through the stub will persist the contents automatically.
autoReturn boolean false If set to true, methods without an explicit return will return the contents of the object itself (as controlled through the toJSON() method). This method is overridable for custom payload shaping.

withDurables(options?: object): function

Highly-recommended middleware to embed itty-durable stubs into the request. Using these stubs allows you to skip manually creating/sending requests or handling response parsing.

Option Type(s) Default Description
parse boolean false By default, the stub methods return a Promise to the Response from the Durable Object itself. This is great if you're just passing the response along and don't want to modify it. To take more control, setting this to true will instead return a Promise to the parsed JSON contents instead. To then respond to requests, you would have to handle building of a JSON Response yourself (e.g. json() within itty-router-extras).

Special Thanks

Big time thanks to all the fantastic developers on the Cloudflare Workers discord group, for their putting up with my constant questions, code snippets, and guiding me off the dangerous[ly flawed] path of async setters ;)

Contributors

Let's face it, in open source, these are the real heroes... improving the quality of libraries out there for everyone!

  • README tweaks, fixes, improvements: @tomByrer

More Repositories

1

itty-router

A little router.
TypeScript
1,747
star
2

apicache

Simple API-caching middleware for Express/Node.
JavaScript
1,190
star
3

treeize

Converts row data (in JSON/associative array format) to tree structure based on column naming conventions.
JavaScript
186
star
4

itty-router-extras

An assortment of delicious extras for the calorie-light itty-router.
JavaScript
79
star
5

itty-fetcher

An even simpler wrapper around native Fetch to strip boilerplate from your fetching code!
TypeScript
67
star
6

use-store

Storing cross-component UI data in React has never been easier... (uses hooks)
JavaScript
18
star
7

parcel-express-react

Barebones boilerplate for Parcel.js + ExpressJS + ReactJS
JavaScript
18
star
8

itty-time

An itty library to handle common time-related things for your API needs.
TypeScript
9
star
9

svelte-navlink-action

Minimalist Svelte action to inject .active class in route-matched links.
TypeScript
7
star
10

cloudflare-template-gpt

A dead-simple example of setting up a simple GPT bot API.
TypeScript
6
star
11

slick-array

Native Arrays, but with built-in index(es) and group support.
JavaScript
6
star
12

retheme-site

Home of Retheme.org
Svelte
5
star
13

adventofcode

Advent of Code 2021
JavaScript
4
star
14

yarn-release

For clean module/component releasing to NPM via Yarn
JavaScript
4
star
15

redux-registry

JavaScript
3
star
16

itty-durable-example

JavaScript
3
star
17

itty-router-help

Help middleware for itty-router
JavaScript
2
star
18

itty.sh

Svelte
2
star
19

sveltekit-template

Full-page responsive shell (with minimal element styles) for spawning new SK apps.
Svelte
2
star
20

cloudflare-kv-store

JavaScript
2
star
21

advent-of-code-2020

JavaScript
2
star
22

bundler-tests

TypeScript
1
star
23

itty-cors

CORS example using itty-router with Cloudflare Workers
JavaScript
1
star
24

pandemic-sandbox

JavaScript
1
star
25

supergeneric

Super-generic JS helper functions
HTML
1
star
26

fusebox-demo-app

JavaScript
1
star
27

portfolio

Kevin's totally awesome portfolio site.
Svelte
1
star
28

chrome-extension

JavaScript
1
star
29

aimees-model-y

Model Y Repo
1
star