Has anyone tried FA on deno?

(Sorry about not following the template, kind of asking something different)

Since the new JS agent is very typey and nice to use, we’re considering switching to deno for various reasons which would turn this post into an ad if listed.

Has anyone done this before? If so, was it a seamless transition or were there some hurdles to overcome?

Hey :wave:

I did try running our agent-nodejs a while ago (way before 1.0) with little to no result.

I did a few tests after seeing your post using deno@latest, and it seems like I’m able to successfully start an agent using

deno --allow-env --allow-read --allow-sys --allow-net --allow-write index.ts

This seems to lead to a working agent for a few minutes.
However, after a fews minutes, I’m getting the following error

error: Uncaught (in promise) TypeError: error reading a body from connection

This still looks promising though, so I’ll investigate further to see if this is achievable, and share anything interesting here.

4 Likes

Ok, so here’s where I am at:

  • I can’t get anymore informations than what I shared earlier: error: Uncaught (in promise) TypeError: error reading a body from connection. Even opening a debugger doesn’t help, as it seems to be related to the inner of deno
  • Running the exact same code runs fine in nodejs… so I can’t really get much more.

However:

  • My first feeling was that maybe this issue was related to fetch. But we don’t fetch as is in the code (We do use axios though), so …
  • My second feeling was that maybe it’s related to our permission cache, which uses SSE to keep permission cache up to date.

Disabling it using instantCacheRefresh: false during the createAgent seems to do the trick :tada:

I can’t really recommand running the agent without this though, as permissions rely on SSE to make sure they are always up-to-date (So disabling it may lead to permission inconsistency).

Just to make sure I don’t forget anything, here’s what I did:

  • Added import { env } from 'node:process'; & switched all process.env to env on the base code of the agent.
  • Removed unecessary option in createSqlDataSource, as I encountered a few typing issues when giving it the classic uri/sslMode/schema.
import { env } from 'node:process';
import 'npm:dotenv/config';
import { createAgent } from 'npm:@forestadmin/agent';
import { createSqlDataSource } from 'npm:@forestadmin/datasource-sql';

import type { Schema } from './typings.ts';

try {
  const agent = createAgent<Schema>({
    authSecret: env.FOREST_AUTH_SECRET!,
    envSecret: env.FOREST_ENV_SECRET!,
    isProduction: env.NODE_ENV === 'production',
    typingsPath: './typings.ts',
    typingsMaxDepth: 5,
    instantCacheRefresh: false,
  });
  agent.addDataSource(createSqlDataSource(env.DATABASE_URL || ''));
  agent.mountOnStandaloneServer(Number(env.PORT));
  await agent.start();
} catch (err) {
  console.error(err);
}

Now that I know where to dig, I’ll check to see if I’m able to locate exactly what is causing this SSE issue, and keep you updated :+1:

2 Likes

(Ok so this is a message I started on Friday - but I thought that the outcome was a bit deceptive)

Hey :wave:

Not a lot of opportunities to work on this topic in the last few days - as I spent most of my available time trying to link our typescript monorepo to a deno project to investigate further in the code.

It led to a few inconsistency in our code base, especially regarding export/export type that I’ll fix in a PR in the next few days.

With the following import map, I was able to run deno on our local dependencies - Maybe there is a better way, but I’m no deno expert …

{
  "imports": {
    "@forestadmin/agent": "../agent-nodejs/packages/agent/src/index.ts",
    "@forestadmin/datasource-customizer": "../agent-nodejs/packages/datasource-customizer/src/index.ts",
    "@forestadmin/datasource-toolkit": "../agent-nodejs/packages/datasource-toolkit/src/index.ts",
    "@forestadmin/forestadmin-client": "../agent-nodejs/packages/forestadmin-client/src/index.ts",
    "object-hash": "npm:object-hash",
    "luxon": "npm:luxon",
    "stream": "node:stream",
    "uuid": "npm:uuid",
    "file-type": "npm:file-type",
    "antlr4": "npm:antlr4",
    "fs/promises": "node:fs/promises",
    "koa-bodyparser": "npm:koa-bodyparser",
    "json-stringify-pretty-compact": "npm:json-stringify-pretty-compact",
    "@koa/router": "npm:@koa/router",
    "@koa/cors": "npm:@koa/cors",
    "eventsource": "npm:eventsource",
    "events": "npm:events",
    "superagent": "npm:superagent",
    "jsonwebtoken": "npm:jsonwebtoken",
    "querystring": "npm:querystring",
    "openid-client": "npm:openid-client",
    "json-api-serializer": "npm:json-api-serializer",
    "crypto": "node:crypto",
    "path": "node:path",
    "net": "node:net",
    "koa": "npm:koa",
    "http": "node:http",
    "@fast-csv/format": "npm:@fast-csv/format",
    "koa-jwt": "npm:koa-jwt",
    "forest-ip-utils": "npm:forest-ip-utils",
    "fs": "node:fs"
   },
   "nodeModulesDir": "manual"
}

(And this is today’s investigation)

Switched to loggerLevel: "Debug", hoping to get more info on what’s going on, with no luck.
Added a bunch of logs, try catches & breakpoints in our @forestadmin/forestadmin-client integration, still with no luck.

I’ll open a discussion with the team that worked on the SSE integration, just to check if it rings a bell.

(And sorry for the “devlog” aspect of the topic. As I cannot find a lot of time to work on this topic, I try to document here all my tests as much as possible).

1 Like

And finally … We’re currently not compatible with deno.

Here’s the why - eventsource@2, a dependency we’re using, seems to have trouble working, especially with deno coming out of the box with a possible implementation of EventSource. This would definitely explain why instantCacheRefresh: false fixes the issue.

I quickly tried, with the import map, to switch to v3/next version of eventsource, but obviously, it seems like there are a few breaking changes, so we’ll need to investigate that further.

If possible on my end, I’ll try to switch to this new version in the following days to check whether or not it fixes the issue, and I’ll let you know.

2 Likes

Really appreciate the time you’re taking to look into this!

I’m happy with the devlog aspect and I hope that this endeavor is worth pursuing for your team.
Speaking of, what value do you see in supporting Deno for ForestAdmin?

Well, initially, I was mainly interested in:

  • Seeing what has been added in deno in general since the pre-release - as it was the version I was the most familiar with.
  • Solving your initial question with a positive answer :smiley:

Now:

  • It would increase our general compatibility, which is always a great news
  • After starting the investigation, it pointed a few inconsistencies in our nodejs integration, especially about what I said regarding export/export type, relative path declaration (.. vs ../, etc). Nothing major, but still things I’d like to be fixed :slight_smile:
  • Deno value promise seems great, and 2.0 speaks for itself. I’m pretty sure most of the typescript developers out there will, at some point, be interested in replacing their whole “classic” tooling system (eslint, prettier, typescript, …) and boilerplate by something like this.

Developer experience has been something essential in Forest Admin (We even have a feature team dedicated to this), especially with the “new” agent. So anything that could provide an even better experience for devs working with Forest is worth a try!

I’ll let you know whenever I’m able to work on this topic. Eventsource seems to have a pre-release that claims deno compatibility.

Hopefully, my next message will contain good news :crossed_fingers:

2 Likes