Hey 馃憢
I'm trying to use native esm modules in relations.
Two models - Huddle, HuddleJoinRequest, they import each other. Here is simplified HuddleJoinRequest model:
class HuddleJoinRequest extends BaseModel {
static relationMappings = {
huddle: {
modelClass: Huddle
}
}
}
With direct import I get circular dependency with error:
ReferenceError: Cannot access 'Huddle' before initialization
From docs I've tried solution 2 (path to model):
class HuddleJoinRequest extends BaseModel {
static relationMappings = {
huddle: {
modelClass: path.join(path.dirname(fileURLToPath(import.meta.url)), 'Huddle')
}
}
}
Error:
Error: HuddleJoinRequest.relationMappings.huddle: Must use import to load ES Module: ...
require() of ES modules is not supported.
I've also tried solution 3 (set modelPaths):
class HuddleJoinRequest extends BaseModel {
static modelPaths = [path.dirname(fileURLToPath(import.meta.url))]
static relationMappings = {
huddle: {
modelClass: 'Huddle'
}
}
}
Error is the same as above one.
I've also tried await import (similar to solution 1 I believe):
class HuddleJoinRequest extends BaseModel {
static relationMappings = async () => ({
huddle: {
modelClass: await import('./Huddle')
}
})
}
error is:
Error: A model class HuddleJoinRequest doesn't have relation huddle
I believe it's because relationMappings promise is not resolved in time.
Last one I've tried is:
class HuddleJoinRequest extends BaseModel {
static relationMappings = {
huddle: {
modelClass: () => import('./Huddle')
}
}
}
Error is:
console
Error: HuddleJoinRequest.relationMappings.huddle: modelClass: is not a subclass of Model or a file path to a module that exports one.
You may be dealing with a require loop. See the documentation section about require loops.
I'm not using Babel or Typescript to transpile code, just Node 14 and Objection 2.2.13 with plain esm module imports.
Wondering what's the solution for this.
Thanks
I reserved my sunday for exploring objection.js, and I was struggling with this issue too, just as I was checking objection.js issues I saw yours. What a coincidence :)
I think the solution is just to import the Model from the top, and make relation mappins a thunk. That is supposed to prevent circular dependencies as mentioned in koa example:
// property can be a thunk to prevent circular dependencies.
static relationMappings = () => ({
https://github.com/Vincit/objection.js/blob/master/examples/koa-ts/models/Movie.ts
@alimertcakar yep, it works, thank you 馃コ
I had used it before and didn't try now because linter screamed at me as soon as I wrote top import.
Wondering if solutions from docs can be adapted to support esm modules, especially with upcoming 3.0 and https://github.com/Vincit/objection.js/issues/2023.
I'd love to use modelPaths in BaseModel and just use string model name in modelClass.
modelPaths or path strings can't be easily supported because esm imports are async and the code that parses relationMappings is synchronous. Making it async would turn every place that uses it async and those would turn all places that use them async and so on.
@koskimas what's the recommended solution though? 馃 None of solutions from docs would work with esm imports.
Most helpful comment
modelPathsor path strings can't be easily supported because esm imports are async and the code that parsesrelationMappingsis synchronous. Making it async would turn every place that uses it async and those would turn all places that use them async and so on.