# esteem Make your [NX](https://nx.dev/) workspaces go easier on your disk. - [esteem](#esteem) - [Why?](#why) - [How does it work?](#how-does-it-work) - [Installation](#installation) - [Miscellaneous](#miscellaneous) - [Project scopes](#project-scopes) - [Requirement scopes](#requirement-scopes) - [Usage](#usage) - [`init`](#init) - [`add`](#add) - [`workspace add`](#workspace-add) - [`remove`](#remove) - [`workspace remove`](#workspace-remove) - [`install-isolated`](#install-isolated) - [Some caveats](#some-caveats) - [Example](#example) - [Contributing](#contributing) ## Why? This tool exists for a very simple reason - I am a :sparkles: cheapskate :sparkles:. I would rather spend a weekend developing a tool than pay an additional $5 on Digital Ocean to buy some additional storage and calling it a day. I present you with **_esteem_**! NX monorepos totally rock, but where they don't is when you need to deploy your projects and now a simple Next app takes up 2GBs of storage because you also had to install dependencies of all other projects in the monorepo. `esteem` solves this problem by keeping track of each individual project's dependencies while also following NX's single-version policy. ## How does it work? It just keeps track of individual project's dependencies. For existing projects this means a small amount of manual work where you copy the dependencies of a project from `package.json` to its `project.json`. When [`install-isolated`](#install-isolated) is called for a project, it simple collects the dependencies for that package and writes it to the root `package.json`. You can then call your package manager's install command and viola! you have a smaller `node_modules`! ## Installation - Guided installation: ```bash curl https://raw.githubusercontent.com/IgnisDa/developrs/main/apps/esteem/install.sh -o install.sh # Warning: always examine scripts downloaded from the internet before running them locally. bash install.sh ``` - Manual installation: You can also download the appropriate executable from the [releases](https://github.com/IgnisDa/developrs/releases) page. - CI environments: For example in `Dockerfile` ```Dockerfile # This script writes to /usr/local/bin/, you can change this via the `--bin-dir` flag RUN curl https://raw.githubusercontent.com/IgnisDa/developrs/main/apps/esteem/install.sh | sudo sh -s -- --yes ``` ## Miscellaneous Esteem separates dependencies by project scope (`project` or `workspace`) and requirement scope (`required` or `development`). ### Project scopes The project in which a dependency is to be installed. If it is a project dependency, it is well... exactly that: a project dependency. Project dependencies are written to their corresponding `project.json`. A workspace dependency can be treated as a global dependency. They are written to the root `workspace.json`. These dependencies will always be a part of the final `package.json`. ### Requirement scopes Think of `required` and `development` scopes as analogous to `dependencies` and `devDependencies` in npm projects. ## Usage `esteem` has very few commands of its own; most of the heavy lifting is done by your package manager (`npm`, `yarn`, `pnpm` etc). Right now `esteem` is only compatible with NX monorepos (or all projects where there is a root level `workspace.json` and project level configurations in `//project.json`). **_Note_:** You can always run `esteem --help` for more information. ### `init` Prepares new repositories to be used with `esteem`. This will add an object of this structure to all `project.json` files and `workspace.json`. **_Note_:** You don't need to run this command if you don't want to, `esteem` can handle projects without `dependencies` key. ```json { "dependencies": { "development": [], "required": [] } } ``` Now for each `project.json`, you will have to manually add the dependent packages for that project. So if project `server` depends on `nestjs` and `prettier`, you will have to make these changes. Eg: `apps/server/project.json` ```json { "dependencies": { "development": ["prettier"], "required": ["nestjs"] } } ``` [Here](https://github.com/IgnisDa/bookius/blob/main/apps/server/project.json) is a `project.json` from the [example](#example) repository. ### `add` It adds a dependency to a project. Eg: ```bash $ esteem add server redis luxon # your package manager called automatically after making changes to `projects/server/project.json` ``` Pass the `-D` flag to add it a development dependency. #### `workspace add` Same functionality as above but for workspace scoped dependencies. ### `remove` Removes a dependency from a project taking into account whether other projects are dependent on that dependency. ```bash $ esteem remove server luxon typescript bull # your package manager called automatically after making changes to `projects/server/project.json` ``` #### `workspace remove` Same functionality as above but for workspace scoped dependencies. ### `install-isolated` This command collects ALL the dependencies of a project (and its dependent project) and writes to `package.json`. This command is meant to be run only on CI environments because it changes your `package.json` file. It makes a backup of the `package.json` file. It is your job to call your package manager to install the dependencies. ```bash esteem install-isolated server ``` It also accepts multiple parameters and resolves all the dependencies. It uses [NX Graph](https://nx.dev/nx/dep-graph) under the hood to solve the dependency tree. #### Some caveats - The lockfile will **NOT** be in sync with `package.json` because `esteem` does not resolve dependencies. However this should not be a problem since dependencies have only been _removed_ and not _added_ (and they were already resolved in the lockfile). However, this means that `pnpm install --frozen-lockfile` and similar commands **WILL** fail. Just remove that flag and it should work as expected. - If you run the command `esteem install-isolated server`, the following files are expected to be present (with the paths intact): - `package.json` - `pnpm-lock.yaml` (or your package manager's lockfile) - `workspace.json` - `apps/server/project.json` - `libs/config/project.json` (assuming `server` depends on `config`) You can refer to [these lines](https://github.com/IgnisDa/bookius/blob/49713a5d0beb1528d471563faf565cabbbbe4ff5/apps/server/Dockerfile#L4-L5) of the [example](#example) repository to see this in action in a `Dockerfile`. ## Example [Bookius](https://github.com/IgnisDa/bookius) is a project where `esteem` is used in conjunction with Dokku, Github Actions and Docker for deployment. All projects therein are deployed from a single Digital Ocean droplet. You can consult [`Dockerfile`](https://github.com/IgnisDa/bookius/blob/49713a5d0beb1528d471563faf565cabbbbe4ff5/apps/server/Dockerfile#L8) to see it being used in a docker environment. ## Contributing Your PRs and stars are always welcome.