New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve Support for Liftoff's Preloaders #3613
Conversation
... Specifically: - resolveDefaultKnexfilePath(...) - resolveKnexFilePath(...)
This property is used when inferring the appropriate extension for the migration files
if (!opts.knexfile) { | ||
const configurationPath = resolveKnexFilePath(); | ||
const configuration = configurationPath | ||
? require(configurationPath.path) | ||
: undefined; | ||
|
||
env.configuration = configuration || mkConfigObj(opts); | ||
if (!env.configuration.ext && configurationPath) { | ||
env.configuration.ext = configurationPath.extension; | ||
} | ||
} | ||
// If knexfile is specified | ||
else { | ||
const resolvedKnexfilePath = path.resolve(opts.knexfile); | ||
const knexfileDir = path.dirname(resolvedKnexfilePath); | ||
process.chdir(knexfileDir); | ||
env.configuration = require(resolvedKnexfilePath); | ||
|
||
if (!env.configuration) { | ||
exit( | ||
'Knexfile not found. Specify a path with --knexfile or pass --client and --connection params in commandline' | ||
); | ||
} | ||
|
||
if (!env.configuration.ext) { | ||
env.configuration.ext = path | ||
.extname(resolvedKnexfilePath) | ||
.replace('.', ''); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic was essentially duplicating the "configuration file discovery" logic that was already provided by Liftoff. However, modules discovered via this control path would never utilize any of Liftoff's module pre-loaders. This is the reason that some users were observing syntax errors when attempting to load non-JS config files via the --knexfile
parameter. Ex: #2998
knexfile: argv.knexfile, | ||
knexpath: argv.knexpath, | ||
configPath: argv.knexfile, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Liftoff#launch(..)
method does not understand the knexfile
and knexpath
parameters. Furthermore, it does not pass them though to the env
object when calling the invoke(..)
callback.
const path = resolveDefaultKnexfilePath(); | ||
throw new Error( | ||
`No default configuration file '${path}' found and no commandline connection parameters passed` | ||
`No configuration file found and no commandline connection parameters passed` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This error message was rendering the config file name as knexfile.undefined
. This is because the resolveDefaultKnexfilePath()
was expecting an argument for the desired extension.
However, Knex actually supports many different config file extensions, including .ts
and .coffee
. So, it didn't really make sense to just show the .js
extension. Therefore, I removed the name from the error message.
function resolveKnexFilePath() { | ||
const jsPath = resolveDefaultKnexfilePath('js'); | ||
if (fs.existsSync(jsPath)) { | ||
return { | ||
path: jsPath, | ||
extension: 'js', | ||
}; | ||
} | ||
|
||
const tsPath = resolveDefaultKnexfilePath('ts'); | ||
if (fs.existsSync(tsPath)) { | ||
return { | ||
path: tsPath, | ||
extension: 'ts', | ||
}; | ||
} | ||
|
||
console.warn( | ||
`Failed to find configuration at default location of ${resolveDefaultKnexfilePath( | ||
'js' | ||
)}` | ||
); | ||
} | ||
|
||
function resolveDefaultKnexfilePath(extension) { | ||
return process.cwd() + `/knexfile.${extension}`; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dead code. (This detail is handled by Liftoff now)
FYI: This code currently breaks 1 unit test. Specifically:
This error occurs because Liftoff treats |
@briandamaged I am somewhat concerned about breaking scripts for existing users, but I guess just one case with cwd is not too bad, as long as we publish it as a major version. Can you add one more cli-testlab-based test that was failing prior to this change, so that we don't break your fix again in the future? I guess adding ts file would work. |
@kibertoad : Sure! I just wanted to get your feedback on the breaking change before moving forward w/ the other test cases. I should have some time to write them in the next day or so. |
... this way, we can be sure that the correct migrations are being run. (As opposed to a directory lookup error, or something like that)
@kibertoad : I've added some new tests, but I'm noticing a discrepancy. When both the Anyway, I'll do a bit more digging into this tomorrow. |
@kibertoad : A closely-related question: what is the intention of the
|
@briandamaged Prior discussions on this subject: #2959 and #2952 |
@briandamaged Would you like any help with this? |
@kibertoad : Howdy, and thx for following up! I got pulled into something else during the last few weeks, so I haven't been able to investigate this any further. However, I should have some time in the next few days. Once I get back to this, I'll create a table that compares the "Old Behavior" and "New Behavior" for various scenarios. From there, we can then discuss what the desired behavior in each scenario should be, and implement things accordingly. (Saying it another way: I think the "New Behavior" fixes certain problems, but it might introduce new problems as well. So, we need to make sure we agree upon the requirements / expectations). |
@kibertoad : Alright, here's the table demonstrating the behaviors for various command line arguments: https://docs.google.com/spreadsheets/d/19TMouhxdIosYGzubO-2lbxm8Ykx4jR-Iu74HXohFYMg/edit?usp=sharing As you can see:
So, based upon my understanding of the requirements, it looks like the behavior in |
As for the travis-ci failure: it looks like the |
@kibertoad : Okay, new update around the travis-ci error: it appears that
This causes the value of The problem: notice that The "quick fix" would be to restrict |
... Specifically: the default configuration for nyc causes it to add ".ts" to the the `require.extensions` list. The problem: Liftoff consults `require.extensions` when deciding which modules need to be preloaded. Since ".ts" is already on the list, Liftoff decides that "ts-node" must have already been preloaded. Therefore, it hands control off to the Knex CLI without ever registering Typescript support. Consequently, the Knex CLI will explode if it attempts to open a Knexfile that was written in Typescript. In other words: this error only occurs when `nyc` (or another tool) modifies `require.extensions` before handing control over to the Knex CLI.
"branches": 69, | ||
"extension": [ | ||
".js" | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI: This is the nyc
fix that I mentioned here:
Short story: it appears that nyc
's extension handling interferes with Liftoff
's extension handling. Thus, when you run the unit tests under nyc
, it fails to preload ts-node
properly.
Thanks! I'll take a look tomorrow. |
@kibertoad : FYI: I just added a couple more rows to the spreadsheet. These ones are for:
As you can see, the two branches behave a bit differently for this specific scenario. So, which of these behaviors do we want to keep? |
@kibertoad : Forgot to mention: I think I figured out an adjustment to the new code that will allow it to recreate the old behavior. To recap, let's say that:
In this case, the CLI will ultimately resolve the Knexfile at:
Personally, I think that the New Behavior makes more sense. That is: paths are always relative to the Shell's CWD. |
@briandamaged I agree that this makes more sense; however, this would be a breaking change and would require bumping second number. Could you also update https://github.com/knex/knex/blob/master/UPGRADING.md explaining under which circumstances users are likely to experience change in behaviour, and what they would need to change to get same result as before? |
If we can keep the way to recreate the old behaviour, though, that would be very helpful, as in general |
@kibertoad : Alright -- I went ahead and implemented a work-around that recreates the "classic" behavior. So:
|
// ensures that Liftoff will then resolve the path to `--knexfile` correctly. | ||
if (argv.cwd) { | ||
process.chdir(argv.cwd); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kibertoad : Here's the work-around that allows the CLI to retain the "classic" behavior.
@kibertoad : Howdy again! Just following up to see if there's anything you need on my side. Thx! |
@briandamaged Sorry, just started at new job and got distracted. This looks great and I would be happy to merge this. Any reasons why you kept WIP in title? |
@kibertoad : Ah -- nope. I just forgot to remove the Good luck on your new job, btw! Doing something interesting, I hope? |
@briandamaged Thanks! Oh yeah, brand new team, greenfield project, I'm extremely hyped about it. The only unfortunate thing is that I switched stacks and returned to Java world, so there'll be less eating of own's dog food, unfortunately. |
@kibertoad: Ah -- oh well. I've heard that the Java language / ecosystem has improved significantly over the last several years. So, it might not be that painful. Plus, there are several languages that compile into Java bytecode, such as Kotlin and Scala. So, you might be able to integrate those into whatever you're building. |
Well yeah, convincing folks over there to use Kotlin is one of my current dreams :D |
Revises the Knex CLI's initialization logic so that it takes better advantage of Liftoff's module pre-loading. More specifically:
"knexfile"
and"knexpath"
arguments from the call toLiftoff#launch(..)
.Importantly: this PR changes the CLI's behavior when both the
--cwd
and--knexfile
parameters are specified. Previously, the location of the--knexfile
was always relative to the value specified via--cwd
. Once this PR is merged, the two parameters will be independent of one another. This better aligns w/ the semantics used by Liftoff. For example: