3

I have a module which exposes a bin in package.json which points to a TypeScript file. The .ts file has a ts-node shebang and is executable and works well.

However, when trying to use this binary from another package, I get errors:

  • Using npm i -g to install globally, when the binary is called which in turn calls ts-node I get errors for all the missing types declared in devDependencies of the module containing the binary, since devDependencies aren't installed when installing the module from another module. I have to manually install all the devDependencies such as `npm i -g @types/lodash" which makes no sense to do.

  • Using npx causes module related errors since I'm trying to use import syntax etc from a stand-alone ts-node call:

    (node:67861) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
    (Use `node --trace-warnings ...` to show where the warning was created)
    
    SyntaxError: Cannot use import statement outside a module

Is there any way to build a module which exposes a binary which is a wrapper around a ts-node script, and where that binary is actually executable through npm i -g or npx?

JHH
  • 8,567
  • 8
  • 47
  • 91
  • 2
    If you intend for it to be run _as TypeScript_ then the types referenced in the implementation (although not in e.g. tests) _aren't_ dev dependencies - they're needed at runtime. Why not distribute the transpiled output? – jonrsharpe Mar 02 '22 at 16:44
  • What doesnt make Sense Is the fact that you didnot compile yow code before uploading It to npm. If you compile yow package AND publish them js files instead none of this Will be happening. I mean Is a comment – Ernesto Mar 02 '22 at 16:46
  • You're both right; if this was a normal library obviously I would transpile and publish the `dist` folder as usual. However, this was an internal project not published at all, and not intended to be a library. It's a backend component that also contains some tools, and I attempted to have other team members use those tools by installing that project globally via the `npm i -g git+ssh://github.com/foo/bar.git#some-branch` syntax. – JHH Mar 11 '22 at 12:29
  • I realize I should've been clearer about this, because I do know how to properly publish TypeScript libraries and use them from other libraries - or as globals - but in this case it didn't really make sense to transpile the TS tools in the git just to enable them being used through the `npm i -g git+ssh` syntax. – JHH Mar 11 '22 at 12:29

1 Answers1

0

Move the "missing" package references into "dependencies".

NPM says that "devDependencies" is for "Packages that are only needed for local development and testing" while "dependencies" is for "Packages required by your application in production". So what is "production"? In the case of modules like this, "production" means use in other packages!

In other words, since the type-only packages are still truly required for use by a consumer, they don't belong in "devDependencies" but in "dependencies". This wouldn't be the case if you were pre-compiling into plain JS, but since you're not, the type packages simply need to be there in "production".

Note that this won't necessarily increase your ultimate bundle size in e.g. a web app. If your consumer package lists your tool package in "devDependencies", then ultimately the types packages will not be considered necessary for "production" for the consumer package.

TheRubberDuck
  • 368
  • 4
  • 12