metascope 0.3.0 → 0.4.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/.DS_Store +0 -0
- package/dist/bin/cli.js +54 -29
- package/dist/lib/metadata-types.d.ts +2 -0
- package/dist/lib/metadata.js +3 -0
- package/dist/lib/package.js +1 -1
- package/dist/lib/sources/dependency-updates.js +4 -12
- package/dist/lib/sources/github-actions.d.ts +12 -0
- package/dist/lib/sources/github-actions.js +41 -0
- package/dist/lib/sources/github.js +2 -2
- package/dist/lib/sources/node-npm-registry.js +2 -2
- package/dist/lib/sources/obsidian-plugin-registry.js +2 -2
- package/dist/lib/sources/python-pypi-registry.js +1 -1
- package/dist/lib/sources/readme-file.d.ts +1 -0
- package/dist/lib/sources/readme-file.js +11 -3
- package/dist/lib/templates/frontmatter.d.ts +1 -1
- package/dist/lib/templates/index.d.ts +1 -1
- package/package.json +5 -4
|
@@ -7,6 +7,7 @@ import { FileStatsData } from "./sources/file-stats.js";
|
|
|
7
7
|
import { GitConfigData } from "./sources/git-config.js";
|
|
8
8
|
import { GitStatsData } from "./sources/git-stats.js";
|
|
9
9
|
import { GitHubData } from "./sources/github.js";
|
|
10
|
+
import { GitHubActionsData } from "./sources/github-actions.js";
|
|
10
11
|
import { GoGoModData } from "./sources/go-go-mod.js";
|
|
11
12
|
import { GoGoreleaserYamlData } from "./sources/go-goreleaser-yaml.js";
|
|
12
13
|
import { JavaPomXmlData } from "./sources/java-pom-xml.js";
|
|
@@ -47,6 +48,7 @@ type MetadataContext = {
|
|
|
47
48
|
fileStats: FileStatsData;
|
|
48
49
|
gitConfig: GitConfigData;
|
|
49
50
|
github: GitHubData;
|
|
51
|
+
githubActions: GitHubActionsData;
|
|
50
52
|
gitStats: GitStatsData;
|
|
51
53
|
goGoMod: GoGoModData;
|
|
52
54
|
goGoreleaserYaml: GoGoreleaserYamlData;
|
package/dist/lib/metadata.js
CHANGED
|
@@ -11,6 +11,7 @@ import { fileStatsSource } from "./sources/file-stats.js";
|
|
|
11
11
|
import { gitConfigSource } from "./sources/git-config.js";
|
|
12
12
|
import { gitStatsSource } from "./sources/git-stats.js";
|
|
13
13
|
import { githubSource } from "./sources/github.js";
|
|
14
|
+
import { githubActionsSource } from "./sources/github-actions.js";
|
|
14
15
|
import { goGoModSource } from "./sources/go-go-mod.js";
|
|
15
16
|
import { goGoreleaserYamlSource } from "./sources/go-goreleaser-yaml.js";
|
|
16
17
|
import { javaPomXmlSource } from "./sources/java-pom-xml.js";
|
|
@@ -56,6 +57,7 @@ const sources = [
|
|
|
56
57
|
cinderCinderblockXmlSource,
|
|
57
58
|
codemetaJsonSource,
|
|
58
59
|
gitConfigSource,
|
|
60
|
+
githubActionsSource,
|
|
59
61
|
goGoModSource,
|
|
60
62
|
goGoreleaserYamlSource,
|
|
61
63
|
javaPomXmlSource,
|
|
@@ -172,6 +174,7 @@ async function getMetadata(options) {
|
|
|
172
174
|
fileStats: void 0,
|
|
173
175
|
gitConfig: void 0,
|
|
174
176
|
github: void 0,
|
|
177
|
+
githubActions: void 0,
|
|
175
178
|
gitStats: void 0,
|
|
176
179
|
goGoMod: void 0,
|
|
177
180
|
goGoreleaserYaml: void 0,
|
package/dist/lib/package.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { log } from "../log.js";
|
|
2
2
|
import { defineSource } from "../source.js";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
import { readFileSync } from "node:fs";
|
|
5
3
|
import { exec } from "tinyexec";
|
|
6
4
|
import { z } from "zod";
|
|
7
5
|
import { fileURLToPath } from "node:url";
|
|
@@ -15,19 +13,13 @@ const depSchema = z.object({
|
|
|
15
13
|
});
|
|
16
14
|
const updatesOutputSchema = z.object({ results: z.record(z.string(), z.record(z.string(), z.record(z.string(), depSchema))) });
|
|
17
15
|
/**
|
|
18
|
-
* Resolve the path to the `updates` CLI binary
|
|
16
|
+
* Resolve the path to the `updates` CLI binary.
|
|
19
17
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* (where `import.meta.url` would point to the consumer's output, not to
|
|
23
|
-
* metascope's node_modules).
|
|
18
|
+
* Consumers that bundle metascope must externalize it (e.g. via `neverBundle`)
|
|
19
|
+
* so that `import.meta.resolve` can find the `updates` dependency.
|
|
24
20
|
*/
|
|
25
21
|
function resolveUpdatesBinary() {
|
|
26
|
-
|
|
27
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
28
|
-
const bin = typeof packageJson === "object" && packageJson !== null && "bin" in packageJson && typeof packageJson.bin === "string" ? packageJson.bin : void 0;
|
|
29
|
-
if (!bin) throw new Error("Could not resolve updates binary path");
|
|
30
|
-
return join(dirname(packageJsonPath), bin);
|
|
22
|
+
return fileURLToPath(import.meta.resolve("updates/dist/index.js"));
|
|
31
23
|
}
|
|
32
24
|
/**
|
|
33
25
|
* Parse an age string from the `updates` CLI (via the `timerel` library) into fractional years.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { OneOrMany, SourceRecord } from "../source.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/lib/sources/github-actions.d.ts
|
|
5
|
+
declare const githubActionSchema: z.ZodObject<{
|
|
6
|
+
file: z.ZodString;
|
|
7
|
+
name: z.ZodString;
|
|
8
|
+
}, z.core.$strip>;
|
|
9
|
+
type GitHubAction = z.infer<typeof githubActionSchema>;
|
|
10
|
+
type GitHubActionsData = OneOrMany<SourceRecord<GitHubAction>> | undefined;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { GitHubActionsData };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { getMatches } from "../file-matching.js";
|
|
2
|
+
import { formatPath } from "../utilities/formatting.js";
|
|
3
|
+
import { defineSource } from "../source.js";
|
|
4
|
+
import { readFile } from "node:fs/promises";
|
|
5
|
+
import { resolve } from "node:path";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { parse } from "yaml";
|
|
8
|
+
//#region src/lib/sources/github-actions.ts
|
|
9
|
+
/**
|
|
10
|
+
* Source for GitHub Actions workflow files.
|
|
11
|
+
*
|
|
12
|
+
* Discovers `.github/workflows/*.yml` and `*.yaml` files and extracts the
|
|
13
|
+
* workflow name and file path from each.
|
|
14
|
+
*/
|
|
15
|
+
const githubActionSchema = z.object({
|
|
16
|
+
file: z.string(),
|
|
17
|
+
name: z.string()
|
|
18
|
+
});
|
|
19
|
+
const githubActionsSource = defineSource({
|
|
20
|
+
async discover(context) {
|
|
21
|
+
return getMatches(context.options, [".github/workflows/*.{yml,yaml}"]);
|
|
22
|
+
},
|
|
23
|
+
key: "githubActions",
|
|
24
|
+
async parse(input, context) {
|
|
25
|
+
const parsed = parse(await readFile(resolve(context.options.path, input), "utf8"));
|
|
26
|
+
if (typeof parsed !== "object" || parsed === null || !("name" in parsed)) return;
|
|
27
|
+
const { name } = parsed;
|
|
28
|
+
if (typeof name !== "string") return;
|
|
29
|
+
const file = formatPath(resolve(context.options.path, input), context.options.path, context.options.absolute);
|
|
30
|
+
return {
|
|
31
|
+
data: githubActionSchema.parse({
|
|
32
|
+
file,
|
|
33
|
+
name
|
|
34
|
+
}),
|
|
35
|
+
source: input
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
phase: 1
|
|
39
|
+
});
|
|
40
|
+
//#endregion
|
|
41
|
+
export { githubActionsSource };
|
|
@@ -361,12 +361,12 @@ function mapRepoData(data, extras) {
|
|
|
361
361
|
const githubSource = defineSource({
|
|
362
362
|
async discover(context) {
|
|
363
363
|
if (context.options.offline) {
|
|
364
|
-
log.
|
|
364
|
+
log.debug("Skipping GitHub data source since we're in offline mode");
|
|
365
365
|
return [];
|
|
366
366
|
}
|
|
367
367
|
let gitRemotes = ensureArray(context.metadata?.gitConfig).map((config) => config.data.remote).filter((remote) => remote !== void 0);
|
|
368
368
|
if (gitRemotes.length === 0 && !context.completedSources?.has("gitConfig")) {
|
|
369
|
-
log.
|
|
369
|
+
log.debug(`Missing gitConfig in source context metadata for ${context.options.path}, extracting it now...`);
|
|
370
370
|
gitRemotes = ensureArray(await gitConfigSource.extract(context)).map((config) => config.data.remote).filter((remote) => remote !== void 0);
|
|
371
371
|
}
|
|
372
372
|
return [...new Set(gitRemotes.map((config) => getGitHubRemoteFromConfig(config)).filter((remote) => remote !== void 0).map((remote) => `${remote.owner}/${remote.repo}`))];
|
|
@@ -10,12 +10,12 @@ import packageJson from "package-json";
|
|
|
10
10
|
const nodeNpmRegistrySource = defineSource({
|
|
11
11
|
async discover(context) {
|
|
12
12
|
if (context.options.offline) {
|
|
13
|
-
log.
|
|
13
|
+
log.debug("Skipping Node NPM registry data source since we're in offline mode");
|
|
14
14
|
return [];
|
|
15
15
|
}
|
|
16
16
|
let packages = ensureArray(context.metadata?.nodePackageJson);
|
|
17
17
|
if (packages.length === 0 && !context.completedSources?.has("nodePackageJson")) {
|
|
18
|
-
log.
|
|
18
|
+
log.debug(`Missing nodePackageJson in source context metadata for ${context.options.path}, extracting it now...`);
|
|
19
19
|
packages = ensureArray(await nodePackageJsonSource.extract(context));
|
|
20
20
|
}
|
|
21
21
|
return packages.filter((packageJson) => {
|
|
@@ -10,12 +10,12 @@ const pluginStatsSchema = z.record(z.string(), z.record(z.string(), z.number()))
|
|
|
10
10
|
const obsidianPluginRegistrySource = defineSource({
|
|
11
11
|
async discover(context) {
|
|
12
12
|
if (context.options.offline) {
|
|
13
|
-
log.
|
|
13
|
+
log.debug("Skipping Obsidian plugin registry data source since we're in offline mode");
|
|
14
14
|
return [];
|
|
15
15
|
}
|
|
16
16
|
let pluginIds = ensureArray(context.metadata?.obsidianPluginManifestJson).map((value) => value.data.id);
|
|
17
17
|
if (pluginIds.length === 0 && !context.completedSources?.has("obsidianPluginManifestJson")) {
|
|
18
|
-
log.
|
|
18
|
+
log.debug(`Missing obsidianPluginManifestJson in source context metadata for ${context.options.path}, extracting it now...`);
|
|
19
19
|
pluginIds = ensureArray(await obsidianPluginManifestJsonSource.extract(context)).map((value) => value.data.id);
|
|
20
20
|
}
|
|
21
21
|
return pluginIds;
|
|
@@ -32,7 +32,7 @@ const pypistatsOverallSchema = z.object({ data: z.array(z.object({
|
|
|
32
32
|
const pythonPypiRegistrySource = defineSource({
|
|
33
33
|
async discover(context) {
|
|
34
34
|
if (context.options.offline) {
|
|
35
|
-
log.
|
|
35
|
+
log.debug("Skipping Python PyPI registry data source since we're in offline mode");
|
|
36
36
|
return [];
|
|
37
37
|
}
|
|
38
38
|
let packageNames = [];
|
|
@@ -3,6 +3,7 @@ import { z } from "zod";
|
|
|
3
3
|
|
|
4
4
|
//#region src/lib/sources/readme-file.d.ts
|
|
5
5
|
declare const readmeSchema: z.ZodObject<{
|
|
6
|
+
frontmatter: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
6
7
|
name: z.ZodString;
|
|
7
8
|
}, z.core.$strip>;
|
|
8
9
|
type Readme = z.infer<typeof readmeSchema>;
|
|
@@ -3,10 +3,14 @@ import { defineSource } from "../source.js";
|
|
|
3
3
|
import { readFile } from "node:fs/promises";
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
5
|
import { z } from "zod";
|
|
6
|
+
import { matter } from "gray-matter-es";
|
|
6
7
|
import remarkParse from "remark-parse";
|
|
7
8
|
import { unified } from "unified";
|
|
8
9
|
//#region src/lib/sources/readme-file.ts
|
|
9
|
-
const readmeSchema = z.object({
|
|
10
|
+
const readmeSchema = z.object({
|
|
11
|
+
frontmatter: z.record(z.string(), z.unknown()).optional(),
|
|
12
|
+
name: z.string()
|
|
13
|
+
});
|
|
10
14
|
/**
|
|
11
15
|
* Recursively extract plain text from mdast phrasing content.
|
|
12
16
|
*/
|
|
@@ -33,9 +37,13 @@ function extractFirstH1(markdown) {
|
|
|
33
37
|
* @returns Parsed metadata, or `undefined` if no H1 heading is found.
|
|
34
38
|
*/
|
|
35
39
|
function parse(content) {
|
|
36
|
-
const
|
|
40
|
+
const { content: markdown, data } = matter(content);
|
|
41
|
+
const name = extractFirstH1(markdown);
|
|
37
42
|
if (!name) return void 0;
|
|
38
|
-
return readmeSchema.parse({
|
|
43
|
+
return readmeSchema.parse({
|
|
44
|
+
frontmatter: Object.keys(data).length > 0 ? data : void 0,
|
|
45
|
+
name
|
|
46
|
+
});
|
|
39
47
|
}
|
|
40
48
|
const readmeFileSource = defineSource({
|
|
41
49
|
async discover(context) {
|
|
@@ -18,7 +18,7 @@ declare const frontmatter: Template<{
|
|
|
18
18
|
Public: boolean;
|
|
19
19
|
Fork: boolean;
|
|
20
20
|
Published: boolean;
|
|
21
|
-
Status: "
|
|
21
|
+
Status: "author" | "maintainer" | "unknown" | "observer";
|
|
22
22
|
Tags: string[] | null;
|
|
23
23
|
Aliases: (string | null | undefined)[] | null;
|
|
24
24
|
License: string[] | null;
|
|
@@ -157,7 +157,7 @@ declare const templates: {
|
|
|
157
157
|
Public: boolean;
|
|
158
158
|
Fork: boolean;
|
|
159
159
|
Published: boolean;
|
|
160
|
-
Status: "
|
|
160
|
+
Status: "author" | "maintainer" | "unknown" | "observer";
|
|
161
161
|
Tags: string[] | null;
|
|
162
162
|
Aliases: (string | null | undefined)[] | null;
|
|
163
163
|
License: string[] | null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metascope",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "A CLI tool and TypeScript library to easily extract metadata from all kinds of software repositories.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"metadata",
|
|
@@ -50,10 +50,11 @@
|
|
|
50
50
|
"@types/plist": "^3.0.5",
|
|
51
51
|
"@types/yargs": "^17.0.35",
|
|
52
52
|
"case-police": "^2.2.0",
|
|
53
|
-
"defu": "^6.1.
|
|
53
|
+
"defu": "^6.1.6",
|
|
54
54
|
"fast-xml-parser": "^5.5.9",
|
|
55
55
|
"find-workspaces": "^0.3.1",
|
|
56
56
|
"git-url-parse": "^16.1.0",
|
|
57
|
+
"gray-matter-es": "^0.2.1",
|
|
57
58
|
"jiti": "^2.6.1",
|
|
58
59
|
"lognow": "^0.5.2",
|
|
59
60
|
"octokit": "^5.0.5",
|
|
@@ -74,7 +75,7 @@
|
|
|
74
75
|
"tinyglobby": "^0.2.15",
|
|
75
76
|
"unified": "^11.0.5",
|
|
76
77
|
"updates": "^17.13.1",
|
|
77
|
-
"web-tree-sitter": "^0.26.
|
|
78
|
+
"web-tree-sitter": "^0.26.8",
|
|
78
79
|
"yaml": "^2.8.3",
|
|
79
80
|
"yargs": "^18.0.0",
|
|
80
81
|
"zod": "^4.3.6"
|
|
@@ -88,7 +89,7 @@
|
|
|
88
89
|
"@types/semver": "^7.7.1",
|
|
89
90
|
"bumpp": "^11.0.1",
|
|
90
91
|
"jsonld": "^9.0.0",
|
|
91
|
-
"mdat-plugin-cli-help": "^1.0.
|
|
92
|
+
"mdat-plugin-cli-help": "^1.0.8",
|
|
92
93
|
"msw": "2.12.14",
|
|
93
94
|
"publint": "^0.3.18",
|
|
94
95
|
"tree-sitter-python": "^0.25.0",
|