Entering open-source software
Tags: npm, git, opensource, javascript
Published: 2020-02-20 08:25:38

![open source software](https://live.staticflickr.com/65535/49560128901_cffa232f26_b.jpg)
######Credit: Getty

I've built free web-apps fulfilling various practical purposes (mostly silly) for quite some time, but it wasn't until fairly recently (~1 yr) that I started getting into open-source software (OSS). It has opened my mind to a whole new world and has had an enormous impact on my general understanding of JavaScript and its ecosystem. This extension of knowledge was partly thanks to contributing to open-source projects but even more so by simply reading a lot more source code written by other developers. The realization that all source code is written by mere mortals, and that it doesn’t bite, caused the threshold for deep diving into libraries whenever issues arose to be significantly lowered.

# Learnings
My OSS journey hasn’t been without bumps in the road. But where there’s bumps, there’s learnings.

## Git & npm: The Confusing Parts

### npm tags

Git and npm has a lot of overlapping terminology which can be confusing at first. When starting out with developing my own projects I had a lot of assumptions as to how the two platforms interacted. For example, a misconception I had early on was that npm would interpret my libraries' versions and make contextual decisions, such as "marking" a release published as `0.0.1-alpha.0` as an *alpha-release* rather than a *latest-release*. However, even though `0.0.1-alpha.0` is completely [valid](https://semver.org/#spec-item-9) semver, npm requires that one explicitly [tag](https://docs.npmjs.com/cli/publish#description) releases: `npm publish --tag alpha`. 

A npm tag can be pretty much anything [*except*](https://docs.npmjs.com/cli/dist-tag#caveats) for something resembling semver. For example,`npm publish --tag ihavenoideawhatimdoing` is completely valid:
![npm tags](https://live.staticflickr.com/65535/49490741663_b9ca622363_o.png)

### git tags
We just learned what a tag is in npm's world. What about Git?

A [tag in Git](https://git-scm.com/book/en/v2/Git-Basics-Tagging) is essentially a snapshot of a repository at a particular time in its history. Dealing with Git tags is fairly straightforward. The weirdest part is that the tag's name can be literally anything and doesn't have to conform to semver. Developers commonly use tags to help mark releases and thus, for sanity's sake, use their library's version as a Git tag (prefixed by `v` of course 🤷🏼‍♂️):

```sh
# Create tag
git tag v0.0.1

# Push to repo (will turn up as a commit)
git push --tags
```

## TypeScript
Building your library in TypeScript?

![typescript is supereasy](https://media1.tenor.com/images/ef005366f35f143e799a2bf05739c352/tenor.gif?itemid=13356160)

### Expose your type declarations
There's a [ton](https://www.typescriptlang.org/docs/handbook/compiler-options.html) of options for compiling TypeScript projects. However, there's one in particular that'll make whoever depends on your library super happy 🐼:

```json
{
	"compilerOptions": {
		"declaration": true
	}
}
```

This'll generate declaration files (`file.d.ts`) next to each JavaScript file outputted from the compilation that'll be exposed to your users when they import your library.

### Fighting your IDE 👨🏼‍💻🥊
*The relevance of this particular tip may vary depending on your [IDE](https://en.wikipedia.org/wiki/Integrated_development_environment).*

There's a wide variety of IDE's out there, from those that give absolutely zero support whatsoever to those that borderline autocompletes your thoughts. My current IDE of choice, [VS Code](https://code.visualstudio.com/), is somewhere in the middle of this range. It is equipped with a bunch of debugging tools and a solid selection of extensions, improving developer experience via customizability. In a perfect world a developer wouldn't have to run e.g. ESLint's CLI but would solely rely on an extension that'd guarantee the same experience.

When developing TypeScript your IDE relies on your `tsconfig.json` to validate your code and highlight type errors. This behavior, as intended as it may be, causes some level of cumbersomeness when publishing your library to e.g. npm.

**Why?**

Well, *hopefully*, your project is blessed with at least *one* unit test. Ideally, tests shouldn't turn up in the distribution code, i.e. the *dist*, just as development dependencies shouldn't turn up in production. However, using `exclude` in your tsconfig makes VS Code a sad 🐼 and you'll see the errors such as:
 > Cannot find name 'describe'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`.
>
>![Sad VS Code](https://live.staticflickr.com/65535/49435983712_b5ebae248c_o.png)

I haven't found any better workaround than to include all TypeScript files in my `tsconfig.json` and create a separate `tsconfig.publish.json` that'll be used when publishing to npm. This setup makes VS code happier...

![Happy VS Code](https://live.staticflickr.com/65535/49435761671_90121b77a0_o_d.png)

...but forces developers to remember yet another detail before publishing: compile the dist using `yarn tsc --project tsconfig.publish.json` instead of simply `yarn tsc`.

## Pipeline - automate automate automate
A colleague of mine who's an OSS wizard once recommended me to automate as much as I possibly could for my projects. Not being a huge fan of pipelines and such, I kindly nodded and postponed the advice as long as possible.

However, my patience finally got the best of me. I learned the hard way that a bunch of manual steps easily led to mistakes and ultimately frustration. Lucky for me, [GitHub Actions](https://github.com/actions) had just been released and it matched my level of interest in DevOps. With it, I could fairly painlessly create [workflows](https://github.com/erikengervall/dockest/blob/master/.github/workflows/nodejs.yml) that would automate everything I needed in order to publish libraries. 

What kind of steps does this entail? Well, here's roughly the flow of my pipeline:

- **Linting**: Running e.g. ESLint is a great way to discover problems without having to run any code.
- **Tests**: Just like the responsible developers that we are, there's plenty of tests validating that our code can do stuff, even better if it does what it's supposed to. Extra points for integration tests ⨑

Since we only wish to publish to npm on version bumps, the following steps only execute on [git refs](https://developer.github.com/v3/git/refs/) starting with `refs/tags/`

- **Publish library**: Install dependencies, build the dist and publish to npm. This step also attaches necessary npm tags, for example `v0.0.1-alpha.0` results in `npm publish --tag alpha`.
- **Build and deploy website**: Creating a website for your library's documentation is pretty sweet once the README starts occupying a few viewports. I recommend [Docusaurus](https://docusaurus.io/) since it's easy to use and deploy.

# Conclusion
This article was intended to outline some of the challenges I've encountered during my adventures on GitHub, I hope it inspires more than it frightens 🙌🏼

If there's interest I'd be happy to share more on this topic!