Closed karlhorky closed 3 years ago
Thanks!
Glad to help, thanks for the merge!
This might be obvious to experienced npm users, but it wasn't to me: postinstall
scripts in your project's main package.json don't run after installing specific packages (e.g. npm install lodash
). They only run when you do an unqualified npm install
.
After some research, I found there is no good solution to this. The only way to get something to run after npm install [package]
is to use a hook script, and hook scripts are platform dependent, and a mess to setup.
Good point, sorry about this. I looked around a bit, and it seems this is known behavior of npm
(if unwanted).
Yarn does it correctly (runs postinstall
on every yarn install <pkg>
), so I didn't think that npm
would have such weird, different behvior. I've asked if they are willing to change this: https://github.com/npm/feedback/discussions/217
Since it would be a while before any change, and npm
users are the majority (unfortunately can't just write a guide that works for Yarn), I've opened https://github.com/jeffijoe/typesync/pull/66 with a shell script alternative:
npm run i <pkg>
Even nicer if typesync
could take a package name as an argument:
typesync install <pkg name>
or just:
typesync <pkg name>
and then it would handle the installation, like typac
does. Then there would be no need for a shell script.
karlhorky, I agree with your assessment of the automation scripting. If only everyone could switch to yarn ...
Regarding typesync install <package>
, I would definitely use this feature. Currently I use typedi to install new packages and typesync to download+install types for a pre-dependencies already in package.json. I like to use just one tool, and I prefer typesync! Of course, you can always npm i [package]
followed by typesync
, but you know picky developers are about saving keystrokes and not wanting to have to write their own aliases/wrappers. :]
@mike-clark-8192 that workflow sounds like typesync
is only used once, and typedi
going forward. It sounds like typedi
solves the problem then?
Use-cases for typesync (npm assumed):
typesync
$ npm i
typesync
$ npm i
npm i lodash
$ typesync
$ npm i
The dream of the package.json "postinstall" script was that you could simplify all three of these scenarios (assuming you had added the the postinstall script to your project's package.json ahead of time):
npm i
npm i
npm i lodash
I believe all three work under yarn(? I'm not a yarn guy, haven't tested), but the third case, which offers the most savings, doesn't work under npm because npm doesn't run postinstall after installing a new package. Also, the npm devs have said they never will change this 'quirk' (their term) of postinstall.
If you want to ignore the postinstall idea altogether and mix in the usage of typedi
, you get this scenario, which works OK:
typesync
$ npm i
typesync
$ npm i
typedi lodash
However, I think there was some hope that maybe the typesync maintainers might be interested in implementing everything a lazy njs/npm/ts dev could ever want :):
typesync i
typesync i
typesync i lodash
I might actually look into this myself some day, but I have several weeks of work piled up, so I'll check back in when I free up. Thanks!
If I were to add this, would the install
be carried out by shelling out to npm
or yarn
?
My concern is having to parse arguments like --saveDev
, -D
and others.
If I were to add this, would the
install
be carried out by shelling out tonpm
oryarn
?
Ha! Good catch. I hadn't thought of that. I'm not gonna lie, this will be a little messy to implement, but I think users will love it. I'll type up some notes and reply in a bit.
typesync <i|install> [options] <package> [...packages]
Install package(s) and their external typedefs. If a package does not
have external typedefs available, the packages will still be installed.
This command is equivalent to running (e.g. with npm):
npm install [options] <package> [...packages]
typesync
npm install
Options:
-D, --save-dev install to devDependencies
-P, --save-prod install to dependencies
-O, --save-optional install to optionalDependencies
-m, --manager [npm|yarn] force preferred package manager
typesync <i|install> [options]
Installs and syncs external typedefs for all of your package.json's
dependencies that have external typedefs available.
This command is equivalent to running (e.g. with npm):
typesync
npm install
By default your preferred package manager will be guessed by the the
presence one of the following files:
File Package Manager
yarn.lock yarn
package-lock.json npm
pnpm-lock.yaml pnpm (not yet supported)
If typesync can't guess your package manager, it will exit with an error. You
can resolve this situation by removing unused lock files, or use -m as below:
Options:
-m, --manager [npm|yarn] force preferred package manager
See the cli --help above for info on guessing the user's package manager (and the ability to override the guess).
NPM (and probably yarn) programmatic APIs aren't stable. Their CLI is their stable interface, so child_process.exec is probably the only way to do this that isn't an impossible versioning nightmare. We have to programmatically construct the correct command to issue to the PM, but this is relatively easy.
We must capture stdout and stderr from exec(), then write it back to typesync's stderr + stdout. We don't need to interpret/parse the output because the process exit code (available from exec) will tell us success vs. failure, which is all we need to branch on.
npm
+ install
. NPM allows you put flags anywhere and has typo correction and all sorts of silly unnecessary things. Example valid command, which actually works (and not incorrectly):
npm -D isntall --save-bundle lodash --dry-run
Huh? No thanks.typesync i
is a convenience thing. If a user needs full control over the package manager invocation, they can continue to use the traditional invocation of typesync
, which won't go away.The typed-install (typedi
) project (https://www.npmjs.com/package/typed-install) already implements the most of the "new" code that would be needed for the above. I wonder if the maintainer of that project is interested in merging functionality under the heading of one tool? Or letting typesync borrow some code? Or vice-versa?
typesync is fully functional as it is right now, and maybe the extra bit of convenience added by the above (plus the presence of already-existing complimentary tools) isn't worth complicating the project with. Anyway, it was fun to talk about, so no loss if it isn't a good fit.
Cheers! :)
Thanks for the detailed write-up!
I don't currently have a lot of free time to work on these things, however. And I guess I just don't install new packages often enough for this to bother me. 😅
Also, the npm devs have said they never will change this 'quirk' (their term) of postinstall.
There has been a bit of movement on this point actually - I submitted an npm RFC and the npm maintainers commented that there is a valid use case there and that they want to do something about this (maybe even a new feature with a new name that allows for this workflow).
If I were to add this, would the
install
be carried out by shelling out tonpm
oryarn
?My concern is having to parse arguments like
--saveDev
,-D
and others.this will be a little messy to implement
I think there would be a simple way to do it, if @jeffijoe would be up for it.
Don't worry about all of the arguments - keeping up with the package managers is not going to be a good time.
Just pass all of them over to the package manager and let it handle them (the user should know which arguments they can use and how). One possible exception - a --yarn
flag (see below).
So eg.
typesync install --save-dev styled-components
would just get translated to:
npm install --save-dev styled-components @types/styled-components
Or, if they use Yarn:
typesync install --yarn --dev styled-components
would just get translated to:
yarn add --dev styled-components @types/styled-components
One special feature (but also pretty simple to implement) would be to install @types/
packages to devDependencies
by default, so that this command:
typesync install styled-components
becomes:
npm install styled-components
npm install --save-dev styled-components
@karlhorky it sounds like jeffijoe has enough work on his plate without having to worry about integrating with package mangers via exec(). Entirely from an end-user's perspective, I feel the feature is a natural fit for what some end-users want to get out of typesync. However, from a technical perspective, the package-manager integration "subsystem" is an entirely different beast from typesync's core functionality -- which is syncing types in the package descriptor.
I think I might try to prototype a meta-module that integrates the functionality of typesync and typedi into a single seamless CLI interface. I'll invite you to the repo when I set it up!
Closes #63