kwhitley / itty-durable

Cloudflare Durable Objects + Itty Router = shorter code
MIT License
236 stars 18 forks source link

Support `newUniqueId` and `idFromString` #36

Closed nathanclevenger closed 1 year ago

nathanclevenger commented 1 year ago

This solves #21 and #29. If get() is called with an undefined id then it is generated with newUniqueId, and if an existing Cloudflare-generated 64-digit is passed in then idFromString is called instead of durable.idFromName(id)

nathanclevenger commented 1 year ago

@kwhitley Here is an example I created that uses both of these new methods. The key advantage of this approach is that it's significantly faster for new IDs as there is no round-the-world check for existing DOs by a given name:

import { error, json, Router, withParams } from 'itty-router'
import { createDurable, withDurables } from '../../src' // from 'itty-durable'

const router = Router()

router
  .get('*', withDurables(), withParams)
  .get('/', ({ Fetcher }) => Fetcher.get().location())
  .get('/:id', ({ Fetcher, id }) => Fetcher.get(id).location())
  .get('/:id/:target+', ({ Fetcher, id, target }) => Fetcher.get(id).fetcher('https://' + target))

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

  async location() {
    const id = this.state.id.toString()
    const { colo } = await fetch('https://workers.cloudflare.com/cf.json').then(res => res.json())
    return { id, colo }
  }

  fetcher(url, options = {}) {
    return fetch(url, options)
  }
}

export default {
  fetch: (req, env, ctx) => router.handle(req, env, ctx).then(json).catch(error)
}