Trouble running migrations

M(Meithz (Razioner)4/2/2023
I am trying to use Kysely on a svelte-kit project, I set up the migration script like the example shown in the docs, but when trying to run the script with ts-node --esm "path/to/script" I receive failed to migrate
 CustomError: ERR_INVALID_MODULE_SPECIFIER src\lib\server\db\migrations\540540540_create_db.ts is not a valid package name E:\Code\Web\portfolio-projects\spotify-cp\node_modules\.pnpm\kysely@0.24.2\node_modules\kysely\dist\esm\migration\file-migration-provider.js 
I tried changin the migration file name, making it a JS file instead of TS but still get the same error, I am not sure what I am doing wrong, the scripts are the same as the examples in the docs.
Kkoskimas4/2/2023
Does it work without the --esm flag?
Kkoskimas4/2/2023
Oh, actually this could be just a case of relative paths instead of absolute. You need to use an absolute path to the migrations folder.
M(Meithz (Razioner)4/2/2023
I check using absolute path
M(Meithz (Razioner)4/2/2023
It doesn't work without the --esm flag but the error is from ts-node, because the project is using ESModules
M(Meithz (Razioner)4/2/2023
When trying with the absolute path I get an error, but it is about ESM path resolution in Windows
M(Meithz (Razioner)4/2/2023
[ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file and data are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'e:'
Kkoskimas4/2/2023
Well there it it. Just add file:// to the beginning. Did you even read the error 😄
M(Meithz (Razioner)4/2/2023
Still doesn't like it
M(Meithz (Razioner)4/2/2023
I run across this error before with another package
M(Meithz (Razioner)4/2/2023
Okey I went back to check the error I had come across in the other package, when using import() on Windows it requires the path to be a file URL, but I cannot pass it as that since I need to pass the directory, not the actual file. so when the migrator tries to import the migration file, there it should change it to a file URL.
M(Meithz (Razioner)4/2/2023
 for (const fileName of files) {
      if (
        fileName.endsWith('.js') ||
        (fileName.endsWith('.ts') && !fileName.endsWith('.d.ts')) ||
        fileName.endsWith('.mjs') ||
        (fileName.endsWith('.mts') && !fileName.endsWith('.d.mts'))
      ) {
        // Doing something like this fixes it in Windows:
        const migrationPath = filePathToURL(this.#props.path.join(
            this.#props.migrationFolder,
            fileName
          )).pathname
        
        const migration = await import( migrationPath)
        
        const migrationKey = fileName.substring(0, fileName.lastIndexOf('.'))

        // Handle esModuleInterop export's `default` prop...
        if (isMigration(migration?.default)) {
          migrations[migrationKey] = migration.default
        } else if (isMigration(migration)) {
          migrations[migrationKey] = migration
        }
      }
    }
M(Meithz (Razioner)4/2/2023
Doing that when the migrator attempts to import the file fixes the problem
M(Meithz (Razioner)4/2/2023
However I don't know how this would work on other operating systems
Kkoskimas4/2/2023
I don't understand. Why can't you just provide the beginning of the URL as the "folder" and then it will be suffixed with the file name --> still a valid URL
M(Meithz (Razioner)4/2/2023
Honestly I have no idea
M(Meithz (Razioner)4/2/2023
I think it fails when trying to read the directory for the filenames inside
Kkoskimas4/2/2023
Oh, damn. that's true
Kkoskimas4/2/2023
Why the hell is there a difference like this between windows and other platforms in node 😲
M(Meithz (Razioner)4/2/2023
I wondered the same thing the last time I had this problem, and it so specific to a small amount of users, because it is the combination of ESM + Windows that it is hard to locate
M(Meithz (Razioner)4/2/2023
They should at least make a very visible warning about this behaviour
Kkoskimas4/2/2023
Where does the filePathToURL function come from?
Kkoskimas4/2/2023
Or is it your own helper?
M(Meithz (Razioner)4/2/2023
from the 'url' node package
M(Meithz (Razioner)4/2/2023
import { pathToFileURL} from 'url'
M(Meithz (Razioner)4/2/2023
wrong order of words
M(Meithz (Razioner)4/2/2023
sorry
Kkoskimas4/2/2023
Crap.. Can't use that since there should be no references to node in Kysely
M(Meithz (Razioner)4/2/2023
Can you use the web API URL?
Kkoskimas4/2/2023
I'll fix that somehow. In the meantime you can just copy paste the FileMigrationProvider and use your own modified version
M(Meithz (Razioner)4/2/2023
Yeah I already did that. Trying to think of a way to fix it without depending on Node
Kkoskimas4/2/2023
Can you use the web API URL?
Yes, but I also need to check if we're on windows. That's node-specific
M(Meithz (Razioner)4/2/2023
how about allowing to pass a custom import
M(Meithz (Razioner)4/2/2023
or fileparser
Kkoskimas4/2/2023
The whole FileMigrationProvider API is already annoying. It takes the node dependencies as arguments
M(Meithz (Razioner)4/2/2023
Yeah I noticed that, so how about:
M(Meithz (Razioner)4/2/2023
    const migrator = new Migrator({
        db,
        provider: new FileMigrationProvider({
            fs,
            path,
            migrationFolder: 'E:/Code/Web/portfolio-projects/spotify-cp/src/lib/server/db/migrations'
        }),
        filePathParser: (path) => pathToFileURL(path).pathname,
    });
M(Meithz (Razioner)4/2/2023
filePathParser would be a better name
IIgal4/2/2023
Is wsl2 not an option?
M(Meithz (Razioner)4/2/2023
I guess it could be, haven't really tried to use it. But I think it would be better if it worked directly on windows, or if there was a easy way to make it work, like passing the filePathParser or something similar to the constructor
IIgal4/3/2023
Can you provide a repository I could clone and test on my windows machine?
M(Meithz (Razioner)4/3/2023
I will try to upload it tonight, you should be able to reproduce it just with a starter svelte-kit project in case you want to try it now
IIgal4/4/2023
I'll look at it today, thanks
IIgal4/5/2023
This is how its done in nuxt-cookie-control https://github.com/dargmuesli/nuxt-cookie-control/pull/57/files#diff-030fc083b2cbf5cf008cfc0c49bb4f1b8d97ac07f93a291d068d81b4d1416f70R113-R114

so maybe something like this should work?

  async getMigrations(): Promise<Record<string, Migration>> {
    const migrations: Record<string, Migration> = {}
    const files = await this.#props.fs.readdir(this.#props.migrationFolder)

    for (const fileName of files) {
      if (
        fileName.endsWith('.js') ||
        (fileName.endsWith('.ts') && !fileName.endsWith('.d.ts')) ||
        fileName.endsWith('.mjs') ||
        (fileName.endsWith('.mts') && !fileName.endsWith('.d.mts'))
      ) {
        const filePath = path.resolve(this.#props.migrationFolder, fileName)
        const migrationPath =
          os.platform() === 'win32'
            ? url.pathToFileURL(filePath).href
            : filePath
        const migration = await import(migrationPath)
        const migrationKey = fileName.substring(0, fileName.lastIndexOf('.'))

        // Handle esModuleInterop export's `default` prop...
        if (isMigration(migration?.default)) {
          migrations[migrationKey] = migration.default
        } else if (isMigration(migration)) {
          migrations[migrationKey] = migration
        }
      }
    }

    return migrations
  }
}
IIgal4/5/2023
I managed to patch-package kysely in your repo and reached a further point in Migrator flow.
IIgal4/5/2023
Its painful to run kysely's tests for windows with docker and everything, might do it tomorrow
M(Meithz (Razioner)4/5/2023
Yes, that way looks like it would work, but it is dependant on Node , and @koskimas said that it shouldn't have any dependencies in node. I also patched my kysely installation to make it work, without actually checking for the Os since I knew I was on windows.
IIgal4/5/2023
We could extend and override the file getting part with a Windows class
IIgal4/5/2023
and a Deno class?
IIgal4/5/2023
I don't like the part where the consumer has to pass fs and path. It probably doesn't make sense in deno
Kkoskimas4/5/2023
Me neither, but the other option was to not provide the whole thing
Kkoskimas4/5/2023
We can't import node-specific stuff or the build will break on non-node environments
Kkoskimas4/5/2023
Neither can we import Deno or Windows-specific stuff
Kkoskimas4/5/2023
Even dynamic imports cause problems with people's bunders
M(Meithz (Razioner)4/5/2023
What about having the migrator in a separate package for each environment? Although I think it would be annoying to mantain it that way
IIgal4/6/2023
Maybe we should recommend not bundling migrations? Recommend ts-node / tsx for running migrations instead?
IIgal4/6/2023
Also, quoting the first paragraph in the README file:

Mainly developed for node.js but also runs on deno and in the browser.
IIgal4/6/2023
I wonder if we could, by default, just use node's stuff, and allow to override the file import function as a whole with an interface such as:

importMigrationFile(folderPath: string, filename: string): Promise<Migration>
M(Meithz (Razioner)4/6/2023
I run into the problem using ts-node, so I don't think that would be a solution.
IIgal4/6/2023
That's to avoid the bundler issues. don't remember dynamic imports causing any problems with ts-node/tsx
M(Meithz (Razioner)4/6/2023
Oh
M(Meithz (Razioner)4/6/2023
Ok that makes sense
UUUnknown User4/10/2023
Message Not Public
Sign In & Join Server To View
M(Meithz (Razioner)4/10/2023
Just making the changes to the package code in my windows installation. That is the best I could do
UUUnknown User4/10/2023
2 Messages Not Public
Sign In & Join Server To View
M(Meithz (Razioner)4/10/2023
Yeah I wrote it down wrong in the example code
IIgal4/10/2023
Maybe this shouldn't be dynamically imported? Maybe CLI could create migration files (empty up & down) and import them where we need to iterate over them
UUUnknown User4/28/2023
Message Not Public
Sign In & Join Server To View
IIgal4/28/2023
I think a kysely-migrations-windows could be a good idea
UUUnknown User4/28/2023
Message Not Public
Sign In & Join Server To View
IIgal4/28/2023
afaik, it should work with deno out the box.