Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Create package",
"packageName": "@ws-tools/paths",
"email": "elcraig@microsoft.com",
"dependentChangeType": "patch"
}
11 changes: 11 additions & 0 deletions change/change-f2f87433-eff5-442f-aee9-504082645db4.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"type": "none",
"comment": "Update tsc command format",
"packageName": "@ws-tools/grapher",
"email": "elcraig@microsoft.com",
"dependentChangeType": "none"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Move path utilities to separate package (re-exported by this one)",
"packageName": "workspace-tools",
"email": "elcraig@microsoft.com",
"dependentChangeType": "patch"
}
2 changes: 1 addition & 1 deletion packages/grapher/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"lib/!(__*)/**/*"
],
"scripts": {
"build": "tsc",
"build": "tsc --pretty",
"start": "tsc -w --preserveWatchOutput",
"test": "jest"
},
Expand Down
5 changes: 5 additions & 0 deletions packages/paths/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# @ws-tools/paths

Helper methods related to paths in a repo or monorepo. The methods in this package are re-exported from [`workspace-tools`](https://www.npmjs.com/package/workspace-tools) for convenience.

This package should contain only the most basic helpers with no or minimal dependencies.
18 changes: 18 additions & 0 deletions packages/paths/etc/paths.api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## API Report File for "@ws-tools/paths"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```ts

// @public
export function findGitRoot(cwd: string): string;

// @public
export function findPackageRoot(cwd: string): string | undefined;

// @public
export function searchUp(filePath: string | string[], cwd: string): string | undefined;

// (No @packageDocumentation comment for this package)

```
1 change: 1 addition & 0 deletions packages/paths/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require("@ws-tools/scripts/jest/jest.config");
31 changes: 31 additions & 0 deletions packages/paths/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "@ws-tools/paths",
"version": "0.1.0",
"license": "MIT",
"description": "Helper methods related to paths in a repo or monorepo",
"repository": {
"type": "git",
"url": "https://github.com/microsoft/workspace-tools"
},
"main": "lib/index.js",
"types": "lib/index.d.ts",
"exports": {
".": {
"require": "./lib/index.js",
"types": "./lib/index.d.ts"
}
},
"files": [
"lib/!(__*)",
"lib/!(__*)/**"
],
"scripts": {
"api": "ws-tools-scripts api",
"build": "tsc --pretty",
"start": "tsc -w --preserveWatchOutput",
"test": "jest"
},
"devDependencies": {
"@ws-tools/scripts": "*"
}
}
16 changes: 16 additions & 0 deletions packages/paths/src/findGitRoot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import path from "path";
import { spawnSync } from "child_process";

/**
* Starting from `cwd`, uses `git rev-parse --show-toplevel` to find the root of the git repo.
* Throws if `cwd` is not in a Git repository.
*/
export function findGitRoot(cwd: string) {
const result = spawnSync("git", ["rev-parse", "--show-toplevel"], { cwd });

if (result.status !== 0) {
throw new Error(`Directory "${cwd}" is not in a git repository`);
}

return path.normalize(result.stdout.toString().trim());
}
10 changes: 10 additions & 0 deletions packages/paths/src/findPackageRoot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import path from "path";
import { searchUp } from "./searchUp";

/**
* Starting from `cwd`, searches up the directory hierarchy for `package.json`.
*/
export function findPackageRoot(cwd: string) {
const jsonPath = searchUp("package.json", cwd);
return jsonPath && path.dirname(jsonPath);
}
3 changes: 3 additions & 0 deletions packages/paths/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { findGitRoot } from "./findGitRoot";
export { findPackageRoot } from "./findPackageRoot";
export { searchUp } from "./searchUp";
27 changes: 27 additions & 0 deletions packages/paths/src/searchUp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import path from "path";
import fs from "fs";

/**
* Starting from `cwd`, searches up the directory hierarchy for `filePath`.
* If multiple strings are given, searches each directory level for any of them.
* @returns Full path to the item found, or undefined if not found.
*/
export function searchUp(filePath: string | string[], cwd: string) {
const paths = typeof filePath === "string" ? [filePath] : filePath;
// convert to an absolute path if needed
cwd = path.resolve(cwd);
const root = path.parse(cwd).root;

let foundPath: string | undefined;

while (!foundPath && cwd !== root) {
foundPath = paths.find((p) => fs.existsSync(path.join(cwd, p)));
if (foundPath) {
break;
}

cwd = path.dirname(cwd);
}

return foundPath ? path.join(cwd, foundPath) : undefined;
}
7 changes: 7 additions & 0 deletions packages/paths/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "@ws-tools/scripts/tsconfig.base.json",
"compilerOptions": {
"outDir": "lib"
},
"include": ["src"]
}
14 changes: 7 additions & 7 deletions packages/workspace-tools/etc/workspace-tools.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

/// <reference types="node" />

import { findGitRoot } from '@ws-tools/paths';
import { findPackageRoot } from '@ws-tools/paths';
import { searchUp } from '@ws-tools/paths';
import { SpawnSyncOptions } from 'child_process';
import { SpawnSyncReturns } from 'child_process';

Expand Down Expand Up @@ -56,11 +59,9 @@ export function fetchRemote(remote: string, cwd: string): void;
// @public (undocumented)
export function fetchRemoteBranch(remote: string, remoteBranch: string, cwd: string): void;

// @public
export function findGitRoot(cwd: string): string;
export { findGitRoot }

// @public
export function findPackageRoot(cwd: string): string | undefined;
export { findPackageRoot }

// @public
export function findProjectRoot(cwd: string): string;
Expand Down Expand Up @@ -250,7 +251,7 @@ export type GitProcessOutput = {
// @public (undocumented)
export function init(cwd: string, email?: string, username?: string): void;

// @public (undocumented)
// @public @deprecated (undocumented)
export function isChildOf(child: string, parent: string): boolean;

// @public (undocumented)
Expand Down Expand Up @@ -444,8 +445,7 @@ export function _resetPackageJsonFilesCache(): void;
// @public (undocumented)
export function revertLocalChanges(cwd: string): boolean;

// @public
export function searchUp(filePath: string | string[], cwd: string): string | undefined;
export { searchUp }

// @public
export function setCachingEnabled(enabled: boolean): void;
Expand Down
5 changes: 3 additions & 2 deletions packages/workspace-tools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
],
"scripts": {
"api": "ws-tools-scripts api",
"build": "tsc",
"build": "tsc --pretty",
"start": "tsc -w --preserveWatchOutput",
"test": "jest"
},
Expand All @@ -25,7 +25,8 @@
"globby": "^11.0.0",
"jju": "^1.4.0",
"js-yaml": "^4.1.0",
"micromatch": "^4.0.0"
"micromatch": "^4.0.0",
"@ws-tools/paths": "^0.1.0"
},
"devDependencies": {
"lodash": "^4.17.21",
Expand Down
2 changes: 1 addition & 1 deletion packages/workspace-tools/src/git/getDefaultRemote.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fs from "fs";
import path from "path";
import { findGitRoot } from "../paths";
import { findGitRoot } from "@ws-tools/paths";
import { PackageInfo } from "../types/PackageInfo";
import { getRepositoryName } from "./getRepositoryName";
import { git } from "./git";
Expand Down
1 change: 0 additions & 1 deletion packages/workspace-tools/src/graph/createDependencyMap.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { getPackageDependencies, PackageDependenciesOptions } from "./getPackageDependencies";
import { PackageInfos } from "../types/PackageInfo";
import { getPackageInfos, getPackageInfosAsync } from "../getPackageInfos";

export interface DependencyMap {
dependencies: Map<string, Set<string>>;
Expand Down
2 changes: 2 additions & 0 deletions packages/workspace-tools/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ export * from "./workspaces/getChangedPackages";
export * from "./workspaces/getPackagesByFiles";
export * from "./workspaces/listOfWorkspacePackageNames";
export * from "./workspaces/getAllPackageJsonFiles";

export { searchUp, findGitRoot, findPackageRoot } from "@ws-tools/paths";
2 changes: 1 addition & 1 deletion packages/workspace-tools/src/lockfile/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import fs from "fs";
import path from "path";
import { ParsedLock, PnpmLockFile, NpmLockFile, BerryLockFile } from "./types";
import { nameAtVersion } from "./nameAtVersion";
import { searchUp } from "../paths";
import { searchUp } from "@ws-tools/paths";
import { parsePnpmLock } from "./parsePnpmLock";
import { parseNpmLock } from "./parseNpmLock";
import { readYaml } from "./readYaml";
Expand Down
50 changes: 2 additions & 48 deletions packages/workspace-tools/src/paths.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,8 @@
import path from "path";
import fs from "fs";
import { findGitRoot } from "@ws-tools/paths";
import { getWorkspaceRoot } from "./workspaces/getWorkspaceRoot";
import { git } from "./git";
import { logVerboseWarning } from "./logging";

/**
* Starting from `cwd`, searches up the directory hierarchy for `filePath`.
* If multiple strings are given, searches each directory level for any of them.
* @returns Full path to the item found, or undefined if not found.
*/
export function searchUp(filePath: string | string[], cwd: string) {
const paths = typeof filePath === "string" ? [filePath] : filePath;
// convert to an absolute path if needed
cwd = path.resolve(cwd);
const root = path.parse(cwd).root;

let foundPath: string | undefined;

while (!foundPath && cwd !== root) {
foundPath = paths.find((p) => fs.existsSync(path.join(cwd, p)));
if (foundPath) {
break;
}

cwd = path.dirname(cwd);
}

return foundPath ? path.join(cwd, foundPath) : undefined;
}

/**
* Starting from `cwd`, uses `git rev-parse --show-toplevel` to find the root of the git repo.
* Throws if `cwd` is not in a Git repository.
*/
export function findGitRoot(cwd: string) {
const output = git(["rev-parse", "--show-toplevel"], { cwd });
if (!output.success) {
throw new Error(`Directory "${cwd}" is not in a git repository`);
}

return path.normalize(output.stdout);
}

/**
* Starting from `cwd`, searches up the directory hierarchy for `package.json`.
*/
export function findPackageRoot(cwd: string) {
const jsonPath = searchUp("package.json", cwd);
return jsonPath && path.dirname(jsonPath);
}

/**
* Starting from `cwd`, searches up the directory hierarchy for the workspace root,
* falling back to the git root if no workspace is detected.
Expand All @@ -68,6 +21,7 @@ export function findProjectRoot(cwd: string) {
return workspaceRoot || findGitRoot(cwd);
}

/** @deprecated */
export function isChildOf(child: string, parent: string) {
const relativePath = path.relative(child, parent);
return /^[.\/\\]+$/.test(relativePath);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from "path";
import { searchUp } from "../../paths";
import { searchUp } from "@ws-tools/paths";
import { WorkspaceManager } from "../WorkspaceManager";
import { isCachingEnabled } from "../../isCachingEnabled";

Expand Down
2 changes: 1 addition & 1 deletion scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
"ws-tools-scripts": "bin/ws-tools-scripts.js"
},
"scripts": {
"build": "tsc --noEmit"
"build": "tsc --pretty --noEmit"
}
}
1 change: 1 addition & 0 deletions scripts/tsconfig.base.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"declaration": true,
"sourceMap": true,
"strict": true,
"noUnusedLocals": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
Expand Down
Loading