Keep Your Monorepo Clean in VS Code with a Workspace Checkout Script
Tags: monorepo, vscode, workspaces, tutorial
Published: 2024-06-07 18:35:09

**Monorepos** can be both a blessing and a curse. They offer a centralized codebase, but managing a large number of applications simultaneously in a Code Editor can quickly become overwhelming. The default behavior of any Code Editor, where all files and folders are visible in the explorer, makes searching for files a cluttered experience and makes the workspace messy.

In **VS Code** To address this issue and maintain a clean workspace, you can leverage the `.vscode/settings.json` file. By configuring the `files.exclude` property, you can hide specific files or folders from the file explorer. For example:

```javascript
// .vscode/settings.json
{
  "files.exclude": {
    "apps/server": true
  }
}
```

This will hide the `server` app from the VS Code explorer without deleting it from the filesystem. However, manually updating this setting can be tedious. To streamline the process, Lets create a `Node.js` script that dynamically updates the `files.exclude` settings based on your current needs.

## Introducing the Workspace Checkout Script

With this script and the [enquirer](https://www.npmjs.com/package/enquirer) npm package, you can create a simple command-line interface (CLI) to toggle the visibility of applications in your monorepo. Here’s how you can set it up:

#### 1. install `enquirer`:
```javascript
 npm i enquirer
```  
#### 2. Create the script:
Save the following script as `scripts/workspace-checkout.js` in your project.

```javascript

import { fileURLToPath } from 'url';
import path, { dirname } from 'path';
import fs, { readdirSync } from 'fs';
import enquirer from 'enquirer';

// Get the current file's directory
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// Destructure AutoComplete from enquirer
const { AutoComplete } = enquirer;

// Define paths for the VS Code settings file and the apps directory
const relativeFilePath = '../.vscode/settings.json';
const absoluteFilePath = path.join(__dirname, relativeFilePath);
const appsPath = path.join(__dirname, '../apps');

// List of apps to always exclude
const excludedApps = [];

// Read the VS Code settings file
fs.readFile(absoluteFilePath, 'utf8', async (err, data) => {
  if (err) {
    console.error('Error reading file:', err);
    return;
  }

  let jsonData;
  try {
    // Parse the JSON data from the settings file
    jsonData = JSON.parse(data);
  } catch (parseError) {
    console.error('Error parsing JSON:', parseError);
    return;
  }

  // Determine initially selected apps based on settings
  const initial = Object.keys(jsonData['files.exclude'])
    .filter(app => !jsonData['files.exclude'][app])
    .map(app => app.split('/')[1]);

  // Read the apps directory and filter out excluded apps
  const apps = readdirSync(appsPath, { withFileTypes: true })
    .filter(direct => {
      return direct.isDirectory() && !excludedApps.includes(direct.name);
    })
    .map(direct => direct.name);

  // Create a prompt for selecting apps to display
  const prompt = new AutoComplete({
    name: 'apps',
    message:
      'Press arrow keys to navigate and space to select/deselect apps. Press enter to confirm.',
    multiple: true,
    choices: [...apps],
    initial: initial.filter(app => !excludedApps.includes(app))
  });

  // Get the user's selection
  const answer = await prompt.run();

  // Update the VS Code settings based on the user's selection
  apps.forEach(app => {
    jsonData['files.exclude'][`apps/${app}`] = !answer.includes(app);
  });

  const updatedJsonData = JSON.stringify(jsonData, null, 2);

  // Write the updated settings back to the file
  fs.writeFile(absoluteFilePath, updatedJsonData, 'utf8', writeErr => {
    if (writeErr) {
      console.error('Error writing to file:', writeErr);
      return;
    }
    console.log('Checkout successful.');
  });
});


```
#### 3.Update your `package.json`:
Add a script entry to your `package.json` to run the checkout script.

```javascript
"scripts": {
  // Others script
  "checkout": "node scripts/workspace-checkout.js"
}

```
#### 4.Run the script:
Open your terminal and type the following command to run the script:

```javascript
npm run checkout
```
This command will present a list of all available apps with a checkmark. Use the spacebar to toggle the selection and press enter to confirm. Only the selected apps will be visible in the VS Code file manager. This keeps your workspace clean and focused on the apps you are currently working on, while still keeping all files intact on the filesystem.

## Conclusion
Using a monorepo can significantly enhance collaboration and code management across multiple applications. However, it's essential to keep your development environment organized. By leveraging the .vscode/settings.json file and automating the process with a Node.js script, you can efficiently manage which apps are visible in your VS Code explorer. This approach keeps your workspace clean, enhances productivity, and reduces clutter.

Try setting up this script in your monorepo and enjoy a more streamlined development experience!

And if you have a better approach, please share your insights in the comments. I'm always looking for new and improved ways to manage my development environments effectively.