elysiajs / elysia

Ergonomic Framework for Humans
https://elysiajs.com
MIT License
10.25k stars 219 forks source link

get "EvalError: Code generation from strings disallowed for this context" when deploying to cloudflare worker #58

Closed implicit-invocation closed 11 months ago

implicit-invocation commented 1 year ago
import { Elysia } from "elysia";
import { cors } from "@elysiajs/cors";
import { swagger } from "@elysiajs/swagger";

const app = new Elysia()
  .use(swagger())
  .use(cors())
  .get("/", () => "Hello Elysia");

export default {
  async fetch(req: Request) {
    return await app.handle(req);
  },
};

I tried to deploy this using wrangler, but it seems that the build contains some eval call.

  Uncaught Error: EvalError: Code generation from strings disallowed for this
  context
    at index.js:5549:15 in composeHandler
    at index.js:7173:407 in add
    at index.js:7290:21 in get
    at index.js:7533:8
    at index.js:7283:18 in use
    at index.js:7595:20
   [code: 10021]

Is there any way to work around this?

implicit-invocation commented 1 year ago

it seems that elysia actually uses code generation from string https://github.com/elysiajs/elysia/blob/main/src/compose.ts

ryoppippi commented 1 year ago

I got the same issue I hope this issue to be solved

SaltyAom commented 1 year ago

In an upcoming release of Elysia, Code Generation will be disabled by default on Cloudflare Worker, you can try out on Elysia 0.6.0-alpha.2 to see if it's solved the problem.

b2df605

Please leave this issue open until 0.6.0 stable is released.

ryoppippi commented 1 year ago

I tried. When I write code like this

const app = new Elysia({
  aot: false,
})
  .get("/", () => "Hello Elysia")
export default app;

it works fine. But if I write code like this

const app = new Elysia({
  aot: false,
})
  .get("/", () => "Hello Elysia")
  .post(
    "/post",
    async (event) => {
      const body = event.body;
      return body;
    },
    {
      body: t.Object({
        username: t.String(),
        password: t.String(),
      }),
    }
  );

export default app;

It causes errors like this

service core:user:hi-elysia: Uncaught Error: EvalError: Code generation from strings disallowed for this context
  at index.js:3307:45 in Compile
  at index.js:7118:135 in getSchemaValidator
  at index.js:8289:22 in add
  at index.js:8413:17 in post
  at index.js:8503:35
ryoppippi commented 1 year ago

OK, I think this error comes from typebox

// node_modules/.pnpm/@sinclair+typebox@0.29.6/node_modules/@sinclair/typebox/compiler/compiler.js

...
      function Compile(schema, references = []) {
        const code = Code(schema, references, { language: "javascript" });
        const customs = new Map(state.customs);
        const compiledFunction = globalThis.Function("custom", "format", "hash", code);
        const checkFunction = compiledFunction((kind, schema_key, value) => {
          if (!Types.TypeRegistry.Has(kind) || !customs.has(schema_key))
            return false;
          const schema2 = customs.get(schema_key);
          const func = Types.TypeRegistry.Get(kind);
          return func(schema2, value);
        }, (format, value) => {
          if (!Types.FormatRegistry.Has(format))
            return false;
          const func = Types.FormatRegistry.Get(format);
          return func(value);
        }, (value) => {
          return hash_1.ValueHash.Create(value);
SaltyAom commented 1 year ago

Setting aot to false in Elysia 0.6.0 stable should force typebox to use JIT instead of AoT, so this problem so be fixed.

See Dynamic Mode.

Please let me know if this solve your problem.

implicit-invocation commented 1 year ago

In my case, setting aot to false makes the errors go away.
But swagger plugin will return No operations defined in spec!
To make it work with cloudflare worker, I will have to figure out how to access env and type the env also (not only for variables but also for durable objects, d1, r2, KV).

SaltyAom commented 1 year ago

Hi, sorry I have just seen this update.

Swagger should be working by updating Elysia 0.6.8

implicit-invocation commented 1 year ago
const app = new Elysia({ aot: false })
  .use(swagger())
  .derive((): { test: string } => ({
    test: "lorem ipsum",
  }))
  .get("/", (c) => {
    console.log(c.test);
    return "Hello Elysia";
  });

As posted on discord, swagger issue is fixed, but the code above will log undefined, seems that {aot: false} breaks derive.

SaltyAom commented 1 year ago

Right, patched it, derive should now works in 0.6.9