@augment-vir/node 31.44.0 → 31.45.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.
@@ -0,0 +1,38 @@
1
+ /**
2
+ * All `package.json` keys that are parsed as direct dependencies.
3
+ *
4
+ * @category Internal
5
+ */
6
+ export declare enum PackageJsonDependencyKey {
7
+ DevDependencies = "devDependencies",
8
+ Dependencies = "dependencies",
9
+ PeerDependencies = "peerDependencies"
10
+ }
11
+ /**
12
+ * A record of package names to package versions included in the direct dependencies. This is the
13
+ * output from {@link listAllDirectNpmDeps}.
14
+ *
15
+ * @category Internal
16
+ */
17
+ export type NpmDeps = Record<string, NpmDep[]>;
18
+ export type NpmDep = {
19
+ /** Path to the `package.json` file that depends on this. */
20
+ requiredBy: string;
21
+ dependencyKey: PackageJsonDependencyKey;
22
+ /**
23
+ * The version as it is directly noted in the `package.json` file. This might not necessarily
24
+ * correlate to any actually published versions.
25
+ */
26
+ versionValue: string;
27
+ /** If true, this dependency is part of the workspace's own packages. */
28
+ isWorkspace: boolean;
29
+ };
30
+ /**
31
+ * Finds all direct deps for the workspace at, or that contains, the given dir path.
32
+ *
33
+ * @category Node : Npm
34
+ * @category Package : @augment-vir/node
35
+ * @throws If no directory with a `package-lock.json` file is found.
36
+ * @package [`@augment-vir/node`](https://www.npmjs.com/package/@augment-vir/node)
37
+ */
38
+ export declare function listAllDirectNpmDeps(startDirPath: string): Promise<NpmDeps>;
@@ -0,0 +1,47 @@
1
+ import { check } from '@augment-vir/assert';
2
+ import { filterMap, getEnumValues, getObjectTypedEntries, getOrSet } from '@augment-vir/common';
3
+ import { readJsonFile } from '../fs/json.js';
4
+ import { findAllPackageJsonFilePaths } from './package-json.js';
5
+ /**
6
+ * All `package.json` keys that are parsed as direct dependencies.
7
+ *
8
+ * @category Internal
9
+ */
10
+ export var PackageJsonDependencyKey;
11
+ (function (PackageJsonDependencyKey) {
12
+ PackageJsonDependencyKey["DevDependencies"] = "devDependencies";
13
+ PackageJsonDependencyKey["Dependencies"] = "dependencies";
14
+ PackageJsonDependencyKey["PeerDependencies"] = "peerDependencies";
15
+ })(PackageJsonDependencyKey || (PackageJsonDependencyKey = {}));
16
+ /**
17
+ * Finds all direct deps for the workspace at, or that contains, the given dir path.
18
+ *
19
+ * @category Node : Npm
20
+ * @category Package : @augment-vir/node
21
+ * @throws If no directory with a `package-lock.json` file is found.
22
+ * @package [`@augment-vir/node`](https://www.npmjs.com/package/@augment-vir/node)
23
+ */
24
+ export async function listAllDirectNpmDeps(startDirPath) {
25
+ const packageJsonFilePaths = await findAllPackageJsonFilePaths(startDirPath);
26
+ const deps = {};
27
+ const packageJsonFiles = await Promise.all(packageJsonFilePaths.map(async (packageJsonFilePath) => {
28
+ return {
29
+ packageJsonFilePath,
30
+ packageJson: (await readJsonFile(packageJsonFilePath)),
31
+ };
32
+ }));
33
+ const allWorkspacePackageNames = filterMap(packageJsonFiles, (packageJsonFile) => packageJsonFile.packageJson.name, check.isTruthy);
34
+ packageJsonFiles.forEach(({ packageJson, packageJsonFilePath }) => {
35
+ getEnumValues(PackageJsonDependencyKey).forEach((dependencyKey) => {
36
+ getObjectTypedEntries(packageJson[dependencyKey] || {}).forEach(([dependencyName, versionValue,]) => {
37
+ getOrSet(deps, dependencyName, () => []).push({
38
+ dependencyKey,
39
+ requiredBy: packageJsonFilePath,
40
+ versionValue,
41
+ isWorkspace: allWorkspacePackageNames.includes(dependencyName),
42
+ });
43
+ });
44
+ });
45
+ });
46
+ return deps;
47
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Finds all `package.json` files contained within the workspaces present in the current
3
+ * `startDirPath`. A workspace root dir is found by recursively looking for a parent
4
+ * `package-lock.json` file.
5
+ *
6
+ * @category Node : Npm
7
+ * @category Package : @augment-vir/node
8
+ * @throws If no directory with a `package-lock.json` file is found.
9
+ * @package [`@augment-vir/node`](https://www.npmjs.com/package/@augment-vir/node)
10
+ */
11
+ export declare function findAllPackageJsonFilePaths(startDirPath: string): Promise<string[]>;
12
+ /**
13
+ * Get all workspace package.json paths starting at the given directory path. The output is string
14
+ * sorted to keep it stable.
15
+ *
16
+ * @category Node : Npm
17
+ * @category Package : @augment-vir/node
18
+ * @throws Error if there is no `package.json` file at the given `rootDirPath`.
19
+ * @package [`@augment-vir/node`](https://www.npmjs.com/package/@augment-vir/node)
20
+ */
21
+ export declare function getWorkspacePackageJsonFilePaths(rootDirPath: string): Promise<string[]>;
@@ -0,0 +1,48 @@
1
+ import { check } from '@augment-vir/assert';
2
+ import { filterMap, fromAsyncIterable } from '@augment-vir/common';
3
+ import { existsSync } from 'node:fs';
4
+ import { glob, readFile } from 'node:fs/promises';
5
+ import { join } from 'node:path';
6
+ import { findAncestor, joinFilesToDir } from '../path/ancestor.js';
7
+ /**
8
+ * Finds all `package.json` files contained within the workspaces present in the current
9
+ * `startDirPath`. A workspace root dir is found by recursively looking for a parent
10
+ * `package-lock.json` file.
11
+ *
12
+ * @category Node : Npm
13
+ * @category Package : @augment-vir/node
14
+ * @throws If no directory with a `package-lock.json` file is found.
15
+ * @package [`@augment-vir/node`](https://www.npmjs.com/package/@augment-vir/node)
16
+ */
17
+ export async function findAllPackageJsonFilePaths(startDirPath) {
18
+ const packageRootDir = findAncestor(startDirPath, (dir) => existsSync(join(dir, 'package-lock.json')));
19
+ if (!packageRootDir) {
20
+ throw new Error(`Cannot find all package.json files: failed to find any directory with a package-lock.json file. Started at '${startDirPath}'.`);
21
+ }
22
+ const rootPackageJsonPath = join(packageRootDir, 'package.json');
23
+ return [
24
+ rootPackageJsonPath,
25
+ ...(await getWorkspacePackageJsonFilePaths(packageRootDir)),
26
+ ];
27
+ }
28
+ /**
29
+ * Get all workspace package.json paths starting at the given directory path. The output is string
30
+ * sorted to keep it stable.
31
+ *
32
+ * @category Node : Npm
33
+ * @category Package : @augment-vir/node
34
+ * @throws Error if there is no `package.json` file at the given `rootDirPath`.
35
+ * @package [`@augment-vir/node`](https://www.npmjs.com/package/@augment-vir/node)
36
+ */
37
+ export async function getWorkspacePackageJsonFilePaths(rootDirPath) {
38
+ const packageJson = JSON.parse(await readFile(join(rootDirPath, 'package.json'), 'utf8'));
39
+ /* node:coverage ignore next 3: this package only uses one type of workspace */
40
+ const patterns = check.isArray(packageJson.workspaces)
41
+ ? packageJson.workspaces
42
+ : packageJson.workspaces?.packages || [];
43
+ const matchedPaths = joinFilesToDir(rootDirPath, (await Promise.all(patterns.map(async (pattern) => {
44
+ return await fromAsyncIterable(glob(pattern, { cwd: rootDirPath }));
45
+ }))).flat());
46
+ const workspacePackageJsonPaths = filterMap(matchedPaths, (matchedPath) => join(matchedPath, 'package.json'), (packageJsonPath) => existsSync(packageJsonPath));
47
+ return workspacePackageJsonPaths.sort();
48
+ }
package/dist/index.d.ts CHANGED
@@ -6,6 +6,8 @@ export * from './augments/fs/read-file.js';
6
6
  export * from './augments/fs/symlink.js';
7
7
  export * from './augments/fs/write.js';
8
8
  export * from './augments/npm/find-bin-path.js';
9
+ export * from './augments/npm/npm-deps.js';
10
+ export * from './augments/npm/package-json.js';
9
11
  export * from './augments/npm/query-workspace.js';
10
12
  export * from './augments/npm/read-package-json.js';
11
13
  export * from './augments/os/operating-system.js';
package/dist/index.js CHANGED
@@ -6,6 +6,8 @@ export * from './augments/fs/read-file.js';
6
6
  export * from './augments/fs/symlink.js';
7
7
  export * from './augments/fs/write.js';
8
8
  export * from './augments/npm/find-bin-path.js';
9
+ export * from './augments/npm/npm-deps.js';
10
+ export * from './augments/npm/package-json.js';
9
11
  export * from './augments/npm/query-workspace.js';
10
12
  export * from './augments/npm/read-package-json.js';
11
13
  export * from './augments/os/operating-system.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@augment-vir/node",
3
- "version": "31.44.0",
3
+ "version": "31.45.0",
4
4
  "description": "A collection of augments, helpers types, functions, and classes only for Node.js (backend) JavaScript environments.",
5
5
  "keywords": [
6
6
  "augment",
@@ -38,8 +38,8 @@
38
38
  "test:update": "npm test"
39
39
  },
40
40
  "dependencies": {
41
- "@augment-vir/assert": "^31.44.0",
42
- "@augment-vir/common": "^31.44.0",
41
+ "@augment-vir/assert": "^31.45.0",
42
+ "@augment-vir/common": "^31.45.0",
43
43
  "@date-vir/duration": "^8.0.0",
44
44
  "ansi-styles": "^6.2.3",
45
45
  "sanitize-filename": "^1.6.3",
@@ -49,7 +49,7 @@
49
49
  "typed-event-target": "^4.1.0"
50
50
  },
51
51
  "devDependencies": {
52
- "@augment-vir/test": "^31.44.0",
52
+ "@augment-vir/test": "^31.45.0",
53
53
  "@types/node": "^24.9.1",
54
54
  "@web/dev-server-esbuild": "^1.0.4",
55
55
  "@web/test-runner": "^0.20.2",
@@ -0,0 +1,85 @@
1
+ import {check} from '@augment-vir/assert';
2
+ import {filterMap, getEnumValues, getObjectTypedEntries, getOrSet} from '@augment-vir/common';
3
+ import {type PackageJson} from 'type-fest';
4
+ import {readJsonFile} from '../fs/json.js';
5
+ import {findAllPackageJsonFilePaths} from './package-json.js';
6
+
7
+ /**
8
+ * All `package.json` keys that are parsed as direct dependencies.
9
+ *
10
+ * @category Internal
11
+ */
12
+ export enum PackageJsonDependencyKey {
13
+ DevDependencies = 'devDependencies',
14
+ Dependencies = 'dependencies',
15
+ PeerDependencies = 'peerDependencies',
16
+ }
17
+
18
+ /**
19
+ * A record of package names to package versions included in the direct dependencies. This is the
20
+ * output from {@link listAllDirectNpmDeps}.
21
+ *
22
+ * @category Internal
23
+ */
24
+ export type NpmDeps = Record<string, NpmDep[]>;
25
+ export type NpmDep = {
26
+ /** Path to the `package.json` file that depends on this. */
27
+ requiredBy: string;
28
+ dependencyKey: PackageJsonDependencyKey;
29
+ /**
30
+ * The version as it is directly noted in the `package.json` file. This might not necessarily
31
+ * correlate to any actually published versions.
32
+ */
33
+ versionValue: string;
34
+ /** If true, this dependency is part of the workspace's own packages. */
35
+ isWorkspace: boolean;
36
+ };
37
+
38
+ /**
39
+ * Finds all direct deps for the workspace at, or that contains, the given dir path.
40
+ *
41
+ * @category Node : Npm
42
+ * @category Package : @augment-vir/node
43
+ * @throws If no directory with a `package-lock.json` file is found.
44
+ * @package [`@augment-vir/node`](https://www.npmjs.com/package/@augment-vir/node)
45
+ */
46
+ export async function listAllDirectNpmDeps(startDirPath: string): Promise<NpmDeps> {
47
+ const packageJsonFilePaths = await findAllPackageJsonFilePaths(startDirPath);
48
+
49
+ const deps: NpmDeps = {};
50
+
51
+ const packageJsonFiles = await Promise.all(
52
+ packageJsonFilePaths.map(async (packageJsonFilePath) => {
53
+ return {
54
+ packageJsonFilePath,
55
+ packageJson: (await readJsonFile(packageJsonFilePath)) as PackageJson,
56
+ };
57
+ }),
58
+ );
59
+
60
+ const allWorkspacePackageNames = filterMap(
61
+ packageJsonFiles,
62
+ (packageJsonFile) => packageJsonFile.packageJson.name,
63
+ check.isTruthy,
64
+ );
65
+
66
+ packageJsonFiles.forEach(({packageJson, packageJsonFilePath}) => {
67
+ getEnumValues(PackageJsonDependencyKey).forEach((dependencyKey) => {
68
+ getObjectTypedEntries(packageJson[dependencyKey] || {}).forEach(
69
+ ([
70
+ dependencyName,
71
+ versionValue,
72
+ ]) => {
73
+ getOrSet(deps, dependencyName, () => []).push({
74
+ dependencyKey,
75
+ requiredBy: packageJsonFilePath,
76
+ versionValue,
77
+ isWorkspace: allWorkspacePackageNames.includes(dependencyName),
78
+ });
79
+ },
80
+ );
81
+ });
82
+ });
83
+
84
+ return deps;
85
+ }
@@ -0,0 +1,75 @@
1
+ import {check} from '@augment-vir/assert';
2
+ import {filterMap, fromAsyncIterable} from '@augment-vir/common';
3
+ import {existsSync} from 'node:fs';
4
+ import {glob, readFile} from 'node:fs/promises';
5
+ import {join} from 'node:path';
6
+ import {type PackageJson} from 'type-fest';
7
+ import {findAncestor, joinFilesToDir} from '../path/ancestor.js';
8
+
9
+ /**
10
+ * Finds all `package.json` files contained within the workspaces present in the current
11
+ * `startDirPath`. A workspace root dir is found by recursively looking for a parent
12
+ * `package-lock.json` file.
13
+ *
14
+ * @category Node : Npm
15
+ * @category Package : @augment-vir/node
16
+ * @throws If no directory with a `package-lock.json` file is found.
17
+ * @package [`@augment-vir/node`](https://www.npmjs.com/package/@augment-vir/node)
18
+ */
19
+ export async function findAllPackageJsonFilePaths(startDirPath: string) {
20
+ const packageRootDir = findAncestor(startDirPath, (dir) =>
21
+ existsSync(join(dir, 'package-lock.json')),
22
+ );
23
+
24
+ if (!packageRootDir) {
25
+ throw new Error(
26
+ `Cannot find all package.json files: failed to find any directory with a package-lock.json file. Started at '${startDirPath}'.`,
27
+ );
28
+ }
29
+
30
+ const rootPackageJsonPath = join(packageRootDir, 'package.json');
31
+
32
+ return [
33
+ rootPackageJsonPath,
34
+ ...(await getWorkspacePackageJsonFilePaths(packageRootDir)),
35
+ ];
36
+ }
37
+
38
+ /**
39
+ * Get all workspace package.json paths starting at the given directory path. The output is string
40
+ * sorted to keep it stable.
41
+ *
42
+ * @category Node : Npm
43
+ * @category Package : @augment-vir/node
44
+ * @throws Error if there is no `package.json` file at the given `rootDirPath`.
45
+ * @package [`@augment-vir/node`](https://www.npmjs.com/package/@augment-vir/node)
46
+ */
47
+ export async function getWorkspacePackageJsonFilePaths(rootDirPath: string): Promise<string[]> {
48
+ const packageJson: PackageJson = JSON.parse(
49
+ await readFile(join(rootDirPath, 'package.json'), 'utf8'),
50
+ );
51
+
52
+ /* node:coverage ignore next 3: this package only uses one type of workspace */
53
+ const patterns = check.isArray(packageJson.workspaces)
54
+ ? packageJson.workspaces
55
+ : packageJson.workspaces?.packages || [];
56
+
57
+ const matchedPaths: string[] = joinFilesToDir(
58
+ rootDirPath,
59
+ (
60
+ await Promise.all(
61
+ patterns.map(async (pattern) => {
62
+ return await fromAsyncIterable(glob(pattern, {cwd: rootDirPath}));
63
+ }),
64
+ )
65
+ ).flat(),
66
+ );
67
+
68
+ const workspacePackageJsonPaths = filterMap(
69
+ matchedPaths,
70
+ (matchedPath) => join(matchedPath, 'package.json'),
71
+ (packageJsonPath) => existsSync(packageJsonPath),
72
+ );
73
+
74
+ return workspacePackageJsonPaths.sort();
75
+ }
package/src/index.ts CHANGED
@@ -6,6 +6,8 @@ export * from './augments/fs/read-file.js';
6
6
  export * from './augments/fs/symlink.js';
7
7
  export * from './augments/fs/write.js';
8
8
  export * from './augments/npm/find-bin-path.js';
9
+ export * from './augments/npm/npm-deps.js';
10
+ export * from './augments/npm/package-json.js';
9
11
  export * from './augments/npm/query-workspace.js';
10
12
  export * from './augments/npm/read-package-json.js';
11
13
  export * from './augments/os/operating-system.js';