I’m working on a project using Deno, ReScript 12, Fresh, and i’m trying to add in rescript-edgedb.
ReScript is all happy and compiles just fine, it’s during runtime I get an error.
Here’s a snippet of the source code:
let client = Db.client
let res = await client->Db.insertMovie({ratingKey: "123"})
Which leads to this compiled JS being used from rescript-edgedb/src/EdgeDB.js
import * as Exn from "rescript/lib/es6/Exn.js";
import * as Edgedb from "edgedb";
import * as Primitive_option from "rescript/lib/es6/Primitive_option.js";
import * as Primitive_exceptions from "rescript/lib/es6/Primitive_exceptions.js";
The error:
error: Uncaught (in promise) TypeError: Unable to load /home/josh2/Dev/plex-movie-night/node_modules/.deno/rescript@11.1.4/node_modules/rescript/lib/es6/Primitive_option.js imported from file:///home/josh2/Dev/plex-movie-night/routes/api/login.js
Caused by:
No such file or directory (os error 2)
Looking inside of node_modules and that file does not exist. I also tried setting "external-stdlib" : "@rescript/std"
and that also pointed to a file that did not exist.
your repro looks weird because you’re saying you use ReScript v12 but the error points at rescript@11.1.4
and the runtime files changed a lot since then. Try to make sure you do use rescript v12 (which version are you using btw?) everywhere.
I’m on "version": "12.0.0-alpha.7"
. I’m configured to use rescript@next
.
rescript-edgedb
is using "rescript": "^11.1.0"
.
Deno is using a nested version of rescript@11.1.4
and a version of rescript@12.0.0-alpha-7
and it’s pulling in 11.1.4 when it’s importing from the compiled JS from rescript-edgedb
.
I think I need to adjust something in the way Deno is configured.
Even with a simple example like this:
// testing.js
import * as Primitive_option from "npm:rescript/std/lib/es6/Primitive_option.js";
console.log(Primitive_option);
It is still trying to import from version 11.
I do have this set in my deno.json file:
"imports": {
"rescript": "npm:rescript@12.0.0-alpha.7",
}
If I change the source code to
import * as Primitive_option from "rescript/std/lib/es6/Primitive_option.js";
I get a different error.
error: Could not resolve 'npm:rescript@12.0.0-alpha.7/std/lib/es6/Primitive_option.js'.
Caused by:
[ERR_PACKAGE_PATH_NOT_EXPORTED] Package subpath './std/lib/es6/Primitive_option.js' is not defined by "exports" in '/home/josh2/Dev/plex-movie-night/node_modules/.deno/rescript@12.0.0-alpha.7/node_modules/rescript/package.json' imported from 'file:///home/josh2/Dev/plex-movie-night/testing.js'
I can get that basic example to work if I update the package.json
for the rescript/package.json
and add this:
"exports": {
"./std/lib/es6/*": "./lib/es6/*", // add this
"./lib/es6/*": "./lib/es6/*",
"./lib/js/*": "./lib/js/*",
"./package.json": "./package.json"
},
The full app is still getting errors.
I figured it out!
In rescript.json
you have to set an extenal stdlib.
"external-stdlib" : "@rescript/std"
And in deno.json
:
"imports": {
"rescript": "npm:rescript@12.0.0-alpha.7",
"@rescript/std": "npm:@rescript/std@12.0.0-alpha.7",
/* ... */
}
There might be an opportunity to publish @rescript/std
on JSR.
1 Like
I don’t understand, which of your dependencies is supposed to use @rescript/std?
Setting @rescript/std
allows me to force the Deno runtime to use the same version.
By default it imports from rescript
, which resolves to a different version for the main app, v12, and rescript-edgedb
, v11. ReScript is changing the compiled code in node_modules
, which Deno picks up on, but Deno runs/bundles the code with the packages exact dependency versions. So while the code in node_modules/rescript-edgedb
is compiled with ReScript v12 the runtime is looking for v11. So by using @rescript/std
I can force everything that ReScript compiles to import the same version, since I have defined the version for @rescript/std
in my deno.json file.
Now this would all break if rescript-edgedb
was using an older version of @rescript/std
for some reason. I’m also not sure what would happen if one of my ReScript dependencies depended on another ReScript dependency.
This would just break if any line of code uses an API that got changed between v11 and v12. Can’t you force the resolution of rescript instead? At least it would break on compile time and not on runtime.
Maybe. I’m still learning Deno, but I haven’t found a way to tell Deno to override dependencies. It’s somewhat baked into the module resolution for files to be more portable, to the point where you can list a version number for an individual import.