ts-sql-codegen icon indicating copy to clipboard operation
ts-sql-codegen copied to clipboard

What is the recommended way to use this tool with ESM projects?

Open thebongy opened this issue 1 year ago • 6 comments

Hi, thanks for building/maintaining this project! I had a small question: currently, the code generated from this project generates import statements of the form:

import { Table as Table4 } from "ts-sql-query/Table";
import { extractColumnsFrom as extractColumnsFrom4 } from "ts-sql-query/extras/utils";

This causes an issue, as relative imports in ESM require extensions, like so:

import { Table as Table4 } from "ts-sql-query/Table.js";
import { extractColumnsFrom as extractColumnsFrom4 } from "ts-sql-query/extras/utils.js";

Is there a work around for this, apart from using a custom NodeJS import loader/bundler (or --experimental-specifier-resolution for older node versions)?

thebongy avatar Mar 11 '24 15:03 thebongy

Hello, thanks for your interest.

So even if the generator here is updated to add extension, the underlying library (ts-sql-query) will need to be updated as well because that is also not esm friendly out of the box. There was some discussion around this in https://github.com/juanluispaz/ts-sql-query/issues/66 - perhaps we can continue the discussion with @juanluispaz there.

Once ts-sql-query supports ESM, I'll update this to add the .js extensions too.

Until then using a bundler or --experimental-specifier-resolution=node is your best bet.

lorefnon avatar Mar 11 '24 16:03 lorefnon

I am working right now on ts-sql-query 2.0, in which I want to address several things, including ESM

juanluispaz avatar Mar 11 '24 16:03 juanluispaz

Thanks @lorefnon @juanluispaz for the clarifications! Just leaving some additional comments, although i'll stick to using a custom node loader for now to get around this:

So even if the generator here is updated to add extension, the underlying library (ts-sql-query) will need to be updated as well because that is also not esm friendly out of the box

I don't believe the underlying library will need to be updated, due to how NodeJS ESM <> CJS interoperability works (https://nodejs.org/api/esm.html#import-statements). Have also verified this on Node LTS (v20), I was able to use an ESM import like the following to import from ts-sql-query (even though it is a CJS library):

import { extractColumnsFrom } from "ts-sql-query/extras/utils.js"

However, when I do it without the .js extension I get:

> node ./dist/index.js

node:internal/process/esm_loader:34
      internalBinding('errors').triggerUncaughtException(
                                ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/redacted/node_modules/ts-sql-query/extras/utils' imported from /redacted/dist/index.js
Did you mean to import ts-sql-query/extras/utils.js?

Until then using a bundler or --experimental-specifier-resolution=node is your best bet.

Although yes, this works for Node below v19 (https://github.com/nodejs/node/issues/45108). In v19, and the latest LTS (v20), this option does not exist anymore....., instead its recommended to use a custom loader (like https://www.npmjs.com/package/extensionless).

I am working right now on ts-sql-query 2.0, in which I want to address several things, including ESM

That's amazing! I was trying to avoid using a bundler/custom loader, although I do understand spending too much time on fixing this is probably not necessary right now if 2.0 is coming soon.

thebongy avatar Mar 11 '24 17:03 thebongy

I don't believe the underlying library will need to be updated, due to how NodeJS ESM <> CJS interoperability works (https://nodejs.org/api/esm.html#import-statements).

Yes, you are correct. Just verified.

In 3.20.0 I have added an option output.import.extension which can be set to .js to ensure that all imports have a .js extension.

I'll enable it by default in a future major version, but for now you can add this to your configuration:

output: {
    import: {
        extension: ".js"
    }
}

lorefnon avatar Mar 11 '24 18:03 lorefnon

Hi @lorefnon , thanks for rolling this out! I verified this new option works for some of the imports, but not the ones inside {{each}} blocks due to hbs scoping rules inside those. I have opened a PR and verified this fixes it (https://github.com/lorefnon/ts-sql-codegen/pull/16)

thebongy avatar Mar 12 '24 04:03 thebongy

Thank you.

lorefnon avatar Mar 12 '24 07:03 lorefnon