Skip to content

Commit

Permalink
move to ts, refactor, dont delete user overrides (#5)
Browse files Browse the repository at this point in the history
Co-authored-by: Arun George <[email protected]>
  • Loading branch information
aruniverse and aruniverse authored Sep 7, 2022
1 parent c6d374b commit ca4a498
Show file tree
Hide file tree
Showing 9 changed files with 359 additions and 50 deletions.
17 changes: 15 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,24 @@ jobs:
run:
working-directory: ./cli
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: actions/checkout@v3
with:
fetch-depth: 2

- uses: actions/setup-node@v3
with:
node-version: 16
registry-url: https://registry.npmjs.org/

- uses: pnpm/[email protected]
name: Install pnpm
id: pnpm-install
with:
version: 7
run_install: true

- run: pnpm build

- run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ node_modules/
.pnpm-debug.log

test/
docs/
docs/

index.js
60 changes: 60 additions & 0 deletions cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# CoSpace

## 0.5.0

- Converted to TypeScript
- `override` command will not delete manual user defined overrides

## 0.4.5

### Fix

- Create `pnpm.overrides` if it doesn't exist; happens if user deletes it from their CoSpace or if they didn't use the template

## 0.4.4

### Fix

- Remove pnpm options from template that were never applied

## 0.4.3

### Enhancement

- `override` command now provides a diff of `pnpm.overrides`

## 0.4.2

- miscellaneous updates

## 0.4.1

- Change dep on lage from `latest` to `^1.5.1`; reacting to change made in [microsoft/lage@a83120f](https://github.com/microsoft/lage/commit/a83120f54edad9526205765c7006d240772ef798)

## 0.4.0

### Breaking Change

- Change package name from `create-cospace` to `cospace`

## 0.3.0

### Enhancement

- Added `purge` command to delete all `node_modules` in the `cospace`

## 0.2.1

### Fix

- Pass dir arg to `init` command

## 0.2.0

### Enhancement

- Add `override` command to automatically update the `pnpm.overrides` section of the CoSpace's package.json, to ignore semver and always use the local package version, `"workspace:*"`, from the workspace.

## 0.1.0

- Initial release
112 changes: 67 additions & 45 deletions cli/index.js → cli/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
#!/usr/bin/env node

import { fileURLToPath } from "url";
import path from "path";
import { execSync } from "node:child_process";
import path from "node:path";
import { fileURLToPath } from "node:url";
import fs from "fs-extra";
import meow from "meow";
import { execSync } from "child_process";

const Commands = {
INIT: "init",
OVERRIDE: "override",
PURGE: "purge",
};
// since __filename and __dirname are undefined for esm, define ourselves
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const PACKAGE_JSON = "package.json";
const WORKSPACE_VERSION = "workspace:*";

interface PnpmPackageInfo {
name: string;
version: string;
private: boolean;
path: string;
}

const enum Commands {
INIT = "init",
OVERRIDE = "override",
PURGE = "purge",
}

const help = `
Usage:
Expand All @@ -27,14 +41,16 @@ const help = `
Flags:
--help, -h Show this help message
--version, -v Show the version of this script
--includePrivate Add private packages to CoSpace's pnpm overrides
`;

const checkPnpmInstalled = () => {
try {
execSync("pnpm -v", { stdio: "ignore" });
} catch (e) {
} catch {
console.error(
"Please install pnpm using 'npm install -g pnpm' before using this script"
"Please install pnpm before using CoSpace, see https://pnpm.io/installation"
);
process.exit(1);
}
Expand All @@ -53,16 +69,13 @@ const init = async (cospaceDir = ".") => {
}
}

console.log(`\nCreating cospace in ${cospaceDir}...`);

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
console.log(`\nCreating CoSpace in ${cospaceDir}...`);
await fs.copy(path.join(__dirname, "./template"), cospaceDir);

process.chdir(cospaceDir);
await fs.mkdir("repos");
try {
execSync("pnpm i");
} catch (e) {
} catch {
console.error("Failed to install, please run install prior to CoSpace use");
}

Expand All @@ -71,41 +84,52 @@ const init = async (cospaceDir = ".") => {
);
};

const overridePnpm = async () => {
const pkgJsonPath = "package.json";

const overrides = JSON.parse(
const getWorkspacePkgs = (): PnpmPackageInfo[] => {
return JSON.parse(
execSync("pnpm ls -r --depth -1 --json", {
encoding: "utf8",
})
)
);
};

const overridePnpm = async (includePrivate: boolean) => {
const pkgJsonData = await fs.readJSON(PACKAGE_JSON);
if (!pkgJsonData.pnpm) {
pkgJsonData.pnpm = {};
}
const currentOverrides = pkgJsonData?.pnpm?.overrides ?? {};

const cospaceOverrides = getWorkspacePkgs()
.map((pkg) => {
if (!pkg.private) return pkg.name;
return !pkg.private || (includePrivate && pkg.private) ? pkg.name : "";
})
.filter((name) => name)
.sort()
.reduce((overrides, name) => {
overrides[name] = "workspace:*";
.reduce((overrides: { [pkgName: string]: string }, name: string) => {
overrides[name] = WORKSPACE_VERSION;
return overrides;
}, {});

const pkgJsonData = await fs.readJSON(pkgJsonPath);
const prev = Object.keys(pkgJsonData?.pnpm?.overrides ?? {});
const next = Object.keys(overrides);
const userOverrides = Object.fromEntries(
Object.entries(currentOverrides).filter(([_pkgName, version]) => {
return version !== WORKSPACE_VERSION;
})
);

if (!pkgJsonData.pnpm) {
pkgJsonData.pnpm = {};
}
const overrides = { ...cospaceOverrides, ...userOverrides };

pkgJsonData.pnpm.overrides = overrides;
await fs.writeJSON(pkgJsonPath, pkgJsonData, { spaces: 2 });
await fs.writeJSON(PACKAGE_JSON, pkgJsonData, { spaces: 2 });

console.log(
"Your CoSpace's workspace links have been overriden. Run `pnpm install`, `pnpm build` and you're good to go!"
);

const removed = prev.filter((name) => !next.includes(name));
const added = next.filter((name) => !prev.includes(name));
const cur = Object.keys(currentOverrides);
const next = Object.keys(overrides);

const removed = cur.filter((name) => !next.includes(name));
const added = next.filter((name) => !cur.includes(name));

if (removed.length) {
console.log(
Expand All @@ -124,15 +148,9 @@ const overridePnpm = async () => {
};

const purge = async () => {
const paths = JSON.parse(
execSync("pnpm ls -r --depth -1 --json", {
encoding: "utf8",
})
).map((pkg) => pkg.path);

await Promise.all(
paths.map((p) => {
const nodeModulesPath = path.join(p, "node_modules");
getWorkspacePkgs().map((pkg) => {
const nodeModulesPath = path.join(pkg.path, "node_modules");
console.log(`Purging ${nodeModulesPath}`);
return fs.remove(nodeModulesPath);
})
Expand All @@ -144,9 +162,11 @@ const purge = async () => {
const run = async () => {
const { input, flags, showHelp, showVersion } = meow(help, {
importMeta: import.meta,
allowUnknownFlags: false,
flags: {
help: { type: "boolean", default: false, alias: "h" },
version: { type: "boolean", default: false, alias: "v" },
includePrivate: { type: "boolean", default: false },
},
});

Expand All @@ -155,16 +175,18 @@ const run = async () => {

checkPnpmInstalled();

switch (input[0]) {
const [command, ...args] = input;

switch (command) {
case Commands.INIT:
return await init(input[1]);
return await init(args[0]);
case Commands.OVERRIDE:
return await overridePnpm();
return await overridePnpm(flags.includePrivate);
case Commands.PURGE:
return await purge();
default:
console.error(
`Unrecognized command, "${input[0]}", please try again with --help for more info.`
`Unrecognized command, "${command}", please try again with --help for more info.`
);
}
};
Expand Down
12 changes: 11 additions & 1 deletion cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cospace",
"version": "0.4.5",
"version": "0.5.0",
"description": "Setup a `CoSpace` to link multiple (mono)repos together!",
"author": "https://github.com/aruniverse",
"homepage": "https://aruniverse.github.io/cospace/",
Expand All @@ -13,6 +13,10 @@
"bin": {
"cospace": "index.js"
},
"scripts": {
"build": "tsc",
"clean": "rimraf index.js"
},
"files": [
"index.js",
"template"
Expand All @@ -30,5 +34,11 @@
"dependencies": {
"fs-extra": "^10.0.0",
"meow": "^10.0.0"
},
"devDependencies": {
"@types/fs-extra": "9.0.13",
"@types/node": "^16.0.0",
"rimraf": "^3.0.2",
"typescript": "^4.8.2"
}
}
6 changes: 5 additions & 1 deletion cli/template/lage.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
/** @type {import("lage").ConfigOptions } */
module.exports = {
pipeline: {
build: ["^build"],
test: ["build"],
lint: [],
clean: [],
clean: {
cache: false,
},
},
cache: true,
};
Empty file removed cli/template/repos/.empty
Empty file.
Loading

0 comments on commit ca4a498

Please sign in to comment.