Giter Club home page Giter Club logo

chiselstrike's Introduction

banner


Build Status License Discord Twitter

What is ChiselStrike?

ChiselStrike is a complete backend bundled in one piece. Your one stop-shop for all your backend needs, powered by TypeScript.

Why ChiselStrike?

Putting together a backend is hard work. Databases? ORM? Business logic? Data access policies? And how to offer all of that through an API?

Learning all that, plus figuring out the interactions between all the components can be a drain on an application developer's time. Low-code based approaches allow for super fast prototypes, but as you need to scale and evolve, the time you saved on the prototype is now owed with interest in refactorings, migrations, etc.

ChiselStrike provides everything you need to handle and evolve your backend, from the data layer to the business logic, allowing you to focus on what you care about โ€“ย your code, rather than worrying about databases schemas, migrations, or even database operations.

All driven by TypeScript, so your backend can evolve as your code evolves.

How does that work?

ChiselStrike keeps things as close as possible to pure TypeScript, and a translation layer takes care of index creation, database query generation, and even communicating with external systems like Kafka.

Internally, ChiselStrike uses a SQLite database so there's no need to set up any external data layer (although it is possible to hook up an external Postgres-compatible database). ChiselStrike also abstract other concepts common to complex backends, like Kafka-compatible streaming platforms.

Quick start

To get a CRUD API working in 30 seconds or less, first create a new project:

npx -y create-chiselstrike-app@latest my-app
cd my-app

Add a model by writing the following TypeScript code to models/BlogComment.ts:

import { ChiselEntity } from "@chiselstrike/api"

export class BlogComment extends ChiselEntity {
    content: string = "";
    by: string = "";
}

Add a route by writing the following TypeScript code to routes/comments.ts:

import { BlogComment } from "../models/BlogComment";
export default BlogComment.crud();

Start the development server with:

npm run dev

This server will provide a CRUD API that you can use to add and query instances of the BlogComment entity.

curl -X POST -d '{"content": "First comment", "by": "Jill"}' localhost:8080/dev/comments

curl localhost:8080/dev/comments

For a more detailed tutorial about how to get started with ChiselStrike, follow our Getting started tutorial.

Is ChiselStrike a database?

No. The founding team at ChiselStrike have written databases from scratch before and we believe there are better things to do in life, like pretty much anything else. ChiselStrike comes bundled with SQLite, providing developers with a zero-conf relational-like abstraction that allows one to think of backends from the business needs down, instead of from the database up.

