adelsz / pgtyped

pgTyped - Typesafe SQL in TypeScript
https://pgtyped.dev
MIT License
2.91k stars 94 forks source link

wrong module resolution when using typescript from commonjs #570

Closed m-ronchi closed 3 months ago

m-ronchi commented 6 months ago

Describe the bug trying to use the latest version of pgtyped from a commonjs project causes typescript to complain with

The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("@pgtyped/runtime")' call instead.
  To convert this file to an ECMAScript module, change its file extension to '.mts', or add the field `"type": "module"` to 'XXXX/package.json'.

this is caused by a wrong exports declaration in your package.json. see here and here for details

Expected behavior typescript does not fail

Test case

npm i -D @tsconfig/node20 tsconfig.json:

{
  "extends": "@tsconfig/node20",
}

src/index.ts

import { PreparedQuery } from '@pgtyped/runtime';
benjie commented 4 months ago

I successfully addressed this with the following patch:

diff --git a/lib/index.d.cts b/lib/index.d.cts
new file mode 100644
index 0000000000000000000000000000000000000000..3d9337b5edcde8c7b8a98aa9cd81c6b1a1451542
--- /dev/null
+++ b/lib/index.d.cts
@@ -0,0 +1,4 @@
+export { ParameterTransform, QueryParameters, InterpolatedQuery, QueryParameter, } from './preprocessor.js';
+export { processTSQueryAST } from './preprocessor-ts.js';
+export { processSQLQueryIR } from './preprocessor-sql.js';
+export { sql, TaggedQuery, PreparedQuery } from './tag.js';
diff --git a/package.json b/package.json
index bed91dd3d360132d3e0b18375f4dc7d89cb4a10b..57491d5b4b2e6f5e87016a888a01001b8614a663 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,11 @@
   "type": "module",
   "exports": {
     ".": {
-      "types": "./lib/index.d.ts",
+      "types": {
+        "import": "./lib/index.d.ts",
+        "require": "./lib/index.d.cts",
+        "default": "./lib/index.d.ts"
+      },
       "import": "./lib/index.js",
       "require": "./lib/index.cjs",
       "default": "./lib/index.js"

You can read about the reasoning behind this change here:

https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/FalseESM.md

But essentially when ran under moduleResolution: "node16", TypeScript needs the .d.ts / .d.mts / .d.cts extension to match with the file that's being imported. Even though the content of the index.d.cts file that I have added is identical to that of the existing index.d.ts file, TypeScript in this mode will get upset if the extensions don't match.