Skip to content

janwilmake/queryable-object

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Queryable Object

Improved version of browsable object that uses RPC instaed of needing fetch. This has the benefit of not exposing any endpoints when you expose your durable object to the public web. Besides, since the studio is not tied to a single DO, we can use things like multistub to connect the studio with more than one DO! This is an alternative to remote-sql-cursor - it has a slightly different API, but is a lot simpler, and more secure by default!

usage

import { DurableObject } from "cloudflare:workers";
import {
  studioMiddleware,
  Queryable,
  QueryableHandler,
  // Extend this instead of @Queryable
  QueryableObject
} from "queryable-object";



export type ExecFn =
/** this adds these functions to your DO Stub:
{
  exec: (query: string, ...bindings: any[]) => Promise<{columnNames: string[]; rowsRead: number; rowsWritten: number; array: any[]; one: any; }>;
  raw: (query: string, ...bindings: any[]) => Promise<{ columnNames: string[]; rowsRead: number; rowsWritten: number; raw: SqlStorageValue[][]; }>;
  // gets the full schema
  getSchema: () => Promise<string>;
};
*/
type Env = { MyDO: DurableObjectNamespace<MyDO & QueryableHandler> };

@Queryable()
export class MyDO extends DurableObject {
  sql: SqlStorage;
  env: any;

  constructor(state: DurableObjectState, env: Env) {
    super(state, env);
    this.env = env;
    this.sql = state.storage.sql;
    // Do stuff with your DO
  }

  //....
}

export default {
  fetch: async (request: Request, env: Env) => {
    const url = new URL(request.url);
    const firstSegment = url.pathname.split("/")[1];
    const stub = env.MyDO.get(env.MyDO.idFromName(firstSegment));

    if (url.pathname === "/") {
      return new Response(`usage:

- Items for any ID: GET /{id}
- Any studio: GET /{id}/studio
`);
    }

    if (url.pathname.endsWith("/studio")) {
      // Add studio that can access any raw function
      // NB: this also adds a small import functionality to import .sql files and execute its statements. use '?page=import' to access it.
      return studioMiddleware(request, stub.raw, {
        basicAuth: { username: "admin", password: "test" },
      });
    }

    // You can query your DO from the outside, with a very well-known interface!
    const { array } = await stub.exec("SELECT * FROM items");
    return new Response(JSON.stringify(array, undefined, 2), {
      headers: { "content-type": "application/json" },
    });
  },
};

About

Query Your DOs from the Outside

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published