@theholocron/fs-utils 1.15.1 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,6 +17,7 @@ import {
17
17
  findRoot,
18
18
  findUpward,
19
19
  hasGitEntry,
20
+ isWorkspaceRoot,
20
21
  walkFilesSync,
21
22
  } from "@theholocron/fs-utils";
22
23
 
@@ -33,6 +34,9 @@ const configDir = await findUpward(
33
34
 
34
35
  // a plain boundary check, usable as `findUpward`'s `stop` or on its own
35
36
  await hasGitEntry("/path/to/dir"); // true if a .git entry (file or folder) exists there
37
+
38
+ // decide whether a pnpm command needs -w at this directory
39
+ await isWorkspaceRoot(repoRoot ?? process.cwd());
36
40
  ```
37
41
 
38
42
  ### `findUpward(startDir, check, stop?)`
@@ -113,6 +117,13 @@ checkout, a file in a worktree/submodule (existence is all that matters).
113
117
  A common `stop` boundary for `findUpward`: treat the nearest `.git` as
114
118
  the project root, searched but not walked past.
115
119
 
120
+ ### `isWorkspaceRoot(dir)`
121
+
122
+ Returns `true` when `dir` has a `pnpm-workspace.yaml` — the file that marks
123
+ a pnpm workspace root. Several pnpm CLI commands (`pnpm add` among them)
124
+ behave differently at a workspace root than in a plain package, so a caller
125
+ shelling out to pnpm can check this before deciding which flags to pass.
126
+
116
127
  ## Documentation
117
128
 
118
129
  Check out [The Holocron Archive](https://docs.theholocron.dev/projects/utils/) for more information.
package/dist/index.d.mts CHANGED
@@ -89,6 +89,25 @@ export declare function findUpward<T>(startDir: string, check: (dir: string) =>
89
89
  */
90
90
  export declare function hasGitEntry(dir: string): Promise<boolean>;
91
91
  //#endregion
92
+ //#region src/is-workspace-root.d.ts
93
+ /**
94
+ * `true` when `dir` has a `pnpm-workspace.yaml` regular file — the marker
95
+ * of a pnpm workspace root. Several pnpm CLI commands (`pnpm add` among
96
+ * them) behave differently at a workspace root than in a plain package,
97
+ * so callers shelling out to pnpm need this check before deciding which
98
+ * flags to pass.
99
+ *
100
+ * `dir` is resolved to an absolute path up front — a relative `dir`
101
+ * resolved lazily inside the `stat` call could end up checking a
102
+ * different directory if `process.chdir()` runs on another task while
103
+ * this one is pending. A directory or symlink-to-directory named
104
+ * `pnpm-workspace.yaml` doesn't count (pnpm never creates one of those);
105
+ * only `stat`'s `ENOENT` means "not there" — any other error (`EACCES`,
106
+ * a transient I/O failure) propagates rather than silently reading as
107
+ * "not a workspace."
108
+ */
109
+ export declare function isWorkspaceRoot(dir: string): Promise<boolean>;
110
+ //#endregion
92
111
  //#region src/walk-files.d.ts
93
112
  export interface WalkFilesOptions {
94
113
  /** Directory names not descended into, at any depth (files with these names are still listed). Defaults to `.git` and `node_modules`. */
package/dist/index.mjs CHANGED
@@ -190,6 +190,32 @@ function findRootSync(startDir, marker, options = {}) {
190
190
  }
191
191
  }
192
192
  //#endregion
193
+ //#region src/is-workspace-root.ts
194
+ /**
195
+ * `true` when `dir` has a `pnpm-workspace.yaml` regular file — the marker
196
+ * of a pnpm workspace root. Several pnpm CLI commands (`pnpm add` among
197
+ * them) behave differently at a workspace root than in a plain package,
198
+ * so callers shelling out to pnpm need this check before deciding which
199
+ * flags to pass.
200
+ *
201
+ * `dir` is resolved to an absolute path up front — a relative `dir`
202
+ * resolved lazily inside the `stat` call could end up checking a
203
+ * different directory if `process.chdir()` runs on another task while
204
+ * this one is pending. A directory or symlink-to-directory named
205
+ * `pnpm-workspace.yaml` doesn't count (pnpm never creates one of those);
206
+ * only `stat`'s `ENOENT` means "not there" — any other error (`EACCES`,
207
+ * a transient I/O failure) propagates rather than silently reading as
208
+ * "not a workspace."
209
+ */
210
+ async function isWorkspaceRoot(dir) {
211
+ try {
212
+ return (await stat(join(resolve(dir), "pnpm-workspace.yaml"))).isFile();
213
+ } catch (err) {
214
+ if (err.code === "ENOENT") return false;
215
+ throw err;
216
+ }
217
+ }
218
+ //#endregion
193
219
  //#region src/walk-files.ts
194
220
  const DEFAULT_SKIP = [".git", "node_modules"];
195
221
  /** The entry's type, asking the filesystem when the platform's directory listing couldn't say. */
@@ -239,4 +265,4 @@ function walkFilesSync(dir, options = {}) {
239
265
  return files;
240
266
  }
241
267
  //#endregion
242
- export { findExecutable, findExecutableSync, findRoot, findRootSync, findUpward, hasGitEntry, walkFilesSync };
268
+ export { findExecutable, findExecutableSync, findRoot, findRootSync, findUpward, hasGitEntry, isWorkspaceRoot, walkFilesSync };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theholocron/fs-utils",
3
- "version": "1.15.1",
3
+ "version": "1.16.0",
4
4
  "description": "Walk a directory tree upward to find the nearest match or project root.",
5
5
  "keywords": [
6
6
  "filesystem",