How to "publish" a private Typescript npm package in git?
Asked Answered
H

3

12

I think this should be a standard problem but I can't find any answers...

I have two typescript projects - LibraryA and WebserverB. They are separate projects and each have their own git repository. They are also private projects - I don't want them to be available in public.

Obviously, I want to use LibraryA in WebserverB. The correct way to do it I think would be through npm, since it manages all other libraries. Luckily npm supports git URLs in dependencies, so I can point it to LibraryA's repository directly.

However that repository doesn't contain the compiled Javascript files, only the TypeScript files. How can I make this work? Or what is the correct approach in this situation?

Halyard answered 5/3, 2019 at 12:26 Comment(2)
Hey if you tried the publish package on github, how did you add it as a dependency in the other typescript project? I have figured how to publish a ts package on github but dont know how can I download it in my project as a dependency instead of me running a command manually to download and compile it.Alsatian
@Alsatian Hmm... check this out, I think it does what you need: docs.npmjs.com/cli/v10/configuring-npm/…Halyard
H
7

OK, I'll answer my own question with a summary of the other answers and some extra options.

After some thought I came to a realization. The question is - who and when runs tsc to compile the LibraryA's Typescript to Javascript? Essentially there are just a few choices:

  1. The developer of LibraryA runs it and publishes the compiled result (somewhere);
  2. LibraryA is published in source form and compilation happens when installing the package to WebserverB;
  3. LibraryA is published in source form and building WebserverB also compiles the library.

Let's look at each in detail.

1. Publish compiled result

The question then is - where is the published result stored? It has to be somewhere where NPM can access it. As such, there are only a few choices again:

  • npm registry (private, if you can afford it, public if you're OK with it). Drawback: well, you have to pay for it.
  • A tarball on some server where you can get a URL to it. Drawback: You have to get a server to host these. And take care of said server.
  • A new GIT repository. Not tarballed, because npm cannot untar from a git repository. Drawback: you now have two repositories for one project.
  • The same git repository where LibraryA lives. In essence, you not only commit your TypeScript source files, but also the compiled result. Drawback: committing compilation artifacts is just wrong. And you're publishing your sources together with the compiled results. You don't need those in WebserverB.
  • The same git repository where LibraryA lives, but in a separate, disconnected branch. Drawback: This gets confusing. How many repositories have you seen with two disconnected main branches?

Still, despite the drawbacks, they're all serviceable options.

2. Compile upon install

The main drawback here is that this immediately puts a dependency on typescript on WebserverB. And not just a development-dependency but a full runtime dependency. This may be OK, but it's getting really weird. How do you plan on deploying WebserverB? Will that too run the compilation? I don't think this is the way to go. But it's possible. See H.B.'s answer for details.

3. Compile together with WebserverB

Well, if you plan only on using it in typescript projects, this might be OK. I'm not sure about installing it though. You'll need to modify your tsconfig.json file to include node_modules/LibraryA in the compilation. That's weird. And will your IDE be happy about this? All in all, this doesn't feel like a good idea either. It feels like fighting/abusing the system and that rarely ends well.

In the end, I think I'll go with the "commit compiled JS" approach. Because "just wrong" isn't a good argument. And since it's a private project, the extra published sources aren't much of an issue either. In fact, maybe they'll even help to debug.

Halyard answered 5/3, 2019 at 14:11 Comment(0)
C
3

If you don't want to install your dependency from the sources in a git repository, here are other solutions:

Solution #1 — Install the dependency from a local folder

A light solution is to install LibraryA via a git clone and to build it. Then, in WebserverB/, you can do a npm install ../path/to/local/LibraryA:

  • npm install <folder>:

Install the package in the directory as a symlink in the current project. Its dependencies will be installed before it’s linked. If <folder> sits inside the root of your project, its dependencies may be hoisted to the toplevel node_modules as they would for other types of dependencies. (Source: NPM documentation)

Solution #2 — Install a private npm proxy registry

You can install a private npm proxy registry on your server, like Verdaccio. Then, you'll be able to publish your package with all compiled files.

Solution #3 — Pay NPM and publish a private package

You could publish a true package (also with the compiled files) in a private repository from a paid account.

Solution #4 — Publish as a release on your GitHub repository (not tested)

The NPM documentation indicates another option:

  • npm install <tarball url>

Fetch the tarball url, and then install it. In order to distinguish between this and other options, the argument must start with “http://” or “https://”

Then, publish a package consist to build, compress and upload it as a new release in your private Github repository. After that, it should be possible to access the tarball through an URL using a personal access token?

Cutinize answered 5/3, 2019 at 13:16 Comment(7)
Wait, wait, wait. I want to install my dependency from a git repository. I just can't figure out how to do it properly.Halyard
@Halyard I've just had an idea. I edited my answer to add it as solution 4.Cutinize
I don't think you can point npm to a single tarball in a GIT repository. It doesn't spell it out directly but it's kinda implied from the install documentation. You can however use a plain URL to the tarball. Or, if you're already invoking a separate GIT repository, why not make a repository that contains just the built package? No need to tarball anything. However this is already getting weird, so a simpler approach is to just commit the built JS files in your original source repository and use that.Halyard
This has the side effect of distributing the source code along with the compiled JS result, but we're talking about private packages anyway so that shouldn't be an issue. Even better, it could help with debugging.Halyard
@Halyard Or maybe a tarball uploaded in a release of your Github repo? (I edited the solution 4)Cutinize
Well, if you're using GitHub, sure. But I was talking about private packages that you don't want to show to the world. I guess Github also has private repositories though. I wonder if you can create a URL to them that contains a username/password embedded in it?Halyard
@Halyard Maybe with a personal access token. Here is an example of URL using a token but I didn't test that.Cutinize
E
1

I guess you could add an install script in the library's package.json that compiles it. Then you just need to point main and types to the output files.

Europium answered 5/3, 2019 at 12:32 Comment(2)
Hmm.. that's one way, but that then brings TypeScript out from Dev Dependencies and into full DepencenciesHalyard
True, there might be other solutions though.Europium

© 2022 - 2024 — McMap. All rights reserved.