dependency-owners 1.0.0 → 1.1.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/dist/cli.js +13 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -17
- package/dist/loader.d.ts +1 -17
- package/dist/utils/loader.d.ts +24 -0
- package/dist/utils/loader.js +48 -0
- package/dist/utils/message.d.ts +6 -0
- package/dist/utils/message.js +11 -0
- package/dist/utils/owners.d.ts +19 -0
- package/dist/utils/owners.js +33 -0
- package/dist/utils.d.ts +1 -27
- package/dist/utils.js +1 -82
- package/package.json +8 -3
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,8 @@ import { buildApplication, buildCommand, run, } from '@stricli/core';
|
|
|
3
3
|
import { createRequire } from 'node:module';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { dependencyOwners } from './index.js';
|
|
6
|
-
import { getErrorMessage } from './utils.js';
|
|
6
|
+
import { getErrorMessage } from './utils/message.js';
|
|
7
|
+
import { getUnownedDependencies } from './utils/owners.js';
|
|
7
8
|
const { name, version, description } = createRequire(import.meta.url)('../package.json');
|
|
8
9
|
function cwdParser(rawInput) {
|
|
9
10
|
return this.path.join(this.process.cwd(), rawInput);
|
|
@@ -17,6 +18,12 @@ const command = buildCommand({
|
|
|
17
18
|
dependencyFile,
|
|
18
19
|
loader: flags.loader,
|
|
19
20
|
});
|
|
21
|
+
if (flags['fail-on-unowned']) {
|
|
22
|
+
const unownedDeps = getUnownedDependencies(result);
|
|
23
|
+
if (unownedDeps.length > 0) {
|
|
24
|
+
throw new Error(`Unowned dependencies found: ${unownedDeps.join(', ')}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
20
27
|
this.process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
21
28
|
}
|
|
22
29
|
catch (error) {
|
|
@@ -40,6 +47,11 @@ const command = buildCommand({
|
|
|
40
47
|
optional: true,
|
|
41
48
|
variadic: true,
|
|
42
49
|
},
|
|
50
|
+
'fail-on-unowned': {
|
|
51
|
+
kind: 'boolean',
|
|
52
|
+
brief: 'Fail if any dependencies are unowned.',
|
|
53
|
+
default: false,
|
|
54
|
+
},
|
|
43
55
|
loader: {
|
|
44
56
|
kind: 'parsed',
|
|
45
57
|
parse: String,
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,21 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as PackageJsonLoader from '@dependency-owners/package-json-loader';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { getOwners, getOwnersMapping
|
|
4
|
-
|
|
5
|
-
* Loader for loading dependencies from package.json files.
|
|
6
|
-
*/
|
|
7
|
-
const PackageJsonLoader = {
|
|
8
|
-
async canLoad(filePath) {
|
|
9
|
-
return path.basename(filePath) === 'package.json';
|
|
10
|
-
},
|
|
11
|
-
async load(filePath) {
|
|
12
|
-
const pkg = JSON.parse(await fs.readFile(filePath, 'utf-8'));
|
|
13
|
-
return [
|
|
14
|
-
...Object.keys(pkg.dependencies || {}),
|
|
15
|
-
...Object.keys(pkg.devDependencies || {}),
|
|
16
|
-
];
|
|
17
|
-
},
|
|
18
|
-
};
|
|
3
|
+
import { getOwners, getOwnersMapping } from './utils/owners.js';
|
|
4
|
+
import { resolveDependencyLoader, } from './utils/loader.js';
|
|
19
5
|
/**
|
|
20
6
|
* Get the owners of the specified dependencies.
|
|
21
7
|
* @param {Options} options - The options for the dependency owners lookup.
|
package/dist/loader.d.ts
CHANGED
|
@@ -1,17 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Interface for loading dependencies from various file types.
|
|
3
|
-
*/
|
|
4
|
-
export interface DependencyLoader {
|
|
5
|
-
/**
|
|
6
|
-
* Check if the loader can handle the specified file.
|
|
7
|
-
* @param {string} filePath The path to the file to check.
|
|
8
|
-
* @returns {boolean} True if the loader can handle the file, false otherwise.
|
|
9
|
-
*/
|
|
10
|
-
canLoad(filePath: string): Promise<boolean>;
|
|
11
|
-
/**
|
|
12
|
-
* Load the dependencies from the specified file.
|
|
13
|
-
* @param {string} filePath The path to the file to load dependencies from.
|
|
14
|
-
* @returns {string[]} The list of loaded dependencies.
|
|
15
|
-
*/
|
|
16
|
-
load(filePath: string): Promise<string[]>;
|
|
17
|
-
}
|
|
1
|
+
export type { DependencyLoader } from './utils/loader.js';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for loading dependencies from various file types.
|
|
3
|
+
*/
|
|
4
|
+
export interface DependencyLoader {
|
|
5
|
+
/**
|
|
6
|
+
* Check if the loader can handle the specified file.
|
|
7
|
+
* @param {string} filePath The path to the file to check.
|
|
8
|
+
* @returns {boolean} True if the loader can handle the file, false otherwise.
|
|
9
|
+
*/
|
|
10
|
+
canLoad(filePath: string): Promise<boolean>;
|
|
11
|
+
/**
|
|
12
|
+
* Load the dependencies from the specified file.
|
|
13
|
+
* @param {string} filePath The path to the file to load dependencies from.
|
|
14
|
+
* @returns {string[]} The list of loaded dependencies.
|
|
15
|
+
*/
|
|
16
|
+
load(filePath: string): Promise<string[]>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Resolve a dependency loader for a specific file.
|
|
20
|
+
* @param {DependencyLoader | string} loader The loader to use.
|
|
21
|
+
* @param {string} depFilePath The path to the dependency file.
|
|
22
|
+
* @returns {Promise<DependencyLoader | undefined>} The resolved dependency loader or undefined if not found.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveDependencyLoader(loader: DependencyLoader | string, depFilePath: string): Promise<DependencyLoader | undefined>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
/**
|
|
3
|
+
* Import a dependency loader by name.
|
|
4
|
+
* @param {string} loaderName The name of the loader to import.
|
|
5
|
+
* @returns {Promise<DependencyLoader>} The imported dependency loader.
|
|
6
|
+
*/
|
|
7
|
+
async function importDependencyLoader(loaderName) {
|
|
8
|
+
let loaderModule;
|
|
9
|
+
// Try importing from an installed dependency/absolute path
|
|
10
|
+
try {
|
|
11
|
+
loaderModule = await import(loaderName);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
// no-op
|
|
15
|
+
}
|
|
16
|
+
// Try import from relative path
|
|
17
|
+
try {
|
|
18
|
+
loaderModule = await import(path.join(process.cwd(), loaderName));
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// no-op
|
|
22
|
+
}
|
|
23
|
+
// If we couldn't find the module, throw an error
|
|
24
|
+
if (!loaderModule) {
|
|
25
|
+
throw new Error(`Failed to import loader: ${loaderName}`);
|
|
26
|
+
}
|
|
27
|
+
// Check if the loader has the required functions
|
|
28
|
+
const loader = loaderModule.default || loaderModule;
|
|
29
|
+
if (loader &&
|
|
30
|
+
typeof loader.canLoad === 'function' &&
|
|
31
|
+
typeof loader.load === 'function') {
|
|
32
|
+
return loader;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
throw new Error(`Invalid loader: ${loaderName}. The module does not export an object with 'canLoad' and 'load' functions.`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Resolve a dependency loader for a specific file.
|
|
40
|
+
* @param {DependencyLoader | string} loader The loader to use.
|
|
41
|
+
* @param {string} depFilePath The path to the dependency file.
|
|
42
|
+
* @returns {Promise<DependencyLoader | undefined>} The resolved dependency loader or undefined if not found.
|
|
43
|
+
*/
|
|
44
|
+
export async function resolveDependencyLoader(loader, depFilePath) {
|
|
45
|
+
const resolvedLoader = typeof loader === 'string' ? await importDependencyLoader(loader) : loader;
|
|
46
|
+
const canLoad = await resolvedLoader.canLoad(depFilePath);
|
|
47
|
+
return canLoad ? resolvedLoader : undefined;
|
|
48
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the mapping of dependency owners from a JSON file.
|
|
3
|
+
* @param {string} filePath - The path to the dependency owners file.
|
|
4
|
+
* @returns {Record<string, string[]>} A mapping of dependency owners.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getOwnersMapping(filePath: string): Record<string, string[]>;
|
|
7
|
+
/**
|
|
8
|
+
* Get the owners of the specified dependencies.
|
|
9
|
+
* @param {string[]} dependencies - The list of dependencies to check.
|
|
10
|
+
* @param {Record<string, string[]>} ownersMapping - The mapping of dependency owners.
|
|
11
|
+
* @returns {Record<string, string[]>} A mapping of dependency owners for the specified dependencies.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getOwners(dependencies: string[], ownersMapping: Record<string, string[]>): Record<string, string[]>;
|
|
14
|
+
/**
|
|
15
|
+
* Get a list of unowned dependencies.
|
|
16
|
+
* @param owners The mapping of dependency owners.
|
|
17
|
+
* @returns A list of unowned dependencies.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getUnownedDependencies(owners: Record<string, string[]>): string[];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
/**
|
|
3
|
+
* Get the mapping of dependency owners from a JSON file.
|
|
4
|
+
* @param {string} filePath - The path to the dependency owners file.
|
|
5
|
+
* @returns {Record<string, string[]>} A mapping of dependency owners.
|
|
6
|
+
*/
|
|
7
|
+
export function getOwnersMapping(filePath) {
|
|
8
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Get the owners of the specified dependencies.
|
|
12
|
+
* @param {string[]} dependencies - The list of dependencies to check.
|
|
13
|
+
* @param {Record<string, string[]>} ownersMapping - The mapping of dependency owners.
|
|
14
|
+
* @returns {Record<string, string[]>} A mapping of dependency owners for the specified dependencies.
|
|
15
|
+
*/
|
|
16
|
+
export function getOwners(dependencies, ownersMapping) {
|
|
17
|
+
return dependencies.reduce((result, dep) => {
|
|
18
|
+
const owners = Object.keys(ownersMapping).filter((owner) => Array.isArray(ownersMapping[owner]) &&
|
|
19
|
+
ownersMapping[owner].includes(dep));
|
|
20
|
+
result[dep] = owners;
|
|
21
|
+
return result;
|
|
22
|
+
}, {});
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get a list of unowned dependencies.
|
|
26
|
+
* @param owners The mapping of dependency owners.
|
|
27
|
+
* @returns A list of unowned dependencies.
|
|
28
|
+
*/
|
|
29
|
+
export function getUnownedDependencies(owners) {
|
|
30
|
+
return Object.entries(owners)
|
|
31
|
+
.filter(([_key, deps]) => deps.length === 0)
|
|
32
|
+
.map(([key]) => key);
|
|
33
|
+
}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,27 +1 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Get the mapping of dependency owners from a JSON file.
|
|
4
|
-
* @param {string} filePath - The path to the dependency owners file.
|
|
5
|
-
* @returns {Record<string, string[]>} A mapping of dependency owners.
|
|
6
|
-
*/
|
|
7
|
-
export declare function getOwnersMapping(filePath: string): Record<string, string[]>;
|
|
8
|
-
/**
|
|
9
|
-
* Get the owners of the specified dependencies.
|
|
10
|
-
* @param {string[]} dependencies - The list of dependencies to check.
|
|
11
|
-
* @param {Record<string, string[]>} ownersMapping - The mapping of dependency owners.
|
|
12
|
-
* @returns {Record<string, string[]>} A mapping of dependency owners for the specified dependencies.
|
|
13
|
-
*/
|
|
14
|
-
export declare function getOwners(dependencies: string[], ownersMapping: Record<string, string[]>): Record<string, string[]>;
|
|
15
|
-
/**
|
|
16
|
-
* Resolve a dependency loader for a specific file.
|
|
17
|
-
* @param {DependencyLoader | string} loader The loader to use.
|
|
18
|
-
* @param {string} depFilePath The path to the dependency file.
|
|
19
|
-
* @returns {Promise<DependencyLoader | undefined>} The resolved dependency loader or undefined if not found.
|
|
20
|
-
*/
|
|
21
|
-
export declare function resolveDependencyLoader(loader: DependencyLoader | string, depFilePath: string): Promise<DependencyLoader | undefined>;
|
|
22
|
-
/**
|
|
23
|
-
* Get a formatted error message.
|
|
24
|
-
* @param error The error to format.
|
|
25
|
-
* @returns The formatted error message.
|
|
26
|
-
*/
|
|
27
|
-
export declare function getErrorMessage(error: unknown): string;
|
|
1
|
+
export { getUnownedDependencies } from './utils/owners.js';
|
package/dist/utils.js
CHANGED
|
@@ -1,82 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
/**
|
|
4
|
-
* Get the mapping of dependency owners from a JSON file.
|
|
5
|
-
* @param {string} filePath - The path to the dependency owners file.
|
|
6
|
-
* @returns {Record<string, string[]>} A mapping of dependency owners.
|
|
7
|
-
*/
|
|
8
|
-
export function getOwnersMapping(filePath) {
|
|
9
|
-
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Get the owners of the specified dependencies.
|
|
13
|
-
* @param {string[]} dependencies - The list of dependencies to check.
|
|
14
|
-
* @param {Record<string, string[]>} ownersMapping - The mapping of dependency owners.
|
|
15
|
-
* @returns {Record<string, string[]>} A mapping of dependency owners for the specified dependencies.
|
|
16
|
-
*/
|
|
17
|
-
export function getOwners(dependencies, ownersMapping) {
|
|
18
|
-
return dependencies.reduce((result, dep) => {
|
|
19
|
-
const owners = Object.keys(ownersMapping).filter((owner) => Array.isArray(ownersMapping[owner]) &&
|
|
20
|
-
ownersMapping[owner].includes(dep));
|
|
21
|
-
result[dep] = owners;
|
|
22
|
-
return result;
|
|
23
|
-
}, {});
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Import a dependency loader by name.
|
|
27
|
-
* @param {string} loaderName The name of the loader to import.
|
|
28
|
-
* @returns {Promise<DependencyLoader>} The imported dependency loader.
|
|
29
|
-
*/
|
|
30
|
-
async function importDependencyLoader(loaderName) {
|
|
31
|
-
let loaderModule;
|
|
32
|
-
// Try importing from an installed dependency/absolute path
|
|
33
|
-
try {
|
|
34
|
-
loaderModule = await import(loaderName);
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
// no-op
|
|
38
|
-
}
|
|
39
|
-
// Try import from relative path
|
|
40
|
-
try {
|
|
41
|
-
loaderModule = await import(path.join(process.cwd(), loaderName));
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
// no-op
|
|
45
|
-
}
|
|
46
|
-
// If we couldn't find the module, throw an error
|
|
47
|
-
if (!loaderModule) {
|
|
48
|
-
throw new Error(`Failed to import loader: ${loaderName}`);
|
|
49
|
-
}
|
|
50
|
-
// Check if the loader has the required functions
|
|
51
|
-
const loader = loaderModule.default || loaderModule;
|
|
52
|
-
if (loader &&
|
|
53
|
-
typeof loader.canLoad === 'function' &&
|
|
54
|
-
typeof loader.load === 'function') {
|
|
55
|
-
return loader;
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
throw new Error(`Invalid loader: ${loaderName}. The module does not export an object with 'canLoad' and 'load' functions.`);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Resolve a dependency loader for a specific file.
|
|
63
|
-
* @param {DependencyLoader | string} loader The loader to use.
|
|
64
|
-
* @param {string} depFilePath The path to the dependency file.
|
|
65
|
-
* @returns {Promise<DependencyLoader | undefined>} The resolved dependency loader or undefined if not found.
|
|
66
|
-
*/
|
|
67
|
-
export async function resolveDependencyLoader(loader, depFilePath) {
|
|
68
|
-
const resolvedLoader = typeof loader === 'string' ? await importDependencyLoader(loader) : loader;
|
|
69
|
-
const canLoad = await resolvedLoader.canLoad(depFilePath);
|
|
70
|
-
return canLoad ? resolvedLoader : undefined;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Get a formatted error message.
|
|
74
|
-
* @param error The error to format.
|
|
75
|
-
* @returns The formatted error message.
|
|
76
|
-
*/
|
|
77
|
-
export function getErrorMessage(error) {
|
|
78
|
-
if (error instanceof Error) {
|
|
79
|
-
return error.message;
|
|
80
|
-
}
|
|
81
|
-
return String(error);
|
|
82
|
-
}
|
|
1
|
+
export { getUnownedDependencies } from './utils/owners.js';
|
package/package.json
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dependency-owners",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Determine ownership of dependencies in a project",
|
|
5
5
|
"author": "Kirk Eaton <contact@kirkeaton.ca>",
|
|
6
6
|
"bin": "./dist/cli.js",
|
|
7
7
|
"dependencies": {
|
|
8
|
+
"@dependency-owners/package-json-loader": "1.0.0",
|
|
8
9
|
"@stricli/core": "1.2.0"
|
|
9
10
|
},
|
|
10
11
|
"devDependencies": {
|
|
11
12
|
"@kirkeaton/prettier-config": "1.0.5",
|
|
12
13
|
"@kirkeaton/semantic-release-config": "1.0.4",
|
|
13
14
|
"@kirkeaton/tsconfig": "1.0.3",
|
|
14
|
-
"@types/node": "24.
|
|
15
|
+
"@types/node": "24.3.0",
|
|
15
16
|
"fs-fixture": "2.8.1",
|
|
16
17
|
"prettier": "3.6.2",
|
|
17
18
|
"semantic-release": "24.2.7",
|
|
@@ -29,6 +30,10 @@
|
|
|
29
30
|
"./loader": {
|
|
30
31
|
"types": "./dist/loader.d.ts",
|
|
31
32
|
"default": "./dist/loader.js"
|
|
33
|
+
},
|
|
34
|
+
"./utils": {
|
|
35
|
+
"types": "./dist/utils.d.ts",
|
|
36
|
+
"default": "./dist/utils.js"
|
|
32
37
|
}
|
|
33
38
|
},
|
|
34
39
|
"files": [
|
|
@@ -50,7 +55,7 @@
|
|
|
50
55
|
"build": "pnpm clean && tsc",
|
|
51
56
|
"clean": "rm -rf dist",
|
|
52
57
|
"format": "prettier \"**/*.{js,json,md,ts}\" --write",
|
|
53
|
-
"lint": "prettier \"**/*.{js,json,md,ts
|
|
58
|
+
"lint": "prettier \"**/*.{js,json,md,ts}\" --check",
|
|
54
59
|
"prepublishOnly": "pnpm build",
|
|
55
60
|
"test": "tsx --test",
|
|
56
61
|
"typecheck": "tsc --noEmit"
|