Instead, you can think of ChiselStrike as a big pool of global shared memory. The data access API is an integral part of ChiselStrike and offers developers a way to just code, without worrying about the underlying database (anymore than you worry about what happens in each level of the memory hierarchy, meaning some people do, but most people don't have to!).

In production, ChiselStrike can also hook up into a Kafka-compatible streaming platform when available, and transparently drive both that and the database from a unified TypeScript/JavaScript abstraction.

Is ChiselStrike an ORM?

Kind of. ChiselStrike has some aspects that overlap with traditional ORMs, in that it allows you to access database abstractions in your programming language. However, in traditional ORMs you start from the database, and export it up. Changes are done to the database schema, which is then bubbled up through migrations, and elements of the database invariably leak to the API.

ChiselStrike, on the other hand, starts from your code and automates the decisions needed to implement that into the database, much like what a compiler would do.

Let's look at ChiselStrike's documentation for an example of what's needed to create a comment on a blog post:

import { ChiselEntity } from "@chiselstrike/api"

export class BlogComment extends ChiselEntity {
    content: string = "";
    by: string = "";
}

The first thing you will notice is that there is no need to specify how those things map to the underlying database. No tracking of primary keys, column types, etc.

Now imagine you need to start tracking whether this was created by a human or a bot. You can change your model to say:

import { ChiselEntity } from "@chiselstrike/api"

export class BlogComment extends ChiselEntity {
    content: string = "";
    by: string = "";
    isHuman: boolean = false;
}

and that's it! There are no migrations and no need to alter a table.

Furthermore, if you need to find all blog posts written by humans, you can just write a lambda instead of trying to craft a database query in TypeScript:

const all = await BlogComment.findMany(p => p.isHuman);

Is ChiselStrike a TypeScript runtime?

ChiselStrike includes a TypeScript runtime - the fantastic and beloved Deno. That's the last piece of the puzzle with the data API and the database bundles. That allows you to develop everything locally from your laptop and integrate with your favorite frontend framework. Be it Next.js, Gatsby, Remix, or any others - we're cool with all of them!

That's all fine and all, but I need more than that!

We hear you. No modern application is complete without authentication and security. ChiselStrike integrates with next-auth and allows you to specify authentication entities directly from your TypeScript models.

You can then add a policy file that details which fields can be accessed, and which endpoints are available.

For example, you can store the blog authors as part of the models,

import { ChiselEntity, AuthUser } from "@chiselstrike/api"

export class BlogComment extends ChiselEntity {
    content: string = "";
    @labels("protect") author: AuthUser;
}

and then write a policy saying that the users should only be able to see the posts that they themselves originated:

labels:
  - name: protect
    transform: match_login

Now your security policies are declaratively applied separately from the code, and you can easily grasp what's going on.

In Summary

ChiselStrike provides everything you need to handle your backend, from the data layer to the business logic, wrapped in powerful abstractions that let you just code and not worry about handling databases schemas, migrations, and operations again.

It allows you to declaratively specify compliance policies around who can access the data and under which circumstances.

Your ChiselStrike files can go into their own repo, or even better, into a subdirectory of your existing frontend repo. You can code your presentation and data layer together, and turn any frontend framework into a full-stack (including the database layer!) framework in minutes.

Contributing

To build and develop from source:

git submodule update --init --recursive
cargo build

That will build the chiseld server and chisel utility.

You can now use create-chiselstrike-app to install a local version of the API:

node ./packages/create-chiselstrike-app --chisel-version="file:../packages/chiselstrike-api" my-backend

And then replace instances of npm run with direct calls to the new binaries. For example, instead of npm run dev, run

cd my-backend
npm i esbuild
../target/debug/chisel dev

Also, consider:

Open (or fix!) an issue ๐Ÿ™‡โ€โ™‚๏ธ

Join our discord community ๐Ÿคฉ

Start a discussion ๐Ÿ™‹โ€โ™€๏ธ

Next steps?

Our documentation (including a quick tutorial) is available at here

chiselstrike's People

Contributors

7flash avatar bearlemma avatar danielferragut avatar dekimir avatar dyasny avatar espindola avatar haaawk avatar honzasp avatar marinpostma avatar mergify[bot] avatar mpdehaan avatar nickhodges avatar nottj avatar penberg avatar psarna avatar psqli avatar ricardodalarme avatar tylermcginnis avatar wilsonnet avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

chiselstrike's Issues

panic with policies

endpoint:

export default async function chisel(req: Request) {
    const url = new URL(req.url);
    const arg = url.searchParams.get("country")

    let count = 0;

    let people = Person.select("country").findMany({ "country": arg });
    for await (let person of people) {
        count += 1
    }
    return new Response(count + "\n");
}

policies:

labels:
  - name: pii
    transform: anonymize

types:

class Person {
        @pii name: string;
        country: string;
}

panic:

thread '<unnamed>' panicked at 'no entry found for key', server/src/db.rs:184:38
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread '<unnamed>' panicked at 'The Tokio context thread-local variable has been destroyed.', /Users/glauber/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.14.0/src/runtime/context.rs:75:23
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: ESRCH', /Users/glauber/IdeaProjects/chiselstrike/server/src/server.rs:202:67
stack backtrace:
   0:        0x103bc4864 - std::backtrace_rs::backtrace::libunwind::trace::hd7ea89f96dbcea2f
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/../../backtrace/src/backtrace/libunwind.rs:90:5
   1:        0x103bc4864 - std::backtrace_rs::backtrace::trace_unsynchronized::h9b871e5dd80d4afa
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:        0x103bc4864 - std::sys_common::backtrace::_print_fmt::hed76ee81d5e4a477
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/sys_common/backtrace.rs:67:5
   3:        0x103bc4864 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h8483effd3e9ec544
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/sys_common/backtrace.rs:46:22
   4:        0x103be4cac - core::fmt::write::ha34752bcd39bca36
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/fmt/mod.rs:1163:17
   5:        0x103bbc9cc - std::io::Write::write_fmt::hfc57a6e48a9ddae2
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/io/mod.rs:1696:15
   6:        0x103bc6664 - std::sys_common::backtrace::_print::h9e9cb382fe2b19e4
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/sys_common/backtrace.rs:49:5
   7:        0x103bc6664 - std::sys_common::backtrace::print::hc8209d6be1d0b41b
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/sys_common/backtrace.rs:36:9
   8:        0x103bc6664 - std::panicking::default_hook::{{closure}}::he9aaba83dd453f35
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/panicking.rs:210:50
   9:        0x103bc6244 - std::panicking::default_hook::hc87ff103cfd8260f
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/panicking.rs:227:9
  10:        0x100bbb26c - <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call::h51d5c476aac70ece
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/alloc/src/boxed.rs:1705:9
  11:        0x100d5efec - chisel_server::server::run_shared_state::{{closure}}::{{closure}}::h2047dd16b2ca7e51
                               at /Users/glauber/IdeaProjects/chiselstrike/server/src/server.rs:201:9
  12:        0x103bc6cd0 - std::panicking::rust_panic_with_hook::hf890018b6cf19ef5
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/panicking.rs:628:17
  13:        0x103bc67f0 - std::panicking::begin_panic_handler::{{closure}}::hc0918e64b5d68f06
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/panicking.rs:521:13
  14:        0x103bc4d24 - std::sys_common::backtrace::__rust_end_short_backtrace::hb99d925d54d4af60
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/sys_common/backtrace.rs:139:18
  15:        0x103bc6758 - rust_begin_unwind
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/panicking.rs:517:5
  16:        0x103c1a49c - core::panicking::panic_fmt::hf9e85df46ac02a7d
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/panicking.rs:100:14
  17:        0x103c1a540 - core::result::unwrap_failed::h3b4d980f8618ad59
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/result.rs:1616:5
  18:        0x100cf6270 - core::result::Result<T,E>::unwrap::h36cf30300a69a8d2
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/result.rs:1298:23
  19:        0x100d5f010 - chisel_server::server::run_shared_state::{{closure}}::{{closure}}::h2047dd16b2ca7e51
                               at /Users/glauber/IdeaProjects/chiselstrike/server/src/server.rs:202:9
  20:        0x103bc6cd0 - std::panicking::rust_panic_with_hook::hf890018b6cf19ef5
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/panicking.rs:628:17
  21:        0x103bc67f0 - std::panicking::begin_panic_handler::{{closure}}::hc0918e64b5d68f06
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/panicking.rs:521:13
  22:        0x103bc4d24 - std::sys_common::backtrace::__rust_end_short_backtrace::hb99d925d54d4af60
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/sys_common/backtrace.rs:139:18
  23:        0x103bc6758 - rust_begin_unwind
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/panicking.rs:517:5
  24:        0x103c1a49c - core::panicking::panic_fmt::hf9e85df46ac02a7d
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/panicking.rs:100:14
  25:        0x1039a5a7c - core::panicking::panic_display::h4bfb5287ccdf7675
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/panicking.rs:64:5
  26:        0x1039a1500 - tokio::runtime::context::spawn_handle::h8c823bdfac24789b
                               at /Users/glauber/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.14.0/src/runtime/context.rs:75:23
  27:        0x1033bd70c - tokio::task::spawn::spawn_inner::hd581cb866d51dd16
                               at /Users/glauber/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.14.0/src/task/spawn.rs:145:28
  28:        0x1033bd8cc - tokio::task::spawn::spawn::hf83e4738e36a904a
                               at /Users/glauber/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.14.0/src/task/spawn.rs:135:13
  29:        0x1033dd768 - <sqlx_core::pool::connection::PoolConnection<DB> as core::ops::drop::Drop>::drop::h2e53bc6903af5206
                               at /Users/glauber/.cargo/registry/src/github.com-1ecc6299db9ec823/sqlx-core-0.5.7/src/pool/connection.rs:136:13
  30:        0x10338c15c - core::ptr::drop_in_place<sqlx_core::pool::connection::PoolConnection<sqlx_core::any::database::Any>>::h32ac756222df0b24
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  31:        0x100e640cc - core::ptr::drop_in_place<sqlx_core::pool::executor::<impl sqlx_core::executor::Executor for &sqlx_core::pool::Pool<sqlx_core::any::database::Any>>::fetch_many<sqlx_core::query::Query<sqlx_core::any::database::Any,sqlx_core::any::arguments::AnyArguments>>::{{closure}}::{{closure}}>::h4edb9af9696ad062
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:71:9
  32:        0x100e64a9c - core::ptr::drop_in_place<core::future::from_generator::GenFuture<sqlx_core::pool::executor::<impl sqlx_core::executor::Executor for &sqlx_core::pool::Pool<sqlx_core::any::database::Any>>::fetch_many<sqlx_core::query::Query<sqlx_core::any::database::Any,sqlx_core::any::arguments::AnyArguments>>::{{closure}}::{{closure}}>>::he2bf152b8bbb504f
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  33:        0x100e6b200 - core::ptr::drop_in_place<sqlx_core::ext::async_stream::TryAsyncStream<either::Either<sqlx_core::any::query_result::AnyQueryResult,sqlx_core::any::row::AnyRow>>::new<sqlx_core::pool::executor::<impl sqlx_core::executor::Executor for &sqlx_core::pool::Pool<sqlx_core::any::database::Any>>::fetch_many<sqlx_core::query::Query<sqlx_core::any::database::Any,sqlx_core::any::arguments::AnyArguments>>::{{closure}},core::future::from_generator::GenFuture<sqlx_core::pool::executor::<impl sqlx_core::executor::Executor for &sqlx_core::pool::Pool<sqlx_core::any::database::Any>>::fetch_many<sqlx_core::query::Query<sqlx_core::any::database::Any,sqlx_core::any::arguments::AnyArguments>>::{{closure}}::{{closure}}>>::{{closure}}>::hf57542b9e55fdd17
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:28:33
  34:        0x100e6ca08 - core::ptr::drop_in_place<core::future::from_generator::GenFuture<sqlx_core::ext::async_stream::TryAsyncStream<either::Either<sqlx_core::any::query_result::AnyQueryResult,sqlx_core::any::row::AnyRow>>::new<sqlx_core::pool::executor::<impl sqlx_core::executor::Executor for &sqlx_core::pool::Pool<sqlx_core::any::database::Any>>::fetch_many<sqlx_core::query::Query<sqlx_core::any::database::Any,sqlx_core::any::arguments::AnyArguments>>::{{closure}},core::future::from_generator::GenFuture<sqlx_core::pool::executor::<impl sqlx_core::executor::Executor for &sqlx_core::pool::Pool<sqlx_core::any::database::Any>>::fetch_many<sqlx_core::query::Query<sqlx_core::any::database::Any,sqlx_core::any::arguments::AnyArguments>>::{{closure}}::{{closure}}>>::{{closure}}>>::h4c8405d3c28f5ae6
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  35:        0x100e6d05c - core::ptr::drop_in_place<core::option::Option<core::future::from_generator::GenFuture<sqlx_core::ext::async_stream::TryAsyncStream<either::Either<sqlx_core::any::query_result::AnyQueryResult,sqlx_core::any::row::AnyRow>>::new<sqlx_core::pool::executor::<impl sqlx_core::executor::Executor for &sqlx_core::pool::Pool<sqlx_core::any::database::Any>>::fetch_many<sqlx_core::query::Query<sqlx_core::any::database::Any,sqlx_core::any::arguments::AnyArguments>>::{{closure}},core::future::from_generator::GenFuture<sqlx_core::pool::executor::<impl sqlx_core::executor::Executor for &sqlx_core::pool::Pool<sqlx_core::any::database::Any>>::fetch_many<sqlx_core::query::Query<sqlx_core::any::database::Any,sqlx_core::any::arguments::AnyArguments>>::{{closure}}::{{closure}}>>::{{closure}}>>>::h2a6da05a12187f21
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  36:        0x100e6d890 - core::ptr::drop_in_place<futures_util::future::future::fuse::Fuse<core::future::from_generator::GenFuture<sqlx_core::ext::async_stream::TryAsyncStream<either::Either<sqlx_core::any::query_result::AnyQueryResult,sqlx_core::any::row::AnyRow>>::new<sqlx_core::pool::executor::<impl sqlx_core::executor::Executor for &sqlx_core::pool::Pool<sqlx_core::any::database::Any>>::fetch_many<sqlx_core::query::Query<sqlx_core::any::database::Any,sqlx_core::any::arguments::AnyArguments>>::{{closure}},core::future::from_generator::GenFuture<sqlx_core::pool::executor::<impl sqlx_core::executor::Executor for &sqlx_core::pool::Pool<sqlx_core::any::database::Any>>::fetch_many<sqlx_core::query::Query<sqlx_core::any::database::Any,sqlx_core::any::arguments::AnyArguments>>::{{closure}}::{{closure}}>>::{{closure}}>>>::hc857f7e1f1c45803
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  37:        0x103392dd8 - core::ptr::drop_in_place<alloc::boxed::Box<dyn core::future::future::Future+Output = core::result::Result<(),sqlx_core::error::Error>+core::marker::Send>>::h069d2459fbf003a0
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  38:        0x1033938e4 - core::ptr::drop_in_place<core::pin::Pin<alloc::boxed::Box<dyn core::future::future::Future+Output = core::result::Result<(),sqlx_core::error::Error>+core::marker::Send>>>::hc5b5012ce2c5dd09
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  39:        0x100e5fc58 - core::ptr::drop_in_place<sqlx_core::ext::async_stream::TryAsyncStream<either::Either<sqlx_core::any::query_result::AnyQueryResult,sqlx_core::any::row::AnyRow>>>::h54b1ef2a1097e77c
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  40:        0x100e62ae4 - core::ptr::drop_in_place<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<either::Either<sqlx_core::any::query_result::AnyQueryResult,sqlx_core::any::row::AnyRow>,sqlx_core::error::Error>+core::marker::Send>>::hf9231603d40bbfa1
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  41:        0x100e62f8c - core::ptr::drop_in_place<core::pin::Pin<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<either::Either<sqlx_core::any::query_result::AnyQueryResult,sqlx_core::any::row::AnyRow>,sqlx_core::error::Error>+core::marker::Send>>>::h949387291306bf4b
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  42:        0x100e6d0bc - core::ptr::drop_in_place<futures_util::stream::try_stream::try_filter_map::TryFilterMap<core::pin::Pin<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<either::Either<sqlx_core::any::query_result::AnyQueryResult,sqlx_core::any::row::AnyRow>,sqlx_core::error::Error>+core::marker::Send>>,core::future::from_generator::GenFuture<<&sqlx_core::pool::Pool<sqlx_core::any::database::Any> as sqlx_core::executor::Executor>::fetch<sqlx_core::query::Query<sqlx_core::any::database::Any,sqlx_core::any::arguments::AnyArguments>>::{{closure}}::{{closure}}>,<&sqlx_core::pool::Pool<sqlx_core::any::database::Any> as sqlx_core::executor::Executor>::fetch<sqlx_core::query::Query<sqlx_core::any::database::Any,sqlx_core::any::arguments::AnyArguments>>::{{closure}}>>::hf7d19e86eddd6637
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  43:        0x100e6126c - core::ptr::drop_in_place<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<sqlx_core::any::row::AnyRow,sqlx_core::error::Error>+core::marker::Send>>::h4879f0ead6b6296f
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  44:        0x100e61d44 - core::ptr::drop_in_place<core::pin::Pin<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<sqlx_core::any::row::AnyRow,sqlx_core::error::Error>+core::marker::Send>>>::h1613108ea34d1437
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  45:        0x100e646d8 - core::ptr::drop_in_place<futures_util::stream::stream::map::Map<core::pin::Pin<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<sqlx_core::any::row::AnyRow,sqlx_core::error::Error>+core::marker::Send>>,chisel_server::query::engine::new_query_results::{{closure}}>>::h1e20ee2a9dfc9dcd
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  46:        0x100e60d44 - core::ptr::drop_in_place<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<sqlx_core::any::row::AnyRow,anyhow::Error>+core::marker::Send>>::hbe2af780438b51e7
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  47:        0x100e61a00 - core::ptr::drop_in_place<core::pin::Pin<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<sqlx_core::any::row::AnyRow,anyhow::Error>+core::marker::Send>>>::hd11a5d8d265e1204
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  48:        0x100e624e8 - core::ptr::drop_in_place<core::option::Option<core::pin::Pin<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<sqlx_core::any::row::AnyRow,anyhow::Error>+core::marker::Send>>>>::ha4ec51244a9f7981
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  49:        0x100e62c28 - core::ptr::drop_in_place<core::cell::UnsafeCell<core::option::Option<core::pin::Pin<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<sqlx_core::any::row::AnyRow,anyhow::Error>+core::marker::Send>>>>>::h207d9ffe42facc30
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  50:        0x100e62a88 - core::ptr::drop_in_place<core::cell::RefCell<core::option::Option<core::pin::Pin<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<sqlx_core::any::row::AnyRow,anyhow::Error>+core::marker::Send>>>>>::hcf434d00e0e0eec0
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  51:        0x100e67570 - core::ptr::drop_in_place<chisel_server::query::engine::QueryResults>::he147b28e51c1fee7
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  52:        0x100e60d44 - core::ptr::drop_in_place<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<sqlx_core::any::row::AnyRow,anyhow::Error>+core::marker::Send>>::hbe2af780438b51e7
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  53:        0x100e61a00 - core::ptr::drop_in_place<core::pin::Pin<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<sqlx_core::any::row::AnyRow,anyhow::Error>+core::marker::Send>>>::hd11a5d8d265e1204
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  54:        0x100e67078 - core::ptr::drop_in_place<chisel_server::db::PolicyApplyingStream>::h1d246fb124dc1cc6
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  55:        0x100e62408 - core::ptr::drop_in_place<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<serde_json::map::Map<alloc::string::String,serde_json::value::Value>,anyhow::Error>+core::marker::Send>>::hc222932147d9adbc
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  56:        0x100e62948 - core::ptr::drop_in_place<core::pin::Pin<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<serde_json::map::Map<alloc::string::String,serde_json::value::Value>,anyhow::Error>+core::marker::Send>>>::ha8f85d4208746287
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  57:        0x100e64d38 - core::ptr::drop_in_place<futures_util::stream::stream::filter::Filter<core::pin::Pin<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<serde_json::map::Map<alloc::string::String,serde_json::value::Value>,anyhow::Error>+core::marker::Send>>,futures_util::future::ready::Ready<bool>,chisel_server::db::filter_stream::{{closure}}>>::hba5d5d72b361acbd
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  58:        0x100e62408 - core::ptr::drop_in_place<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<serde_json::map::Map<alloc::string::String,serde_json::value::Value>,anyhow::Error>+core::marker::Send>>::hc222932147d9adbc
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  59:        0x100e62948 - core::ptr::drop_in_place<core::pin::Pin<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<serde_json::map::Map<alloc::string::String,serde_json::value::Value>,anyhow::Error>+core::marker::Send>>>::ha8f85d4208746287
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  60:        0x100e62408 - core::ptr::drop_in_place<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<serde_json::map::Map<alloc::string::String,serde_json::value::Value>,anyhow::Error>+core::marker::Send>>::hc222932147d9adbc
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  61:        0x100e62948 - core::ptr::drop_in_place<core::pin::Pin<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<serde_json::map::Map<alloc::string::String,serde_json::value::Value>,anyhow::Error>+core::marker::Send>>>::ha8f85d4208746287
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  62:        0x100e62f44 - core::ptr::drop_in_place<core::cell::UnsafeCell<core::pin::Pin<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<serde_json::map::Map<alloc::string::String,serde_json::value::Value>,anyhow::Error>+core::marker::Send>>>>::h3463e515c92062bb
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  63:        0x100e62edc - core::ptr::drop_in_place<core::cell::RefCell<core::pin::Pin<alloc::boxed::Box<dyn futures_core::stream::Stream+Item = core::result::Result<serde_json::map::Map<alloc::string::String,serde_json::value::Value>,anyhow::Error>+core::marker::Send>>>>::h862e9c62bff5e3fe
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  64:        0x100e67300 - core::ptr::drop_in_place<chisel_server::deno::QueryStreamResource>::h2cab8682008f5ba5
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  65:        0x10262b870 - core::ptr::drop_in_place<dyn deno_core::resources::Resource>::h55c1a9e737aede5b
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  66:        0x1025cd248 - <alloc::rc::Rc<T> as core::ops::drop::Drop>::drop::h3a10414cc998de46
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/alloc/src/rc.rs:1450:17
  67:        0x10262e2ec - core::ptr::drop_in_place<alloc::rc::Rc<dyn deno_core::resources::Resource>>::hcd4d66beac011e68
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  68:        0x10265fa24 - core::mem::maybe_uninit::MaybeUninit<T>::assume_init_drop::h4765a7af9ff2cce5
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/mem/maybe_uninit.rs:735:18
  69:        0x102652b2c - alloc::collections::btree::node::Handle<alloc::collections::btree::node::NodeRef<alloc::collections::btree::node::marker::Dying,K,V,NodeType>,alloc::collections::btree::node::marker::KV>::drop_key_val::h5b9e9f7e33675dc9
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/alloc/src/collections/btree/node.rs:1082:13
  70:        0x1026319ac - <alloc::collections::btree::map::IntoIter<K,V> as core::ops::drop::Drop>::drop::h02db4c42c84a52c4
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/alloc/src/collections/btree/map.rs:1485:22
  71:        0x1026216ec - core::ptr::drop_in_place<alloc::collections::btree::map::IntoIter<u32,alloc::rc::Rc<dyn deno_core::resources::Resource>>>::h3395e18f6397269f
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  72:        0x1026723ac - core::mem::drop::hc8d3f0f1a50a0039
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/mem/mod.rs:898:24
  73:        0x102631930 - <alloc::collections::btree::map::BTreeMap<K,V> as core::ops::drop::Drop>::drop::hf7240fccefe8601f
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/alloc/src/collections/btree/map.rs:167:9
  74:        0x1026216c8 - core::ptr::drop_in_place<alloc::collections::btree::map::BTreeMap<u32,alloc::rc::Rc<dyn deno_core::resources::Resource>>>::h58464b0feebf32ed
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  75:        0x10262b514 - core::ptr::drop_in_place<deno_core::resources::ResourceTable>::h214bb1265b0ce475
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  76:        0x102626e20 - core::ptr::drop_in_place<deno_core::ops::OpState>::hb909eaefa8aaf9da
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  77:        0x10262dc88 - core::ptr::drop_in_place<core::cell::UnsafeCell<deno_core::ops::OpState>>::h65744c5aaa266499
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  78:        0x10262d888 - core::ptr::drop_in_place<core::cell::RefCell<deno_core::ops::OpState>>::h8fd3216a55528269
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  79:        0x1025cd374 - <alloc::rc::Rc<T> as core::ops::drop::Drop>::drop::h80baacea1c8c302c
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/alloc/src/rc.rs:1450:17
  80:        0x10262f18c - core::ptr::drop_in_place<alloc::rc::Rc<core::cell::RefCell<deno_core::ops::OpState>>>::h1d1c8005096be691
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  81:        0x10262b2e0 - core::ptr::drop_in_place<deno_core::runtime::JsRuntimeState>::h8dc6df138ae717a6
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  82:        0x10262ea5c - core::ptr::drop_in_place<core::cell::UnsafeCell<deno_core::runtime::JsRuntimeState>>::ha297d2f108656eeb
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  83:        0x10262e684 - core::ptr::drop_in_place<core::cell::RefCell<deno_core::runtime::JsRuntimeState>>::ha923b189a857f75d
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  84:        0x1025cd010 - <alloc::rc::Rc<T> as core::ops::drop::Drop>::drop::h15e32e5e881ce5dc
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/alloc/src/rc.rs:1450:17
  85:        0x1026201dc - core::ptr::drop_in_place<alloc::rc::Rc<core::cell::RefCell<deno_core::runtime::JsRuntimeState>>>::h37ad4be74dcfa114
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  86:        0x1026a74ac - core::ptr::drop_in_place<alloc::boxed::Box<dyn core::any::Any>>::hef858a3e455b03fd
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  87:        0x1026a7da8 - core::ptr::drop_in_place<(core::any::TypeId,alloc::boxed::Box<dyn core::any::Any>)>::hc32010171ac64990
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  88:        0x1026bc9c4 - core::ptr::mut_ptr::<impl *mut T>::drop_in_place::h473daff6375fd4a2
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mut_ptr.rs:996:18
  89:        0x1026bc9c4 - hashbrown::raw::Bucket<T>::drop::h46f937cd4bbb8203
                               at /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.11.0/src/raw/mod.rs:344:9
  90:        0x1026bccf0 - hashbrown::raw::RawTable<T,A>::drop_elements::hd6ab7df2758c8898
                               at /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.11.0/src/raw/mod.rs:598:17
  91:        0x1026bcdd4 - hashbrown::raw::RawTable<T,A>::clear::h9fbbe9b189c2fc71
                               at /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.11.0/src/raw/mod.rs:591:13
  92:        0x1026af398 - hashbrown::map::HashMap<K,V,S,A>::clear::he09bc7673ad1f180
                               at /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.11.0/src/map.rs:774:9
  93:        0x1026a617c - std::collections::hash::map::HashMap<K,V,S>::clear::h0e61d04b9193c6f9
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/collections/hash/map.rs:570:9
  94:        0x1026c7df8 - v8::isolate::Isolate::dispose::hfa3644ceda59f07a
                               at /Users/glauber/.cargo/registry/src/github.com-1ecc6299db9ec823/v8-0.36.0/src/isolate.rs:691:5
  95:        0x1026c83d4 - <v8::isolate::OwnedIsolate as core::ops::drop::Drop>::drop::h69ab48cdb0823238
                               at /Users/glauber/.cargo/registry/src/github.com-1ecc6299db9ec823/v8-0.36.0/src/isolate.rs:893:7
  96:        0x1026a6a28 - core::ptr::drop_in_place<v8::isolate::OwnedIsolate>::h749cd49d319c96d6
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  97:        0x10262dcf4 - core::ptr::drop_in_place<core::option::Option<v8::isolate::OwnedIsolate>>::h5a897b811dd57c68
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  98:        0x10262a87c - core::ptr::drop_in_place<deno_core::runtime::JsRuntime>::ha22ad158fd6ee1d4
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
  99:        0x1017ce320 - core::ptr::drop_in_place<deno_runtime::worker::MainWorker>::h8180198ab145ef4e
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
 100:        0x100e65ee0 - core::ptr::drop_in_place<chisel_server::deno::DenoService>::h0ef1c91bf49cef38
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
 101:        0x100e6a274 - core::ptr::drop_in_place<core::cell::UnsafeCell<chisel_server::deno::DenoService>>::hbaf4a3a551ae432f
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
 102:        0x100e69c28 - core::ptr::drop_in_place<core::cell::RefCell<chisel_server::deno::DenoService>>::hf0791412e6293150
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
 103:        0x100e6e1d0 - <alloc::rc::Rc<T> as core::ops::drop::Drop>::drop::h11254252898f61f5
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/alloc/src/rc.rs:1450:17
 104:        0x100e59588 - core::ptr::drop_in_place<alloc::rc::Rc<core::cell::RefCell<chisel_server::deno::DenoService>>>::haa9b6a3eb74be6c5
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
 105:        0x100e5cdb4 - core::ptr::drop_in_place<core::option::Option<alloc::rc::Rc<core::cell::RefCell<chisel_server::deno::DenoService>>>>::h7438296249ab589c
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
 106:        0x100e5f2d0 - core::ptr::drop_in_place<core::cell::UnsafeCell<core::option::Option<alloc::rc::Rc<core::cell::RefCell<chisel_server::deno::DenoService>>>>>::h2e46c54424edf8e3
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
 107:        0x100e5d73c - core::ptr::drop_in_place<once_cell::unsync::OnceCell<alloc::rc::Rc<core::cell::RefCell<chisel_server::deno::DenoService>>>>::h4947fe5cebedfec7
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
 108:        0x100e5f8ec - core::ptr::drop_in_place<core::option::Option<once_cell::unsync::OnceCell<alloc::rc::Rc<core::cell::RefCell<chisel_server::deno::DenoService>>>>>::h0c5cb49e892336fa
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ptr/mod.rs:188:1
 109:        0x100f33b14 - core::mem::drop::hed57b810782afa3d
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/mem/mod.rs:898:24
 110:        0x100fe44ac - std::thread::local::fast::destroy_value::hb5343e90f68b5aa7
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/thread/local.rs:655:13
 111:        0x103bcd3e4 - std::sys::unix::thread_local_dtor::register_dtor::run_dtors::h757046b4b0ea0f4c
                               at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/sys/unix/thread_local_dtor.rs:89:17
thread panicked while processing panic. aborting.

`chisel dev` stops listening when there is an `apply` error

Whenever a file watched by chisel dev has an error, the chisel dev process exits and stops watching the directories. But the chiseld process stays up.

Easy reproduction:

$ mkdir -p bbb && cd bbb
$ chisel init
Initialized ChiselStrike project in /tmp/bbb
$ echo '}' > endpoints/zzz.js
$ chisel dev
INFO - ChiselStrike is ready ๐Ÿš€ - URL: http://127.0.0.1:8080 
error: Unexpected token `}`. Expected this, import, async, function, [ for array literal, { for object literal, @ for decorator, function, class, null, true, false, number, bigint, string, regexp, ` for template literal, (, or an identifier
 --> <anon>:1:1
  |
1 | }
  | ^

Error: Uncaught TypeError: Parse failed
$ curl localhost:8080/dev/hello
"hello, world!"$ cp endpoints/hello.js endpoints/zzz.js 
$ curl -v localhost:8080/dev/zzz
*   Trying ::1:8080...
* connect to ::1 port 8080 failed: Connection refused
*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /dev/zzz HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.76.1
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< transfer-encoding: chunked
< date: Thu, 16 Dec 2021 02:59:04 GMT
< 
* Connection #0 to host localhost left intact

Inspector is (too) lazy

The inspector does not start up until an endpoint is invoked, which makes it hard to discover by newbies. Let's make the inspector available via CLI option (perhaps enable by default) and make it visible by default. Printing and URL that automatically opens the browser inspector is a plus.

`chisel type export` order is not stable

The chisel type export order is not stable across restarts of chiseld:

penberg@neumann chiselstrike % cargo run --bin chisel type export
    Finished dev [unoptimized + debuginfo] target(s) in 0.11s
     Running `target/debug/chisel type export`
class Person {
  first_name: String;
  last_name: String;
}
class Position {
  title: String;
}
penberg@neumann chiselstrike % cargo run --bin chisel type export
    Finished dev [unoptimized + debuginfo] target(s) in 0.11s
     Running `target/debug/chisel type export`
class Position {
  title: String;
}
class Person {
  first_name: String;
  last_name: String;
}

We should define some ordering of types (alphabetical order?) and also fields and ensure chisel type export adheres to that.

Not a lot of information in 500 errors

If JS execution fails (with an exception for example), we return a 500 HTTP error:

                .status(StatusCode::INTERNAL_SERVER_ERROR)
                .body(format!("{:?}\n", err).into()),

Somewhere along the way information is lost and we don't include enough information to discover where the error is from. We should try to include a full backtrace, at least in dev mode.

Types with repeated names are not persisted

To reproduce, import the following types on an empty database:

type First {
	repeated_name: String
}

type Second {
	repeated_name: String
}

The second errors out with:

Error: status: Internal, message: "execution failed: `error returned from database: UNIQUE constraint failed: field_names.field_name`", details: [], metadata: MetadataMap { headers: {"content-type": "application/grpc", "date": "Mon, 01 Nov 2021 23:28:10 GMT"} }

Which apparently comes from this line in meta/mod.rs:

            let add_field_name =
                sqlx::query("INSERT INTO field_names (field_name, field_id) VALUES ($1, $2)");

Indeed there is a UNIQUE clause on field_name

CREATE TABLE `field_names` ( `field_name` text UNIQUE, `field_id` integer, FOREIGN KEY (`field_id`) REFERENCES `fields` (`field_id`) ON DELETE CASCADE );

So we have to either prepend the field_name with the type's name, or remove the unique constraint.

As you guys know this better, I'll leave it up to you how to fix it.

Deno runtime is not re-initialized on "chisel restart"

I noticed that the "cargo test" command fails with a weird assertion in my Deno data access branch. After debugging it a bit, I realized that the Deno runtime -- a static thread-local thing -- is not reinitialized upon "chisel restart", which means we attempt to re-register the ops.

Dropping a policy has bad UI

If you import the following YAML:

labels:
  - name: L1
    transform: anonymize

and then change it to this:

labels:
  - name: L2
    transform: anonymize

the policy on L1 will remain in the system. To drop it, you must add this:

labels:
  - name: L1

This is unintuitive and unnecessary. We should make chisel apply clobber old state.

type export should become `describe`

As we move to chiseld-versioning, type export is insufficient since it doesn't tell users about important things like policies, endpoints, etc.

It should become describe, but do more than just spit the files back to the user:
for example, for a given endpoint, or type, it should mention which policies affect it.

This is how the user would reason about what's going on in the deployment.

@penberg FYI

Our endpoints are single threaded

We need to get a lock on api to find what we are routing to, but we keep the lock while executing the endpoint:

                let mut api = api.lock().await;
                api.route(req).await

cli/tests/integration_tests.rs depends on the chiseld binary but doesn't build it

This results in cargo test failing on a clean checkout with the following error:

running 1 test
test tests::lit ... FAILED

failures:

---- tests::lit stdout ----
thread 'tests::lit' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }', cli/tests/integration_tests.rs:28:55
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

chiseld using postgres backend: error returned from database: syntax error at or near "WHERE"

Fresh build of chiseld (git fd03edf) trying to connect to a running postgres fails:

Error: fetch failed `error returned from database: syntax error at or near "WHERE"`

Caused by:
    0: error returned from database: syntax error at or near "WHERE"
    1: syntax error at or near "WHERE"

This happens in k8s and in a local test setup.

Local reproducer:

  1. install postgres:
podman run -d --name some-postgres     -e POSTGRES_PASSWORD=password -e POSTGRES_USER=pg -p 5432:5432 postgres
podman exec -it some-postgres bash
root@05a81a6a5d6f:/# psql -U pg -W
Password: 
psql (14.1 (Debian 14.1-1.pgdg110+1))
Type "help" for help.

pg=# 
pg=# 
pg=# 
pg=# create database chiseld;
CREATE DATABASE
pg=# create database chiseldmeta;
CREATE DATABASE
pg=# \q

Now that it's ready and prepared, run chiseld:

$ ./chiseld --help
chiseld 0.1.0

USAGE:
    chiseld [FLAGS] [OPTIONS]

FLAGS:
    -h, --help           Prints help information
        --inspect-brk    Should we wait for a debugger before executing any JS?
    -V, --version        Prints version information

OPTIONS:
    -a, --api-listen-addr <api-listen-addr>      API server listen address [default: 127.0.0.1:8080]
    -d, --data-db-uri <data-db-uri>              Data database URI [default: sqlite://chiseld-data.db?mode=rwc]
    -e, --executor-threads <executor-threads>    How many executor threads to create [default: 1]
    -m, --metadata-db-uri <metadata-db-uri>      Metadata database URI [default: sqlite://chiseld.db?mode=rwc]
    -r, --rpc-listen-addr <rpc-listen-addr>      RPC server listen address [default: 127.0.0.1:50051]

$ ./chiseld -d postgres://pg:password@localhost/chiseld -m postgres://pg:password@localhost/chiseldmeta
Error: fetch failed `error returned from database: syntax error at or near "WHERE"`

Caused by:
    0: error returned from database: syntax error at or near "WHERE"
    1: syntax error at or near "WHERE"

Linux release tarballs

Tweak scripts/build-tarball.sh to build a static executable that can run on multiple Linux distributions for release purposes:

V8_FROM_SOURCE=1 OPENSSL_STATIC=1 OPENSSL_LIB_DIR=/usr/lib64 OPENSSL_INCLUDE_DIR=/usr/include/ cargo build --release --target=x86_64-unknown-linux-musl

Current depends on the following fix from @espindola circling back to us:

denoland/rusty_v8#855

Cannot have a field `id` in a type

$ cat types/t.ts 
class Person {
    id: bigint;
}
$ chisel apply
Error: execution failed: `error returned from database: duplicate column name: id`

Unable to use `var img = new Image();` in endpoint

I would like to use Image class in my chisel endpoint to parse an image and determine it's size. That turned out to be impossible as the endpoint seems to crash (return 500) immediately after I create the variable. Minimal endpoint to reproduce:

export default async function chisel(req) {
    var img = new Image();
}

I suspect that Image internally uses window or something which Deno doesn't provide. Chiseld also doesn't provide any useful debugging log or message.

Deno TLS build error when attempting to "cargo install"

When I attempt to run cargo install, build fails as follows whereas cargo build --release works fine...

$ cargo install --path server --bin chiseld
  Installing server v0.1.0 (/Users/penberg/src/chiselstrike/chiselstrike/server)
    Updating crates.io index
    Updating git repository `https://github.com/hyperium/hyper`
   Compiling swc_ecma_transforms_base v0.44.7
   Compiling deno_runtime v0.33.0
error: failed to run custom build command for `deno_runtime v0.33.0`

Caused by:
  process didn't exit successfully: `/Users/penberg/src/chiselstrike/chiselstrike/target/release/build/deno_runtime-c87bd89b2493d9e4/build-script-build` (exit status: 101)
  --- stdout
  cargo:rustc-env=TARGET=aarch64-apple-darwin
  cargo:rustc-env=PROFILE=release
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_core-0.107.0/00_primordials.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_core-0.107.0/01_core.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_core-0.107.0/02_error.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_webidl-0.25.0/00_webidl.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_console-0.25.0/01_colors.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_console-0.25.0/02_console.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_url-0.25.0/00_url.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_url-0.25.0/01_urlpattern.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_web-0.56.0/00_infra.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_web-0.56.0/01_dom_exception.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_web-0.56.0/01_mimesniff.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_web-0.56.0/02_event.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_web-0.56.0/02_structured_clone.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_web-0.56.0/03_abort_signal.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_web-0.56.0/04_global_interfaces.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_web-0.56.0/05_base64.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_web-0.56.0/06_streams.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_web-0.56.0/08_text_encoding.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_web-0.56.0/09_file.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_web-0.56.0/10_filereader.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_web-0.56.0/11_blob_url.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_web-0.56.0/12_location.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_web-0.56.0/13_message_port.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_fetch-0.48.0/01_fetch_util.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_fetch-0.48.0/20_headers.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_fetch-0.48.0/21_formdata.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_fetch-0.48.0/22_body.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_fetch-0.48.0/22_http_client.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_fetch-0.48.0/23_request.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_fetch-0.48.0/23_response.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_fetch-0.48.0/26_fetch.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_websocket-0.30.0/01_websocket.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_websocket-0.30.0/02_websocketstream.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_webstorage-0.20.0/01_webstorage.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_crypto-0.39.0/00_crypto.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_crypto-0.39.0/01_webidl.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_webgpu-0.26.0/01_webgpu.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_webgpu-0.26.0/02_idl_types.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_timers-0.23.0/01_timers.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_timers-0.23.0/02_performance.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_broadcast_channel-0.19.0/01_broadcast_channel.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_ffi-0.12.0/00_ffi.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_net-0.17.0/01_net.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_net-0.17.0/02_tls.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_net-0.17.0/04_net_unstable.js
  cargo:rerun-if-changed=/Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_http-0.17.0/01_http.js

  --- stderr
  thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Unable to build http client: builder error: Unknown TLS backend passed to `use_preconfigured_tls`', /Users/penberg/.cargo/registry/src/github.com-1ecc6299db9ec823/deno_fetch-0.48.0/lib.rs:103:10
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...
error: failed to compile `server v0.1.0 (/Users/penberg/src/chiselstrike/chiselstrike/server)`, intermediate artifacts can be found at `/Users/penberg/src/chiselstrike/chiselstrike/target`

Caused by:
  build failed

relational_row_to_json panics with a float row

Context is I am trying to make Chisel.store return a Person object (which I figured it is best than just the ID)

So I add a RETURNING * clause to the insert statement and try to construct the object from that.
This panics. Relevant backtrace:

thread '<unnamed>' panicked at 'not implemented', /Users/glauber/.cargo/registry/src/github.com-1ecc6299db9ec823/sqlx-core-0.5.7/src/any/types.rs:28:1
stack backtrace:
   0: rust_begin_unwind
             at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/panicking.rs:517:5
   1: core::panicking::panic_fmt
             at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/panicking.rs:100:14
   2: core::panicking::panic
             at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/panicking.rs:50:5
   3: sqlx_core::any::types::<impl sqlx_core::types::Type<sqlx_core::any::database::Any> for f64>::type_info
             at /Users/glauber/.cargo/registry/src/github.com-1ecc6299db9ec823/sqlx-core-0.5.7/src/any/type.rs:12:17
   4: sqlx_core::error::mismatched_types
             at /Users/glauber/.cargo/registry/src/github.com-1ecc6299db9ec823/sqlx-core-0.5.7/src/error.rs:143:9
   5: sqlx_core::row::Row::try_get
             at /Users/glauber/.cargo/registry/src/github.com-1ecc6299db9ec823/sqlx-core-0.5.7/src/row.rs:124:29
   6: sqlx_core::row::Row::get
             at /Users/glauber/.cargo/registry/src/github.com-1ecc6299db9ec823/sqlx-core-0.5.7/src/row.rs:73:9
   7: chisel_server::query::engine::relational_row_to_json
             at ./server/src/query/engine.rs:358:28
   8: chisel_server::query::engine::QueryEngine::add_row::{{closure}}
             at ./server/src/query/engine.rs:338:9

Endpoint path sanitization

The endpoint path matching is a dumb string comparison, which breaks if you have extra trailing slashes in the path, for example.

Move to the TSC compiler

If I understand the code, Deno currently uses SWC for tooling and TSC for actual compilation. We have example code using SWC which seems a lot simpler than what deno has for TSC.

The advantages of using TSC is that it is what deno uses and is the "official" compiler. It would also avoid the cargo dependency problems with SWC.

The disadvantages of using TSC is that it is written in JS, so running it is a fork/exec and we have to bundle it. There is a lot of code for interacting with TSC in deno_cli which we might be able to refactor into its own crate if we go this way.

`cargo test` fails with `Connection refused`

Running cargo test on c1e19e6:

FAIL :: status.lit

test failed: unsuccessful program execution whilst running test

command '/home/dejan/src/chiselstrike/target/debug/chisel status' exited with code '1'

NOTE: the program '/home/dejan/src/chiselstrike/target/debug/chisel status' emitted text on standard error:

<stderr>:

  1|      Error: transport error
  2|
  3|      Caused by:
  4|          0: error trying to connect: tcp connect error: Connection refused (os error 111)
  5|          1: tcp connect error: Connection refused (os error 111)
  6|          2: Connection refused (os error 111)

</stderr>

Incomplete alias support

We want to support field aliases since they simplify renames, as a field can be aliased while the endpoints are converted to use the new name.

What is missing is:

  • Representing that in the rust types. The Field type should probably have a column_name, similar to how we have a backing_table in types.

    pub struct Field {
    pub name: String,
    pub type_: Type,
    pub labels: Vec,
    }

  • Storing the column_name in the metadata db.

    CREATE TABLE `fields` ( `field_id` integer PRIMARY KEY AUTOINCREMENT, `field_type` text, `type_id` integer, FOREIGN KEY (`type_id`) REFERENCES `types` (`type_id`) ON DELETE CASCADE );
    

A simple way to see that this is incomplete is to manually add an alias. Given a DB with cli/examples/person.graphql imported, run:

 INSERT INTO field_names VALUES ("Person.given_name", 1);

This should make given_name an alias of first_name, but running chisel export shows a Person type with 3 independent fields.

Runtime is single-threaded

V8 isolates can live in a single thread so we now made the runtime single-threaded as of 653139d. However, let's work on making the runtime multithreaded again.

Endpoint TLS support

Endpoints are likely accessed over public internet, which is why we need TLS support for them.

chisel restart should probably restart the process

I just sent a pull request for restarting deno. That works, but convinced me that our restart infrastructure is too complicated. We should probably really restart the process using nix::unistd::execv or just exit and have chisel start a new chiseld.

A big advantage is that we would be able to use Once or lazy_static. We would also not need to worry about complications around restarting deno with futures pending that are using the old one.

Returning JSON from endpoints is hard

I am trying to write an endpoint that returns JSON but it turns out to be hard.

I have so far managed to come up with this:

export default async function chisel(req) {
    let response = "";
    let posts = await Chisel.find_all("Post");
    for await (let post of posts) {
        response += post.title;
        response += " ";
    }
    return new Response(JSON.stringify({"response": response}));
}

which is not only cumbersome from API point of view, but also returns the wrong content type:

% curl -v localhost:8080/posts
*   Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 8080 failed: Connection refused
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /posts HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/1.1 200 OK
< content-type: text/plain;charset=UTF-8
< access-control-allow-origin: *
< transfer-encoding: chunked
< date: Tue, 02 Nov 2021 12:53:48 GMT
< 
* Connection #0 to host localhost left intact
{"response":"hello, blog post! "}* Closing connection 0

Iterators are not always released

The Chisel.find_all() JavaScript function returns an iterator that is backed by a Rust QueryStreamResource object, which needs to be released at some point.

In JavaScript, you can implement a "return()" function for an iterator, which is called if the iterator is partially consumed.

For example, if you do the following (break out of iteration loop after first element):

let people = await Chisel.find_all("Person");
for await (let person of people) { 
  response += person.first_name;
  response += " ";
  break;
} 

The "return()" function is called to clean up. Our Chisel.find_all() iterator implements release() so this part is fine.

However, if you do:

let people = await Chisel.find_all("Person");

or even:

let people = await Chisel.find_all("Person");
people.next();

The "return()" function is not called, leaving the iterator alive. For us, this means that user can potentially leave QueryStream objects, for example, alive...

chisel apply kills the authentication-callback route

$ curl -v http://localhost:8080/__chiselstrike/auth/callback?user=Sekula
[snip]
< HTTP/1.1 307 Temporary Redirect
< location: http://localhost:3000/profile?chiselstrike_token=f5557548-0d8d-447f-ac63-c09d31ab8bea
$ chisel apply
Type defined: Person
End point defined: /api/get_all_people
End point defined: /api/import_person
$ curl -v http://localhost:8080/__chiselstrike/auth/callback
[snip]
< HTTP/1.1 404 Not Found

We should preserve routes under /__chiselstrike and only drop user routes.

We need a way to to check chiseld is up and running

Currently we use sleeps, but those are both slow and unreliable.

It might be sufficient to add a "chisel wait" command that runs "chisel status" with an exponential backoff until status is OK.

We then do have to make sure status only responds once the full server is running, but even without that a chisel wait would be an improvement.

Listen to IPv6 addresses

The chiseld server listens to 127.0.0.1 by default, which makes accessing the server via localhost difficult on IPv6-enabled setups. Make chiseld also listen to the IPv6 address.

Prisma client API support

It would be nice to be able to use the Prisma client API in ChiselStrike endpoints. As pointed out by @espindola, running Prisma as-is is hard because of various issues (Prisma does not run on Deno, we would need to integrate with the Prisma Engine), but we could likely re-target the Prisma client code generator for ChiselStrike.

Hot reload chisel.js during development

Currently, if you modify chisel.js, you need to rebuild chiseld for the changes to be effective. Let's make chisel.js hot reload during development to remove the need to compile.

wrong response from endpoints when changing policies

prepping for the demo today, I have those two endpoints:

export default async function chisel(req: Request) {
    var url = new URL(req.url);
    let country = url.searchParams.get("country")

    let response = "";
    for await (let person of Chisel.Person) {
	if (person.country === country) {
	    response += person.name
	    response += "\n"
	}
    }
    return new Response( response );
}
export default async function chisel(req: Request) {
    const url = new URL(req.url);
    const arg = url.searchParams.get("country")

    let people = Chisel.Person.findMany({ "country": arg });

    let count = 0;
    for await (let person of people) {
	count += 1
    }
    return new Response(count + "\n");
}

Everything works well if there is a @pii label on name.
But as soon as I add a @pii label to country as well, the find endpoint now returns an empty result, and the count endpoint returns 0 (hard to say if it is working or broken as well)

That is not permanent, and if I remove the @pii label from country, the find endpoint works again (returns anonymized results)

Unexpected reserved word syntax error at __chiselstrike/rpc_errormsg

If I define an endpoint as JavaScript as follows:

% cat endpoints/hello.js
export default function chisel(req) {
    let person = await req.json();
    return Chisel.json("OK");
}

I get a really odd error message with chisel apply:

% chisel apply
Error: parsing endpoint hello:
TypeError: Uncaught SyntaxError: Unexpected reserved word
    at file://$chisel$/__chiselstrike/rpc_errormsg?ver=0:2:17

Uncaught TypeError: invalid op id

When user submits data which are inconsistent with corresponding type, the user gets a nice error:

Uncaught Error: provided data for field `age` are incompatible with given type `Person`
  9 |          at file://$chisel$/:22:4

but the console output of chiseld is

  24|      deno:core/01_core.js:4229: Uncaught TypeError: invalid op id: expected type `rusty_v8::data::Integer`, got `rusty_v8::data::Value`
  25|      deno:core/01_core.js:4229: Uncaught TypeError: invalid op id: expected type `rusty_v8::data::Integer`, got `rusty_v8::data::Value`

which isn't desirable.

How to reproduce
Create a type, submit incompatible data.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.