0x80 / isolate-package

Isolate a monorepo package with its internal dependencies to form a self-contained directory with a pruned lockfile
MIT License
121 stars 13 forks source link

There are types at 'isolate-package/dist/index.d.ts', but this result could not be resolved when respecting package.json "exports". #58

Closed matbour closed 6 months ago

matbour commented 7 months ago

In order to solve problem described in #56, I built a script to handle my isolation process. However, TypeScript refuses to import the isolate-package types.

Here is the full error:

Could not find a declaration file for module 'isolate-package'. '[workspace]/node_modules/.pnpm/isolate-package@1.10.1/node_modules/isolate-package/dist/index.mjs' implicitly has an 'any' type.
  There are types at [workspace]/apps/api/node_modules/isolate-package/dist/index.d.ts', but this result could not be resolved when respecting package.json "exports". The 'isolate-package' library may need to update its package.json or typings.ts(7016)

I am using isolate-package v1.10.1.

The script: ```ts import { execSync } from 'node:child_process'; import { readFile, writeFile } from 'node:fs/promises'; import { isolate } from 'isolate-package'; import { rimraf } from 'rimraf'; import { build as tsup } from 'tsup'; import tsupConfig from '../tsup.config'; const isolateDirName = 'isolate'; await rimraf(['dist', isolateDirName]); await tsup(tsupConfig); await isolate({ isolateDirName, }); // Copy the overrides from the root workspace to the isolate workspace const rootPackageJson = JSON.parse(await readFile('../../package.json', 'utf-8')); const isolatePackageJson = JSON.parse(await readFile('package.json', 'utf-8')); isolatePackageJson.pnpm = { ...isolatePackageJson.pnpm, overrides: rootPackageJson.pnpm.overrides }; await writeFile('isolate/package.json', JSON.stringify(isolatePackageJson, null, 2)); execSync('pnpm install --lockfile-only', { cwd: isolateDirName, stdio: 'inherit' }); execSync('zip -r ../dist/function.zip ./*', { cwd: isolateDirName, stdio: 'inherit' }); await rimraf([isolateDirName]); ```
My tsconfig.json: ```json { "extends": "@tsconfig/strictest/tsconfig.json", "compilerOptions": { "outDir": "dist", "strict": true, "allowJs": false, "checkJs": false, "noEmit": true, "allowImportingTsExtensions": true, "forceConsistentCasingInFileNames": true, "verbatimModuleSyntax": true, "esModuleInterop": true, "resolveJsonModule": true, "isolatedModules": true, "allowSyntheticDefaultImports": true, "exactOptionalPropertyTypes": false, "target": "ES2022", "module": "ESNext", "moduleResolution": "Bundler", "paths": { "@/*": ["./src/*"] } }, "include": ["**/*.ts"], "exclude": ["node_modules"] } ```

The fix is fairly easy: add explicit types to the package.json exports:

   "type": "module",
   "types": "./dist/index.d.ts",
   "exports": {
-    ".": "./dist/index.mjs"
+    ".": {
+      "import": "./dist/index.mjs",
+      "types": "./dist/index.d.ts"
+    }
   },
   "files": [
     "dist",

Happy to submit a PR.

0x80 commented 7 months ago

Thanks for reporting. I wasn't aware that exports.types was still needed when types is already defined in the root. I will change it soon, and if you like you can also submit a PR.

Do you happen to have a link to some documentation where this requirement is described?

0x80 commented 7 months ago

I don't see how this would be related to #56, since that is a runtime error. Can you elaborate on that?

--- edit --- Ah I think I understand. You wrote your script to get around the problem of #56 so it's not directly related.

0x80 commented 6 months ago

@mathieu-bour what is your setting for "moduleResolution" in Typescript? I'm trying to figure out why you are having trouble with the types, because my applications don't have this problem.

This an ESM-only package so we shouldn't have to specify what exports are meant for "import" I think, and AFAIK the types field in the root should be picked up by Typescript.

But it might have something to do with the mjs extension, which isn't the default if you use type: module, but it's a workaround I had to use.

matbour commented 6 months ago

@0x80 my moduleResolution is Bundler. fyi I added the full tsconfig in the first issue.

0x80 commented 6 months ago

@mathieu-bour Sorry I missed them because they were collapsed. Neat way to format a longer issue though 👌

0x80 commented 6 months ago

@mathieu-bour I had to change it to something else because your proposal broke the integration in firebase-tools-with-isolate. In the latest version I just do exports: "./dist/index.mjs". I hope this works for you, and seems to be the correct way for pure ESM packages.

If it doesn't work, please tell me more about how you're executing your script.

0x80 commented 6 months ago

@mathieu-bour did you mean to link #55 instead #56? Seems like that's where the confusion came from.