metascope 0.8.4 → 0.9.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/bin/cli.js +30426 -29237
- package/dist/bin/{jiti-DDHyYNLW.js → jiti-B26uDQuv.js} +2 -2
- package/dist/bin/renovate-CEC0BhMB.js +1 -0
- package/dist/bin/shared-Ch5JsD6s.js +8 -0
- package/dist/bin/shared2-Dhjk_Okb.js +1 -0
- package/dist/bin/web-tree-sitter.wasm +0 -0
- package/dist/lib/data/license-urls.js +2904 -0
- package/dist/lib/file-matching.js +5 -2
- package/dist/lib/log.d.ts +0 -1
- package/dist/lib/metadata-types.d.ts +16 -9
- package/dist/lib/metadata.d.ts +0 -1
- package/dist/lib/metadata.js +5 -5
- package/dist/lib/package.js +1 -1
- package/dist/lib/parsers/configparser-parser.js +14 -12
- package/dist/lib/parsers/gemspec-parser.js +41 -42
- package/dist/lib/parsers/go-mod-parser.js +51 -45
- package/dist/lib/parsers/makefile-config-parser.js +7 -6
- package/dist/lib/parsers/properties-parser.js +1 -1
- package/dist/lib/parsers/rfc822-header-parser.js +8 -6
- package/dist/lib/parsers/setup-py-parser.js +28 -24
- package/dist/lib/source.d.ts +6 -2
- package/dist/lib/sources/arduino-library-properties.d.ts +0 -1
- package/dist/lib/sources/arduino-library-properties.js +6 -7
- package/dist/lib/sources/cinder-cinderblock-xml.d.ts +0 -1
- package/dist/lib/sources/cinder-cinderblock-xml.js +5 -5
- package/dist/lib/sources/code-stats.d.ts +3 -2
- package/dist/lib/sources/codemeta-json.d.ts +0 -1
- package/dist/lib/sources/codemeta-json.js +21 -20
- package/dist/lib/sources/dependency-updates.d.ts +17 -8
- package/dist/lib/sources/dependency-updates.js +38 -34
- package/dist/lib/sources/file-stats.d.ts +7 -4
- package/dist/lib/sources/git-config.d.ts +0 -1
- package/dist/lib/sources/git-stats.d.ts +47 -24
- package/dist/lib/sources/git-stats.js +51 -33
- package/dist/lib/sources/github-actions.d.ts +0 -1
- package/dist/lib/sources/github-actions.js +4 -3
- package/dist/lib/sources/github.d.ts +156 -78
- package/dist/lib/sources/github.js +11 -8
- package/dist/lib/sources/go-go-mod.d.ts +0 -1
- package/dist/lib/sources/go-goreleaser-yaml.d.ts +0 -1
- package/dist/lib/sources/go-goreleaser-yaml.js +5 -3
- package/dist/lib/sources/java-pom-xml.d.ts +0 -1
- package/dist/lib/sources/java-pom-xml.js +12 -12
- package/dist/lib/sources/license-file.d.ts +0 -1
- package/dist/lib/sources/metadata-file.d.ts +0 -1
- package/dist/lib/sources/metadata-file.js +9 -10
- package/dist/lib/sources/metascope.d.ts +9 -5
- package/dist/lib/sources/node-npm-registry.d.ts +21 -11
- package/dist/lib/sources/node-npm-registry.js +12 -6
- package/dist/lib/sources/node-package-json.d.ts +0 -1
- package/dist/lib/sources/obsidian-plugin-manifest-json.d.ts +17 -9
- package/dist/lib/sources/obsidian-plugin-manifest-json.js +2 -2
- package/dist/lib/sources/obsidian-plugin-registry.d.ts +3 -2
- package/dist/lib/sources/obsidian-plugin-registry.js +2 -1
- package/dist/lib/sources/openframeworks-addon-config-mk.d.ts +0 -1
- package/dist/lib/sources/openframeworks-install-xml.d.ts +0 -1
- package/dist/lib/sources/openframeworks-install-xml.js +3 -3
- package/dist/lib/sources/processing-library-properties.d.ts +0 -1
- package/dist/lib/sources/processing-library-properties.js +9 -10
- package/dist/lib/sources/processing-sketch-properties.d.ts +0 -1
- package/dist/lib/sources/processing-sketch-properties.js +13 -20
- package/dist/lib/sources/publiccode-yaml.d.ts +0 -1
- package/dist/lib/sources/publiccode-yaml.js +61 -58
- package/dist/lib/sources/python-pkg-info.d.ts +0 -1
- package/dist/lib/sources/python-pkg-info.js +6 -5
- package/dist/lib/sources/python-pypi-registry.d.ts +21 -11
- package/dist/lib/sources/python-pypi-registry.js +23 -16
- package/dist/lib/sources/python-pyproject-toml.d.ts +0 -1
- package/dist/lib/sources/python-setup-cfg.d.ts +2 -3
- package/dist/lib/sources/python-setup-cfg.js +10 -9
- package/dist/lib/sources/python-setup-py.d.ts +0 -1
- package/dist/lib/sources/readme-file.d.ts +0 -1
- package/dist/lib/sources/readme-file.js +4 -3
- package/dist/lib/sources/ruby-gemspec.d.ts +0 -1
- package/dist/lib/sources/rust-cargo-toml.d.ts +0 -1
- package/dist/lib/sources/rust-cargo-toml.js +1 -1
- package/dist/lib/sources/xcode-info-plist.d.ts +0 -1
- package/dist/lib/sources/xcode-info-plist.js +29 -31
- package/dist/lib/sources/xcode-project-pbxproj.d.ts +0 -1
- package/dist/lib/sources/xcode-project-pbxproj.js +17 -16
- package/dist/lib/templates/codemeta-json.d.ts +1 -0
- package/dist/lib/templates/codemeta.d.ts +1 -0
- package/dist/lib/templates/codemeta.js +98 -89
- package/dist/lib/templates/frontmatter.d.ts +2 -1
- package/dist/lib/templates/frontmatter.js +1 -1
- package/dist/lib/templates/index.d.ts +2 -1
- package/dist/lib/templates/index.js +1 -1
- package/dist/lib/templates/metadata.d.ts +1 -0
- package/dist/lib/templates/project.d.ts +1 -0
- package/dist/lib/utilities/codemeta-helpers.js +14 -13
- package/dist/lib/utilities/fetch.js +18 -2
- package/dist/lib/utilities/formatting.js +1 -1
- package/dist/lib/utilities/github.js +2 -2
- package/dist/lib/utilities/license-identification.d.ts +9 -4
- package/dist/lib/utilities/license-identification.js +37 -23
- package/dist/lib/utilities/template-helpers.d.ts +7 -5
- package/dist/lib/utilities/template-helpers.js +15 -14
- package/dist/lib/utilities/tree-sitter-wasm.d.ts +0 -1
- package/dist/lib/utilities/tree-sitter-wasm.js +1 -1
- package/package.json +18 -17
- package/readme.md +13 -11
- package/dist/bin/renovate-CpDMbQZd.js +0 -1
- package/dist/bin/shared-Dix5HPlG.js +0 -6
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { splitCommaSeparated } from "../utilities/template-helpers.js";
|
|
2
2
|
import { getPythonLanguage, initParser } from "../utilities/tree-sitter-wasm.js";
|
|
3
3
|
//#region src/lib/parsers/setup-py-parser.ts
|
|
4
|
-
const STRING_PREFIX_REGEX = /^[bfru]*/
|
|
4
|
+
const STRING_PREFIX_REGEX = /^[bfru]*/iv;
|
|
5
5
|
/** Filter nulls from web-tree-sitter's `namedChildren` array. */
|
|
6
6
|
function children(node) {
|
|
7
7
|
return node.namedChildren.filter((c) => c !== null);
|
|
@@ -65,7 +65,7 @@ function extractStringDict(node) {
|
|
|
65
65
|
if (!key || !value) continue;
|
|
66
66
|
const k = extractString(key);
|
|
67
67
|
const v = extractString(value);
|
|
68
|
-
if (k && v) result[k] = v;
|
|
68
|
+
if (k !== void 0 && k !== "" && v !== void 0 && v !== "") result[k] = v;
|
|
69
69
|
}
|
|
70
70
|
return result;
|
|
71
71
|
}
|
|
@@ -79,7 +79,7 @@ function extractStringListDict(node) {
|
|
|
79
79
|
const value = pair.childForFieldName("value");
|
|
80
80
|
if (!key || !value) continue;
|
|
81
81
|
const k = extractString(key);
|
|
82
|
-
if (k) result[k] = extractStringList(value);
|
|
82
|
+
if (k !== void 0 && k !== "") result[k] = extractStringList(value);
|
|
83
83
|
}
|
|
84
84
|
return result;
|
|
85
85
|
}
|
|
@@ -127,30 +127,34 @@ async function parseSetupPy(source) {
|
|
|
127
127
|
if (value !== void 0) Object.assign(data, { [argumentName]: value });
|
|
128
128
|
continue;
|
|
129
129
|
}
|
|
130
|
-
|
|
131
|
-
case "classifiers":
|
|
132
|
-
data.classifiers = extractStringList(valueNode);
|
|
133
|
-
break;
|
|
134
|
-
case "extras_require":
|
|
135
|
-
data.extras_require = extractStringListDict(valueNode);
|
|
136
|
-
break;
|
|
137
|
-
case "install_requires":
|
|
138
|
-
data.install_requires = extractStringList(valueNode);
|
|
139
|
-
break;
|
|
140
|
-
case "keywords":
|
|
141
|
-
if (valueNode.type === "list" || valueNode.type === "tuple") data.keywords = extractStringList(valueNode);
|
|
142
|
-
else {
|
|
143
|
-
const string_ = extractString(valueNode);
|
|
144
|
-
if (string_) data.keywords = splitCommaSeparated(string_);
|
|
145
|
-
}
|
|
146
|
-
break;
|
|
147
|
-
case "project_urls":
|
|
148
|
-
data.project_urls = extractStringDict(valueNode);
|
|
149
|
-
break;
|
|
150
|
-
}
|
|
130
|
+
applyListAttribute(data, argumentName, valueNode);
|
|
151
131
|
}
|
|
152
132
|
return data;
|
|
153
133
|
}
|
|
134
|
+
/** Apply a list/dict-valued setup() keyword argument to the data object. */
|
|
135
|
+
function applyListAttribute(data, argumentName, valueNode) {
|
|
136
|
+
switch (argumentName) {
|
|
137
|
+
case "classifiers":
|
|
138
|
+
data.classifiers = extractStringList(valueNode);
|
|
139
|
+
break;
|
|
140
|
+
case "extras_require":
|
|
141
|
+
data.extras_require = extractStringListDict(valueNode);
|
|
142
|
+
break;
|
|
143
|
+
case "install_requires":
|
|
144
|
+
data.install_requires = extractStringList(valueNode);
|
|
145
|
+
break;
|
|
146
|
+
case "keywords":
|
|
147
|
+
if (valueNode.type === "list" || valueNode.type === "tuple") data.keywords = extractStringList(valueNode);
|
|
148
|
+
else {
|
|
149
|
+
const string_ = extractString(valueNode);
|
|
150
|
+
if (string_ !== void 0 && string_ !== "") data.keywords = splitCommaSeparated(string_);
|
|
151
|
+
}
|
|
152
|
+
break;
|
|
153
|
+
case "project_urls":
|
|
154
|
+
data.project_urls = extractStringDict(valueNode);
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
154
158
|
/**
|
|
155
159
|
* Recursively find the setup() or setuptools.setup() call in the AST.
|
|
156
160
|
*/
|
package/dist/lib/source.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import "./metadata-types.js";
|
|
1
2
|
//#region src/lib/source.d.ts
|
|
2
3
|
/**
|
|
3
4
|
* A value that is either a single item or an array of items.
|
|
@@ -10,8 +11,11 @@ type OneOrMany<T> = T | T[];
|
|
|
10
11
|
* @template E The shape of any additional computed/derived fields.
|
|
11
12
|
*/
|
|
12
13
|
type SourceRecord<D extends Record<string, unknown> = Record<string, unknown>, E extends Record<string, unknown> = Record<string, unknown>> = {
|
|
13
|
-
/** Primary structured data from this source. */
|
|
14
|
-
|
|
14
|
+
/** Primary structured data from this source. */
|
|
15
|
+
data: D;
|
|
16
|
+
/** Additional computed or derived fields not present in the raw source. */
|
|
17
|
+
extra?: E;
|
|
18
|
+
/** The file path or URL from which the data was derived. */
|
|
15
19
|
source: string;
|
|
16
20
|
};
|
|
17
21
|
//#endregion
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { OneOrMany, SourceRecord } from "../source.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
|
|
4
3
|
//#region src/lib/sources/arduino-library-properties.d.ts
|
|
5
4
|
declare const arduinoLibraryPropertiesSchema: z.ZodObject<{
|
|
6
5
|
architectures: z.ZodDefault<z.ZodPreprocess<z.ZodArray<z.ZodString>>>;
|
|
@@ -29,8 +29,7 @@ const CANONICAL_CATEGORIES = [
|
|
|
29
29
|
"Uncategorized"
|
|
30
30
|
];
|
|
31
31
|
/** Map from letters-only lowercase to canonical category form. */
|
|
32
|
-
const CATEGORY_MAP = new Map(CANONICAL_CATEGORIES.map((cat) => [cat.replaceAll(/[^a-z]/
|
|
33
|
-
CATEGORY_MAP.set("sensor", "Sensors");
|
|
32
|
+
const CATEGORY_MAP = new Map([...CANONICAL_CATEGORIES.map((cat) => [cat.replaceAll(/[^a-z]/giv, "").toLowerCase(), cat]), ["sensor", "Sensors"]]);
|
|
34
33
|
const arduinoLibraryPropertiesSchema = z.object({
|
|
35
34
|
/** Comma-separated architecture identifiers, or ["*"] for all. */
|
|
36
35
|
architectures: stringArray,
|
|
@@ -76,7 +75,7 @@ function parse(content) {
|
|
|
76
75
|
category: normalizeCategory(get(raw, "category")),
|
|
77
76
|
depends: parseDependencies(get(raw, "depends") ?? get(raw, "dependencies") ?? ""),
|
|
78
77
|
email: nonEmpty(get(raw, "email")),
|
|
79
|
-
includes: includesValue ? splitCommaSeparated(includesValue) : [],
|
|
78
|
+
includes: includesValue !== void 0 && includesValue !== "" ? splitCommaSeparated(includesValue) : [],
|
|
80
79
|
license: nonEmpty(get(raw, "license")),
|
|
81
80
|
maintainer: parsePersonList(get(raw, "maintainer") ?? "")[0],
|
|
82
81
|
name: nonEmpty(get(raw, "name")),
|
|
@@ -109,10 +108,10 @@ function normalizeCategory(value) {
|
|
|
109
108
|
const trimmed = value.trim();
|
|
110
109
|
if (trimmed.length === 0) return;
|
|
111
110
|
for (const part of trimmed.split(",")) {
|
|
112
|
-
const key = part.replaceAll(/[^a-z]/
|
|
111
|
+
const key = part.replaceAll(/[^a-z]/giv, "").toLowerCase();
|
|
113
112
|
if (key.length === 0) continue;
|
|
114
113
|
const canonical = CATEGORY_MAP.get(key);
|
|
115
|
-
if (canonical) return canonical;
|
|
114
|
+
if (canonical !== void 0) return canonical;
|
|
116
115
|
}
|
|
117
116
|
}
|
|
118
117
|
/**
|
|
@@ -214,10 +213,10 @@ const arduinoLibraryPropertiesSource = defineSource({
|
|
|
214
213
|
key: "arduinoLibraryProperties",
|
|
215
214
|
async parse(input, context) {
|
|
216
215
|
const content = await readFile(resolve(context.options.path, input), "utf8");
|
|
217
|
-
|
|
216
|
+
return isArduinoLibraryProperties(content) ? {
|
|
218
217
|
data: parse(content),
|
|
219
218
|
source: input
|
|
220
|
-
};
|
|
219
|
+
} : void 0;
|
|
221
220
|
},
|
|
222
221
|
phase: 1
|
|
223
222
|
});
|
|
@@ -106,7 +106,7 @@ function parseOperatingSystems(block) {
|
|
|
106
106
|
for (const support of ensureArray(block.supports)) {
|
|
107
107
|
if (!is.plainObject(support)) continue;
|
|
108
108
|
const os = getAttribute(support, "os");
|
|
109
|
-
if (os) {
|
|
109
|
+
if (os !== void 0) {
|
|
110
110
|
const mapped = OS_MAP[os.toLowerCase()] ?? os;
|
|
111
111
|
if (!seen.has(mapped)) {
|
|
112
112
|
seen.add(mapped);
|
|
@@ -121,9 +121,9 @@ function parseOperatingSystems(block) {
|
|
|
121
121
|
*/
|
|
122
122
|
function parseDependencies(block) {
|
|
123
123
|
const results = [];
|
|
124
|
-
for (const
|
|
125
|
-
if (typeof
|
|
126
|
-
const trimmed =
|
|
124
|
+
for (const dependency of ensureArray(block.requires)) {
|
|
125
|
+
if (typeof dependency !== "string") continue;
|
|
126
|
+
const trimmed = dependency.trim();
|
|
127
127
|
if (trimmed.length > 0) results.push(trimmed);
|
|
128
128
|
}
|
|
129
129
|
return results;
|
|
@@ -135,7 +135,7 @@ const cinderCinderblockXmlSource = defineSource({
|
|
|
135
135
|
key: "cinderCinderblockXml",
|
|
136
136
|
async parse(input, context) {
|
|
137
137
|
const data = parse(await readFile(resolve(context.options.path, input), "utf8"));
|
|
138
|
-
|
|
138
|
+
return data === void 0 ? void 0 : {
|
|
139
139
|
data,
|
|
140
140
|
source: input
|
|
141
141
|
};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { OneOrMany, SourceRecord } from "../source.js";
|
|
2
2
|
import { Language, LanguageInfo } from "@kitschpatrol/tokei";
|
|
3
|
-
|
|
4
3
|
//#region src/lib/sources/code-stats.d.ts
|
|
5
4
|
type CodeStatsTotals = Omit<LanguageInfo, 'language' | 'reports'> & {
|
|
6
5
|
languages: Language[];
|
|
7
6
|
};
|
|
8
7
|
type CodeStatsFields = {
|
|
9
|
-
/** Per-language line count perLanguage, sorted by lines of code descending. */
|
|
8
|
+
/** Per-language line count perLanguage, sorted by lines of code descending. */
|
|
9
|
+
perLanguage?: LanguageInfo[];
|
|
10
|
+
/** Aggregate line counts across all languages. */
|
|
10
11
|
total?: CodeStatsTotals;
|
|
11
12
|
};
|
|
12
13
|
type CodeStatsData = OneOrMany<SourceRecord<CodeStatsFields>> | undefined;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { OneOrMany, SourceRecord } from "../source.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
|
|
4
3
|
//#region src/lib/sources/codemeta-json.d.ts
|
|
5
4
|
declare const codeMetaJsonDataSchema: z.ZodObject<{
|
|
6
5
|
applicationCategory: z.ZodOptional<z.ZodPreprocess<z.ZodOptional<z.ZodPreprocess<z.ZodOptional<z.ZodString>>>>>;
|
|
@@ -30,12 +30,12 @@ import { z } from "zod";
|
|
|
30
30
|
*/
|
|
31
31
|
const codeMetaString = z.preprocess((value) => {
|
|
32
32
|
if (typeof value === "string") return value;
|
|
33
|
-
|
|
33
|
+
return is.plainObject(value) && typeof value["@value"] === "string" ? value["@value"] : void 0;
|
|
34
34
|
}, nonEmptyString).optional();
|
|
35
35
|
/** Same as codeMetaString but semantically a URL field. */
|
|
36
36
|
const codeMetaUrl = z.preprocess((value) => {
|
|
37
37
|
if (typeof value === "string") return value;
|
|
38
|
-
|
|
38
|
+
return is.plainObject(value) && typeof value["@value"] === "string" ? value["@value"] : void 0;
|
|
39
39
|
}, optionalUrl).optional();
|
|
40
40
|
/**
|
|
41
41
|
* A string array that handles CodeMeta's polymorphic inputs:
|
|
@@ -48,7 +48,8 @@ const codeMetaUrl = z.preprocess((value) => {
|
|
|
48
48
|
const codeMetaStringArray = z.preprocess((value) => {
|
|
49
49
|
if (value === void 0 || value === null) return;
|
|
50
50
|
if (typeof value === "string") return value.includes(",") ? splitCommaSeparated(value) : [value];
|
|
51
|
-
if (Array.isArray(value)) return
|
|
51
|
+
if (!Array.isArray(value)) return;
|
|
52
|
+
return value.map((item) => {
|
|
52
53
|
if (typeof item === "string") return item.trim();
|
|
53
54
|
if (is.plainObject(item)) return typeof item.name === "string" ? item.name.trim() : "";
|
|
54
55
|
log.warn("Invalid type found in codemeta json parser");
|
|
@@ -60,10 +61,9 @@ const codeMetaStringArray = z.preprocess((value) => {
|
|
|
60
61
|
*/
|
|
61
62
|
const codeMetaLicense = z.preprocess((value) => {
|
|
62
63
|
if (typeof value === "string") return value;
|
|
63
|
-
if (Array.isArray(value))
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
64
|
+
if (!Array.isArray(value)) return;
|
|
65
|
+
const filtered = value.filter((l) => typeof l === "string");
|
|
66
|
+
return filtered.length > 0 ? filtered : void 0;
|
|
67
67
|
}, z.union([z.string(), z.array(z.string())]).optional()).optional();
|
|
68
68
|
const codeMetaPersonOrOrgSchema = z.object({
|
|
69
69
|
affiliation: nonEmptyString,
|
|
@@ -97,7 +97,8 @@ function preprocessPersonOrOrg(value) {
|
|
|
97
97
|
if (typeof value.url === "string") result.url = value.url;
|
|
98
98
|
if (typeof value.affiliation === "string") result.affiliation = value.affiliation;
|
|
99
99
|
else if (is.plainObject(value.affiliation) && typeof value.affiliation.name === "string") result.affiliation = value.affiliation.name;
|
|
100
|
-
|
|
100
|
+
const identifyingValue = result.name ?? result.givenName ?? result.familyName ?? result.email;
|
|
101
|
+
if (identifyingValue !== void 0 && identifyingValue !== "") return result;
|
|
101
102
|
}
|
|
102
103
|
/**
|
|
103
104
|
* A person/org array that normalizes single values to arrays, and each element
|
|
@@ -121,12 +122,13 @@ const codeMetaDependencySchema = z.object({
|
|
|
121
122
|
function preprocessDependency(value) {
|
|
122
123
|
if (typeof value === "string") return { name: value };
|
|
123
124
|
if (!is.plainObject(value)) return;
|
|
124
|
-
const
|
|
125
|
-
if (typeof value.name === "string")
|
|
126
|
-
if (typeof value.identifier === "string")
|
|
127
|
-
if (typeof value.version === "string")
|
|
128
|
-
if (typeof value.runtimePlatform === "string")
|
|
129
|
-
|
|
125
|
+
const dependency = {};
|
|
126
|
+
if (typeof value.name === "string") dependency.name = value.name;
|
|
127
|
+
if (typeof value.identifier === "string") dependency.identifier = value.identifier;
|
|
128
|
+
if (typeof value.version === "string") dependency.version = value.version;
|
|
129
|
+
if (typeof value.runtimePlatform === "string") dependency.runtimePlatform = value.runtimePlatform;
|
|
130
|
+
const dependencyKey = dependency.name ?? dependency.identifier;
|
|
131
|
+
if (dependencyKey !== void 0 && dependencyKey !== "") return dependency;
|
|
130
132
|
}
|
|
131
133
|
/**
|
|
132
134
|
* A dependency array that normalizes single values to arrays, and each element
|
|
@@ -148,10 +150,9 @@ const codeMetaJsonDataSchema = z.object({
|
|
|
148
150
|
copyrightHolder: codeMetaPersonArray,
|
|
149
151
|
copyrightYear: z.preprocess((v) => {
|
|
150
152
|
if (typeof v === "number") return v;
|
|
151
|
-
if (typeof v
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
153
|
+
if (typeof v !== "string") return;
|
|
154
|
+
const parsed = Number.parseInt(v, 10);
|
|
155
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
155
156
|
}, z.number().optional()).optional(),
|
|
156
157
|
dateCreated: codeMetaString,
|
|
157
158
|
dateModified: codeMetaString,
|
|
@@ -208,7 +209,7 @@ function migrateV1Properties(raw) {
|
|
|
208
209
|
for (const [key, value] of Object.entries(raw)) {
|
|
209
210
|
if (key.startsWith("@")) continue;
|
|
210
211
|
const mappedKey = v1PropertyMap[key] ?? key;
|
|
211
|
-
if (!(mappedKey
|
|
212
|
+
if (!Object.hasOwn(result, mappedKey)) result[mappedKey] = value;
|
|
212
213
|
}
|
|
213
214
|
return result;
|
|
214
215
|
}
|
|
@@ -219,7 +220,7 @@ const codemetaJsonSource = defineSource({
|
|
|
219
220
|
key: "codemetaJson",
|
|
220
221
|
async parse(input, context) {
|
|
221
222
|
const data = parse(await readFile(resolve(context.options.path, input), "utf8"));
|
|
222
|
-
|
|
223
|
+
return data === void 0 ? void 0 : {
|
|
223
224
|
data,
|
|
224
225
|
source: input
|
|
225
226
|
};
|
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
import { OneOrMany, SourceRecord } from "../source.js";
|
|
2
|
-
|
|
3
2
|
//#region src/lib/sources/dependency-updates.d.ts
|
|
4
3
|
type DependencyUpdatesPackage = {
|
|
5
|
-
/** Human-readable age of the update (e.g. "3 months"). */
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
/** Human-readable age of the update (e.g. "3 months"). */
|
|
5
|
+
age?: string;
|
|
6
|
+
/** Additional info about the update (e.g. deprecation notice). */
|
|
7
|
+
info?: string;
|
|
8
|
+
/** Package name. */
|
|
9
|
+
name: string;
|
|
10
|
+
/** Latest available version. */
|
|
11
|
+
new: string;
|
|
12
|
+
/** Currently installed version. */
|
|
9
13
|
old: string;
|
|
10
14
|
};
|
|
11
15
|
type DependencyUpdatesFields = {
|
|
12
|
-
/** Packages with available major version updates. */
|
|
13
|
-
|
|
16
|
+
/** Packages with available major version updates. */
|
|
17
|
+
major?: DependencyUpdatesPackage[];
|
|
18
|
+
/** Packages with available minor version updates. */
|
|
19
|
+
minor?: DependencyUpdatesPackage[];
|
|
20
|
+
/** Packages with available patch version updates. */
|
|
14
21
|
patch?: DependencyUpdatesPackage[];
|
|
15
22
|
};
|
|
16
23
|
type DependencyUpdatesExtra = {
|
|
17
|
-
/** Total dependency staleness in libyears. */
|
|
24
|
+
/** Total dependency staleness in libyears. */
|
|
25
|
+
libyears?: number;
|
|
26
|
+
/** Total number of outdated packages. */
|
|
18
27
|
total?: number;
|
|
19
28
|
};
|
|
20
29
|
type DependencyUpdatesData = OneOrMany<SourceRecord<DependencyUpdatesFields, DependencyUpdatesExtra>> | undefined;
|
|
@@ -4,14 +4,14 @@ import { z } from "zod";
|
|
|
4
4
|
import { coerce, diff } from "semver";
|
|
5
5
|
import { updates } from "updates";
|
|
6
6
|
//#region src/lib/sources/dependency-updates.ts
|
|
7
|
-
const AGE_VALUE_UNIT_REGEX = /^(\d+)\s+(\w+)
|
|
8
|
-
const
|
|
7
|
+
const AGE_VALUE_UNIT_REGEX = /^(\d+)\s+(\w+)$/v;
|
|
8
|
+
const dependencySchema = z.object({
|
|
9
9
|
age: z.string().optional(),
|
|
10
10
|
info: z.string().optional(),
|
|
11
11
|
new: z.string(),
|
|
12
12
|
old: z.string()
|
|
13
13
|
});
|
|
14
|
-
const updatesOutputSchema = z.object({ results: z.record(z.string(), z.record(z.string(), z.record(z.string(),
|
|
14
|
+
const updatesOutputSchema = z.object({ results: z.record(z.string(), z.record(z.string(), z.record(z.string(), dependencySchema))) });
|
|
15
15
|
/**
|
|
16
16
|
* Parse an age string from the `updates` CLI (via the `timerel` library) into
|
|
17
17
|
* fractional years.
|
|
@@ -24,7 +24,9 @@ function parseAgeToYears(age) {
|
|
|
24
24
|
const match = AGE_VALUE_UNIT_REGEX.exec(age.trim());
|
|
25
25
|
if (!match) return 0;
|
|
26
26
|
const value = Number(match[1]);
|
|
27
|
-
|
|
27
|
+
const unit = match[2];
|
|
28
|
+
if (unit === void 0) return 0;
|
|
29
|
+
switch (unit) {
|
|
28
30
|
case "day":
|
|
29
31
|
case "days": return value / 365.25;
|
|
30
32
|
case "hour":
|
|
@@ -51,11 +53,33 @@ function classifyBump(oldVersion, newVersion) {
|
|
|
51
53
|
const newSemver = coerce(newVersion);
|
|
52
54
|
if (!oldSemver || !newSemver) return "major";
|
|
53
55
|
const result = diff(oldSemver, newSemver);
|
|
54
|
-
if (
|
|
55
|
-
if (result
|
|
56
|
-
if (result
|
|
56
|
+
if (result === null) return "major";
|
|
57
|
+
if (result === "premajor" || result.startsWith("major")) return "major";
|
|
58
|
+
if (result === "preminor" || result.startsWith("minor")) return "minor";
|
|
57
59
|
return "patch";
|
|
58
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Classify each dependency in a group into the appropriate bucket, skipping
|
|
63
|
+
* `@types/node` and packages already seen. Returns the libyears contributed by
|
|
64
|
+
* this group.
|
|
65
|
+
*/
|
|
66
|
+
function collectDependencyUpdates(dependencyGroup, buckets, seen) {
|
|
67
|
+
let libyears = 0;
|
|
68
|
+
for (const [name, dependency] of Object.entries(dependencyGroup)) {
|
|
69
|
+
if (name === "@types/node" || seen.has(name)) continue;
|
|
70
|
+
seen.add(name);
|
|
71
|
+
if (dependency.age !== void 0 && dependency.age !== "") libyears += parseAgeToYears(dependency.age);
|
|
72
|
+
const packageStatus = {
|
|
73
|
+
name,
|
|
74
|
+
new: dependency.new,
|
|
75
|
+
old: dependency.old
|
|
76
|
+
};
|
|
77
|
+
if (dependency.age !== void 0 && dependency.age !== "") packageStatus.age = dependency.age;
|
|
78
|
+
if (dependency.info !== void 0 && dependency.info !== "") packageStatus.info = dependency.info;
|
|
79
|
+
buckets[classifyBump(dependency.old, dependency.new)].push(packageStatus);
|
|
80
|
+
}
|
|
81
|
+
return libyears;
|
|
82
|
+
}
|
|
59
83
|
const dependencyUpdatesSource = defineSource({
|
|
60
84
|
async discover(context) {
|
|
61
85
|
return [context.options.path];
|
|
@@ -74,35 +98,15 @@ const dependencyUpdatesSource = defineSource({
|
|
|
74
98
|
log.debug("No dependency files found for updates analysis.");
|
|
75
99
|
return;
|
|
76
100
|
}
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
101
|
+
const buckets = {
|
|
102
|
+
major: [],
|
|
103
|
+
minor: [],
|
|
104
|
+
patch: []
|
|
105
|
+
};
|
|
80
106
|
const seen = /* @__PURE__ */ new Set();
|
|
81
107
|
let libyears = 0;
|
|
82
|
-
for (const mode of Object.values(parsed.results)) for (const
|
|
83
|
-
|
|
84
|
-
if (seen.has(name)) continue;
|
|
85
|
-
seen.add(name);
|
|
86
|
-
if (dep.age) libyears += parseAgeToYears(dep.age);
|
|
87
|
-
const packageStatus = {
|
|
88
|
-
name,
|
|
89
|
-
new: dep.new,
|
|
90
|
-
old: dep.old
|
|
91
|
-
};
|
|
92
|
-
if (dep.age) packageStatus.age = dep.age;
|
|
93
|
-
if (dep.info) packageStatus.info = dep.info;
|
|
94
|
-
switch (classifyBump(dep.old, dep.new)) {
|
|
95
|
-
case "major":
|
|
96
|
-
major.push(packageStatus);
|
|
97
|
-
break;
|
|
98
|
-
case "minor":
|
|
99
|
-
minor.push(packageStatus);
|
|
100
|
-
break;
|
|
101
|
-
case "patch":
|
|
102
|
-
patch.push(packageStatus);
|
|
103
|
-
break;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
108
|
+
for (const mode of Object.values(parsed.results)) for (const dependencyGroup of Object.values(mode)) libyears += collectDependencyUpdates(dependencyGroup, buckets, seen);
|
|
109
|
+
const { major, minor, patch } = buckets;
|
|
106
110
|
return {
|
|
107
111
|
data: {
|
|
108
112
|
major,
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { OneOrMany, SourceRecord } from "../source.js";
|
|
2
|
-
|
|
3
2
|
//#region src/lib/sources/file-stats.d.ts
|
|
4
3
|
type FileStats = {
|
|
5
|
-
/** Name of repo folder, possibly useful as a name fallback */
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
/** Name of repo folder, possibly useful as a name fallback */
|
|
5
|
+
folderName?: string;
|
|
6
|
+
/** Total number of directories (recursive). */
|
|
7
|
+
totalDirectoryCount?: number;
|
|
8
|
+
/** Total number of files (recursive). */
|
|
9
|
+
totalFileCount?: number;
|
|
10
|
+
/** Total size of all files in bytes. */
|
|
8
11
|
totalSizeBytes?: number;
|
|
9
12
|
};
|
|
10
13
|
type FileStatsData = OneOrMany<SourceRecord<FileStats>> | undefined;
|
|
@@ -1,33 +1,56 @@
|
|
|
1
1
|
import { OneOrMany, SourceRecord } from "../source.js";
|
|
2
|
-
|
|
3
2
|
//#region src/lib/sources/git-stats.d.ts
|
|
4
3
|
type GitStatsInfo = {
|
|
5
|
-
/** Total number of local branches. */
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
/** Total number of local branches. */
|
|
5
|
+
branchCount?: number;
|
|
6
|
+
/** Name of the currently checked-out branch. */
|
|
7
|
+
branchCurrent?: string;
|
|
8
|
+
/** Total number of commits in the current branch. */
|
|
9
|
+
commitCount?: number;
|
|
10
|
+
/** ISO 8601 date of the repository's first commit. */
|
|
11
|
+
commitDateFirst?: string;
|
|
12
|
+
/** ISO 8601 date of the most recent commit. */
|
|
13
|
+
commitDateLast?: string;
|
|
14
|
+
/** Number of unique commit author emails. */
|
|
15
|
+
contributorCount?: number;
|
|
16
|
+
/** Whether the repo uses Git LFS. */
|
|
17
|
+
hasLfs?: boolean;
|
|
18
|
+
/** Whether the working tree has no uncommitted changes. */
|
|
19
|
+
isClean?: boolean;
|
|
20
|
+
/** Whether the working tree has uncommitted changes. */
|
|
21
|
+
isDirty?: boolean;
|
|
22
|
+
/** Whether any remote is ahead of the local branch. */
|
|
23
|
+
isRemoteAhead?: boolean;
|
|
24
|
+
/** Number of configured remotes. */
|
|
25
|
+
remoteCount?: number;
|
|
26
|
+
/** Per-remote ahead/behind commit counts relative to HEAD. */
|
|
16
27
|
remoteStatus?: Record<string, {
|
|
17
28
|
ahead: number;
|
|
18
29
|
behind: number;
|
|
19
|
-
}>;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
}>;
|
|
31
|
+
/** Number of registered git submodules. */
|
|
32
|
+
submoduleCount?: number;
|
|
33
|
+
/** Total number of tags. */
|
|
34
|
+
tagCount?: number;
|
|
35
|
+
/** ISO 8601 date of the most recent tag. */
|
|
36
|
+
tagDateLatest?: string;
|
|
37
|
+
/** Name of the most recent tag. */
|
|
38
|
+
tagNameLatest?: string;
|
|
39
|
+
/** Number of tags matching a version pattern (e.g. v1.2.3). */
|
|
40
|
+
tagReleaseCount?: number;
|
|
41
|
+
/** ISO 8601 date of the most recent version tag. */
|
|
42
|
+
tagVersionDateLatest?: string;
|
|
43
|
+
/** Most recent version tag, without the leading "v". */
|
|
44
|
+
tagVersionLatest?: string;
|
|
45
|
+
/** Total commits ahead of all remotes combined. */
|
|
46
|
+
totalAhead?: number;
|
|
47
|
+
/** Total commits behind all remotes combined. */
|
|
48
|
+
totalBehind?: number;
|
|
49
|
+
/** Number of files tracked by git. */
|
|
50
|
+
trackedFileCount?: number;
|
|
51
|
+
/** Total size in bytes of all tracked files. */
|
|
52
|
+
trackedSizeBytes?: number;
|
|
53
|
+
/** Number of files with staged or unstaged changes. */
|
|
31
54
|
uncommittedFileCount?: number;
|
|
32
55
|
};
|
|
33
56
|
type GitStatsData = OneOrMany<SourceRecord<GitStatsInfo>> | undefined;
|