metascope 0.1.0 → 0.2.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 +14 -14
- package/dist/lib/{chunk-DrSxFLj_.js → _virtual/_rolldown/runtime.js} +1 -1
- package/dist/lib/file-matching.js +152 -0
- package/dist/lib/index.d.ts +11 -1496
- package/dist/lib/index.js +6 -6215
- package/dist/lib/log.d.ts +11 -0
- package/dist/lib/log.js +20 -0
- package/dist/lib/metadata-types.d.ts +151 -0
- package/dist/lib/metadata-types.js +30 -0
- package/dist/lib/metadata.d.ts +16 -0
- package/dist/lib/metadata.js +235 -0
- package/dist/lib/package.js +5 -0
- package/dist/lib/parsers/configparser-parser.js +43 -0
- package/dist/lib/parsers/gemspec-parser.js +256 -0
- package/dist/lib/parsers/go-mod-parser.js +153 -0
- package/dist/lib/parsers/makefile-config-parser.js +102 -0
- package/dist/lib/parsers/properties-parser.js +31 -0
- package/dist/lib/parsers/rfc822-header-parser.js +48 -0
- package/dist/lib/parsers/setup-py-parser.js +173 -0
- package/dist/lib/source.d.ts +17 -0
- package/dist/lib/source.js +34 -0
- package/dist/lib/sources/arduino-library-properties.d.ts +45 -0
- package/dist/lib/sources/arduino-library-properties.js +208 -0
- package/dist/lib/sources/cinder-cinderblock-xml.d.ts +21 -0
- package/dist/lib/sources/cinder-cinderblock-xml.js +134 -0
- package/dist/lib/sources/code-stats.d.ts +14 -0
- package/dist/lib/sources/code-stats.js +40 -0
- package/dist/lib/sources/codemeta-json.d.ts +117 -0
- package/dist/lib/sources/codemeta-json.js +226 -0
- package/dist/lib/sources/dependency-updates.d.ts +22 -0
- package/dist/lib/sources/dependency-updates.js +132 -0
- package/dist/lib/sources/file-stats.d.ts +12 -0
- package/dist/lib/sources/file-stats.js +48 -0
- package/dist/lib/sources/git-config.d.ts +8 -0
- package/dist/lib/sources/git-config.js +21 -0
- package/dist/lib/sources/git-stats.d.ts +35 -0
- package/dist/lib/sources/git-stats.js +130 -0
- package/dist/lib/sources/github.d.ts +94 -0
- package/dist/lib/sources/github.js +399 -0
- package/dist/lib/sources/go-go-mod.d.ts +19 -0
- package/dist/lib/sources/go-go-mod.js +38 -0
- package/dist/lib/sources/go-goreleaser-yaml.d.ts +19 -0
- package/dist/lib/sources/go-goreleaser-yaml.js +152 -0
- package/dist/lib/sources/java-pom-xml.d.ts +52 -0
- package/dist/lib/sources/java-pom-xml.js +248 -0
- package/dist/lib/sources/license-file.d.ts +10 -0
- package/dist/lib/sources/license-file.js +26 -0
- package/dist/lib/sources/metadata-file.d.ts +14 -0
- package/dist/lib/sources/metadata-file.js +109 -0
- package/dist/lib/sources/metascope.d.ts +14 -0
- package/dist/lib/sources/metascope.js +35 -0
- package/dist/lib/sources/node-npm-registry.d.ts +19 -0
- package/dist/lib/sources/node-npm-registry.js +74 -0
- package/dist/lib/sources/node-package-json.d.ts +7 -0
- package/dist/lib/sources/node-package-json.js +27 -0
- package/dist/lib/sources/obsidian-plugin-manifest-json.d.ts +17 -0
- package/dist/lib/sources/obsidian-plugin-manifest-json.js +34 -0
- package/dist/lib/sources/obsidian-plugin-registry.d.ts +10 -0
- package/dist/lib/sources/obsidian-plugin-registry.js +44 -0
- package/dist/lib/sources/openframeworks-addon-config-mk.d.ts +17 -0
- package/dist/lib/sources/openframeworks-addon-config-mk.js +39 -0
- package/dist/lib/sources/openframeworks-install-xml.d.ts +20 -0
- package/dist/lib/sources/openframeworks-install-xml.js +153 -0
- package/dist/lib/sources/processing-library-properties.d.ts +44 -0
- package/dist/lib/sources/processing-library-properties.js +219 -0
- package/dist/lib/sources/processing-sketch-properties.d.ts +38 -0
- package/dist/lib/sources/processing-sketch-properties.js +185 -0
- package/dist/lib/sources/publiccode-yaml.d.ts +73 -0
- package/dist/lib/sources/publiccode-yaml.js +256 -0
- package/dist/lib/sources/python-pkg-info.d.ts +31 -0
- package/dist/lib/sources/python-pkg-info.js +115 -0
- package/dist/lib/sources/python-pypi-registry.d.ts +19 -0
- package/dist/lib/sources/python-pypi-registry.js +101 -0
- package/dist/lib/sources/python-pyproject-toml.d.ts +7 -0
- package/dist/lib/sources/python-pyproject-toml.js +30 -0
- package/dist/lib/sources/python-setup-cfg.d.ts +28 -0
- package/dist/lib/sources/python-setup-cfg.js +106 -0
- package/dist/lib/sources/python-setup-py.d.ts +28 -0
- package/dist/lib/sources/python-setup-py.js +48 -0
- package/dist/lib/sources/readme-file.d.ts +11 -0
- package/dist/lib/sources/readme-file.js +55 -0
- package/dist/lib/sources/ruby-gemspec.d.ts +44 -0
- package/dist/lib/sources/ruby-gemspec.js +62 -0
- package/dist/lib/sources/rust-cargo-toml.d.ts +40 -0
- package/dist/lib/sources/rust-cargo-toml.js +159 -0
- package/dist/lib/sources/xcode-info-plist.d.ts +22 -0
- package/dist/lib/sources/xcode-info-plist.js +199 -0
- package/dist/lib/sources/xcode-project-pbxproj.d.ts +21 -0
- package/dist/lib/sources/xcode-project-pbxproj.js +222 -0
- package/dist/lib/templates/codemeta.d.ts +47 -0
- package/dist/lib/templates/codemeta.js +494 -0
- package/dist/lib/templates/frontmatter.d.ts +87 -0
- package/dist/lib/templates/frontmatter.js +111 -0
- package/dist/lib/templates/index.d.ts +181 -0
- package/dist/lib/templates/index.js +22 -0
- package/dist/lib/templates/metadata.d.ts +17 -0
- package/dist/lib/templates/metadata.js +35 -0
- package/dist/lib/templates/project.d.ts +39 -0
- package/dist/lib/templates/project.js +51 -0
- package/dist/lib/utilities/codemeta-helpers.d.ts +39 -0
- package/dist/lib/utilities/codemeta-helpers.js +83 -0
- package/dist/lib/utilities/fetch.js +43 -0
- package/dist/lib/utilities/formatting.js +28 -0
- package/dist/lib/utilities/license-identification.js +141 -0
- package/dist/lib/utilities/schema-primitives.js +47 -0
- package/dist/lib/utilities/template-helpers.d.ts +135 -0
- package/dist/lib/utilities/template-helpers.js +310 -0
- package/dist/lib/utilities/tree-sitter-wasm.js +30 -0
- package/package.json +6 -6
- package/readme.md +62 -15
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { log } from "../log.js";
|
|
2
|
+
import { getMatches } from "../file-matching.js";
|
|
3
|
+
import { batchMap } from "../utilities/formatting.js";
|
|
4
|
+
import { defineSource } from "../source.js";
|
|
5
|
+
import { stat } from "node:fs/promises";
|
|
6
|
+
import { join, resolve } from "node:path";
|
|
7
|
+
import { simpleGit } from "simple-git";
|
|
8
|
+
//#region src/lib/sources/git-stats.ts
|
|
9
|
+
const gitStatsSource = defineSource({
|
|
10
|
+
async discover(context) {
|
|
11
|
+
return (await getMatches(context.options, [".git/config"])).map((value) => resolve(value, "../../"));
|
|
12
|
+
},
|
|
13
|
+
key: "gitStats",
|
|
14
|
+
async parse(input, context) {
|
|
15
|
+
log.debug("Extracting git statistics metadata...");
|
|
16
|
+
const git = simpleGit(input);
|
|
17
|
+
const [statusResult, logResult, branchResult, tagResult, commitDateFirst, trackedFiles, remotes, submoduleCount, hasLfs] = await Promise.all([
|
|
18
|
+
git.status(),
|
|
19
|
+
git.log(),
|
|
20
|
+
git.branch(),
|
|
21
|
+
git.tags(),
|
|
22
|
+
git.raw([
|
|
23
|
+
"rev-list",
|
|
24
|
+
"--max-parents=0",
|
|
25
|
+
"HEAD",
|
|
26
|
+
"--format=%aI"
|
|
27
|
+
]).then((output) => {
|
|
28
|
+
return output.trim().split("\n").filter((line) => !line.startsWith("commit ")).at(-1) ?? void 0;
|
|
29
|
+
}),
|
|
30
|
+
git.raw(["ls-files"]).then((output) => output.trim().split("\n").filter(Boolean)),
|
|
31
|
+
git.getRemotes(),
|
|
32
|
+
git.raw(["submodule", "status"]).then((output) => {
|
|
33
|
+
const count = output.trim().split("\n").filter(Boolean).length;
|
|
34
|
+
return count > 0 ? count : void 0;
|
|
35
|
+
}).catch(() => void 0),
|
|
36
|
+
git.raw(["lfs", "ls-files"]).then((output) => output.trim().length > 0 ? true : void 0).catch(() => void 0)
|
|
37
|
+
]);
|
|
38
|
+
const trackedSizeBytes = (await batchMap(trackedFiles, async (file) => {
|
|
39
|
+
try {
|
|
40
|
+
return (await stat(join(context.options.path, file))).size;
|
|
41
|
+
} catch {
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
})).reduce((sum, size) => sum + size, 0);
|
|
45
|
+
const contributors = new Set(logResult.all.map((commit) => commit.author_email));
|
|
46
|
+
let tagDateLatest;
|
|
47
|
+
const tagNameLatest = tagResult.latest ?? void 0;
|
|
48
|
+
if (tagNameLatest) try {
|
|
49
|
+
tagDateLatest = (await git.raw([
|
|
50
|
+
"log",
|
|
51
|
+
"-1",
|
|
52
|
+
"--format=%aI",
|
|
53
|
+
tagNameLatest
|
|
54
|
+
])).trim() || void 0;
|
|
55
|
+
} catch {}
|
|
56
|
+
const versionTagPattern = /^v?\d+(?:\.\d+){1,2}$/;
|
|
57
|
+
let tagReleaseCount;
|
|
58
|
+
let tagVersionLatest;
|
|
59
|
+
let tagVersionDateLatest;
|
|
60
|
+
try {
|
|
61
|
+
const versionTags = (await git.raw(["tag", "--sort=-creatordate"])).trim().split("\n").filter(Boolean).filter((tag) => versionTagPattern.test(tag));
|
|
62
|
+
tagReleaseCount = versionTags.length > 0 ? versionTags.length : void 0;
|
|
63
|
+
const match = versionTags[0];
|
|
64
|
+
if (match) {
|
|
65
|
+
const tagDate = await git.raw([
|
|
66
|
+
"log",
|
|
67
|
+
"-1",
|
|
68
|
+
"--format=%aI",
|
|
69
|
+
match
|
|
70
|
+
]);
|
|
71
|
+
tagVersionLatest = match.replace(/^v/, "");
|
|
72
|
+
tagVersionDateLatest = tagDate.trim() || void 0;
|
|
73
|
+
}
|
|
74
|
+
} catch {}
|
|
75
|
+
const remoteStatusEntries = await Promise.all(remotes.map(async (remote) => {
|
|
76
|
+
for (const branch of ["main", "master"]) {
|
|
77
|
+
const reference = `${remote.name}/${branch}`;
|
|
78
|
+
try {
|
|
79
|
+
const [ahead, behind] = (await git.raw([
|
|
80
|
+
"rev-list",
|
|
81
|
+
"--left-right",
|
|
82
|
+
"--count",
|
|
83
|
+
`HEAD...${reference}`
|
|
84
|
+
])).trim().split(" ").map(Number);
|
|
85
|
+
return [remote.name, {
|
|
86
|
+
ahead,
|
|
87
|
+
behind
|
|
88
|
+
}];
|
|
89
|
+
} catch {}
|
|
90
|
+
}
|
|
91
|
+
}));
|
|
92
|
+
const remoteStatus = {};
|
|
93
|
+
for (const entry of remoteStatusEntries) if (entry) remoteStatus[entry[0]] = entry[1];
|
|
94
|
+
const remoteStatusValues = Object.values(remoteStatus);
|
|
95
|
+
const totalAhead = remoteStatusValues.length > 0 ? remoteStatusValues.reduce((sum, s) => sum + s.ahead, 0) : void 0;
|
|
96
|
+
const totalBehind = remoteStatusValues.length > 0 ? remoteStatusValues.reduce((sum, s) => sum + s.behind, 0) : void 0;
|
|
97
|
+
return {
|
|
98
|
+
data: {
|
|
99
|
+
branchCount: branchResult.all.length,
|
|
100
|
+
branchCurrent: branchResult.current,
|
|
101
|
+
commitCount: logResult.total,
|
|
102
|
+
commitDateFirst,
|
|
103
|
+
commitDateLast: logResult.latest?.date ?? void 0,
|
|
104
|
+
contributorCount: contributors.size,
|
|
105
|
+
hasLfs,
|
|
106
|
+
isClean: statusResult.isClean(),
|
|
107
|
+
isDirty: !statusResult.isClean(),
|
|
108
|
+
isRemoteAhead: Object.values(remoteStatus).some((s) => s.behind > 0) || void 0,
|
|
109
|
+
remoteCount: remotes.length,
|
|
110
|
+
remoteStatus: Object.keys(remoteStatus).length > 0 ? remoteStatus : void 0,
|
|
111
|
+
submoduleCount,
|
|
112
|
+
tagCount: tagResult.all.length,
|
|
113
|
+
tagDateLatest,
|
|
114
|
+
tagNameLatest,
|
|
115
|
+
tagReleaseCount,
|
|
116
|
+
tagVersionDateLatest,
|
|
117
|
+
tagVersionLatest,
|
|
118
|
+
totalAhead,
|
|
119
|
+
totalBehind,
|
|
120
|
+
trackedFileCount: trackedFiles.length,
|
|
121
|
+
trackedSizeBytes,
|
|
122
|
+
uncommittedFileCount: statusResult.files.length
|
|
123
|
+
},
|
|
124
|
+
source: input
|
|
125
|
+
};
|
|
126
|
+
},
|
|
127
|
+
phase: 1
|
|
128
|
+
});
|
|
129
|
+
//#endregion
|
|
130
|
+
export { gitStatsSource };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { OneOrMany, SourceRecord } from "../source.js";
|
|
2
|
+
|
|
3
|
+
//#region src/lib/sources/github.d.ts
|
|
4
|
+
type GitHubInfo = {
|
|
5
|
+
/** ISO 8601 date when the repo was archived, if applicable. */archivedAt?: string; /** Name of the repository's code of conduct. */
|
|
6
|
+
codeOfConduct?: string; /** Commits the default branch is ahead of the upstream fork parent. */
|
|
7
|
+
commitsAheadUpstream?: number; /** Commits the default branch is behind the upstream fork parent. */
|
|
8
|
+
commitsBehindUpstream?: number; /** Number of contributors to the repository. */
|
|
9
|
+
contributorCount?: number; /** ISO 8601 date when the repo was created. */
|
|
10
|
+
createdAt?: string; /** GitHub's internal numeric repository ID. */
|
|
11
|
+
databaseId?: number; /** Name of the default branch (e.g. "main"). */
|
|
12
|
+
defaultBranch?: string; /** Repository description. */
|
|
13
|
+
description?: string; /** Total number of discussions. */
|
|
14
|
+
discussionCount?: number; /** Repository disk usage in bytes. */
|
|
15
|
+
diskUsageBytes?: number; /** Number of forks. */
|
|
16
|
+
forkCount?: number; /** URL of the upstream repository this was forked from. */
|
|
17
|
+
forkedFrom?: string; /** Funding links configured on the repository. */
|
|
18
|
+
fundingLinks?: Array<{
|
|
19
|
+
platform: string;
|
|
20
|
+
url: string;
|
|
21
|
+
}>; /** Whether a CONTRIBUTING file exists. */
|
|
22
|
+
hasContributing?: boolean; /** Whether discussions are enabled. */
|
|
23
|
+
hasDiscussionsEnabled?: boolean; /** Whether issues are enabled. */
|
|
24
|
+
hasIssuesEnabled?: boolean; /** Whether the repo uses Git LFS (detected via .gitattributes). */
|
|
25
|
+
hasLfs?: boolean; /** Whether GitHub Pages is enabled. */
|
|
26
|
+
hasPages?: boolean; /** Whether projects are enabled. */
|
|
27
|
+
hasProjectsEnabled?: boolean; /** Whether sponsorships are enabled. */
|
|
28
|
+
hasSponsorshipsEnabled?: boolean; /** Whether vulnerability alerts are enabled. */
|
|
29
|
+
hasVulnerabilityAlertsEnabled?: boolean; /** Whether the wiki is enabled. */
|
|
30
|
+
hasWikiEnabled?: boolean; /** Homepage URL set on the repository. */
|
|
31
|
+
homepageUrl?: string; /** Whether the repository is archived. */
|
|
32
|
+
isArchived?: boolean; /** Whether the repository is disabled. */
|
|
33
|
+
isDisabled?: boolean; /** Whether the repository is a fork. */
|
|
34
|
+
isFork?: boolean; /** Whether the repository belongs to an organization. */
|
|
35
|
+
isInOrganization?: boolean; /** Whether the repository is a mirror. */
|
|
36
|
+
isMirror?: boolean; /** Whether the repository is private. */
|
|
37
|
+
isPrivate?: boolean; /** Whether a security policy is enabled. */
|
|
38
|
+
isSecurityPolicyEnabled?: boolean; /** Number of closed issues. */
|
|
39
|
+
issueCountClosed?: number; /** Number of open issues. */
|
|
40
|
+
issueCountOpen?: number; /** Whether the repository is a template. */
|
|
41
|
+
isTemplate?: boolean; /** Languages used in the repo, keyed by name with size in bytes. */
|
|
42
|
+
languages?: Record<string, number>;
|
|
43
|
+
/** License identifier (unused; codemeta provides this). */
|
|
44
|
+
/** SPDX license key (e.g. "mit"). */
|
|
45
|
+
licenseKey?: string; /** Human-readable license name. */
|
|
46
|
+
licenseName?: string; /** SPDX license identifier (e.g. "MIT"). */
|
|
47
|
+
licenseSpdxId?: string; /** URL to the license text. */
|
|
48
|
+
licenseUrl?: string; /** URL of the upstream mirror, if applicable. */
|
|
49
|
+
mirrorUrl?: string; /** Repository name. */
|
|
50
|
+
name?: string; /** Full "owner/repo" identifier. */
|
|
51
|
+
nameWithOwner?: string; /** URL to the repository's Open Graph image. */
|
|
52
|
+
openGraphImageUrl?: string; /** GitHub username of the repository owner. */
|
|
53
|
+
ownerLogin?: string; /** Owner type, e.g. "User" or "Organization". */
|
|
54
|
+
ownerType?: string; /** Full "owner/repo" of the parent fork source. */
|
|
55
|
+
parentNameWithOwner?: string; /** Primary programming language of the repository. */
|
|
56
|
+
primaryLanguage?: string; /** Number of closed pull requests. */
|
|
57
|
+
pullRequestCountClosed?: number; /** Number of merged pull requests. */
|
|
58
|
+
pullRequestCountMerged?: number; /** Number of open pull requests. */
|
|
59
|
+
pullRequestCountOpen?: number; /** ISO 8601 date of the most recent push. */
|
|
60
|
+
pushedAt?: string; /** Total number of releases. */
|
|
61
|
+
releaseCount?: number; /** ISO 8601 date of the latest release. */
|
|
62
|
+
releaseDateLatest?: string; /** Total download count across latest release assets. */
|
|
63
|
+
releaseDownloadCount?: number; /** Tag name of the latest release. */
|
|
64
|
+
releaseVersionLatest?: string; /** URL to the security policy. */
|
|
65
|
+
securityPolicyUrl?: string; /** Repository merge and branch settings. */
|
|
66
|
+
settings?: {
|
|
67
|
+
/** Whether "Update branch" button is enabled. */allowUpdateBranch?: boolean; /** Whether auto-merge is allowed. */
|
|
68
|
+
autoMergeAllowed?: boolean; /** Whether branches are deleted after merge. */
|
|
69
|
+
deleteBranchOnMerge?: boolean; /** Whether forking is allowed. */
|
|
70
|
+
forkingAllowed?: boolean; /** Whether merge commits are allowed. */
|
|
71
|
+
mergeCommitAllowed?: boolean; /** Template for merge commit messages. */
|
|
72
|
+
mergeCommitMessage?: string; /** Template for merge commit titles. */
|
|
73
|
+
mergeCommitTitle?: string; /** Whether rebase merging is allowed. */
|
|
74
|
+
rebaseMergeAllowed?: boolean; /** Whether squash merging is allowed. */
|
|
75
|
+
squashMergeAllowed?: boolean; /** Template for squash merge commit messages. */
|
|
76
|
+
squashMergeCommitMessage?: string; /** Template for squash merge commit titles. */
|
|
77
|
+
squashMergeCommitTitle?: string; /** Whether web-based commits require sign-off. */
|
|
78
|
+
webCommitSignoffRequired?: boolean;
|
|
79
|
+
}; /** SSH clone URL. */
|
|
80
|
+
sshUrl?: string; /** Number of stars. */
|
|
81
|
+
stargazerCount?: number; /** Number of git submodules (detected via .gitmodules). */
|
|
82
|
+
submoduleCount?: number; /** URL of the template repository this was created from. */
|
|
83
|
+
templateFrom?: string; /** Repository topics. */
|
|
84
|
+
topics?: string[]; /** ISO 8601 date the repo was last updated. */
|
|
85
|
+
updatedAt?: string; /** GitHub URL of the repository. */
|
|
86
|
+
url?: string; /** Whether a custom Open Graph image is set. */
|
|
87
|
+
usesCustomOpenGraphImage?: boolean; /** Repository visibility (e.g. "PUBLIC", "PRIVATE"). */
|
|
88
|
+
visibility?: string; /** Number of open vulnerability alerts. */
|
|
89
|
+
vulnerabilityAlertCount?: number; /** Number of watchers. */
|
|
90
|
+
watcherCount?: number;
|
|
91
|
+
};
|
|
92
|
+
type GitHubData = OneOrMany<SourceRecord<GitHubInfo>> | undefined;
|
|
93
|
+
//#endregion
|
|
94
|
+
export { GitHubData };
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
import { log } from "../log.js";
|
|
2
|
+
import { defineSource } from "../source.js";
|
|
3
|
+
import { ensureArray } from "../utilities/template-helpers.js";
|
|
4
|
+
import { gitConfigSource } from "./git-config.js";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import gitUrlParse from "git-url-parse";
|
|
7
|
+
import { Octokit } from "octokit";
|
|
8
|
+
//#region src/lib/sources/github.ts
|
|
9
|
+
const gitHubRepoSchema = z.object({ repository: z.object({
|
|
10
|
+
allowUpdateBranch: z.boolean(),
|
|
11
|
+
archivedAt: z.string().nullable(),
|
|
12
|
+
autoMergeAllowed: z.boolean(),
|
|
13
|
+
closedIssues: z.object({ totalCount: z.number() }),
|
|
14
|
+
closedPullRequests: z.object({ totalCount: z.number() }),
|
|
15
|
+
codeOfConduct: z.object({ name: z.string() }).nullable(),
|
|
16
|
+
contributingGuidelines: z.object({ body: z.string() }).nullable(),
|
|
17
|
+
contributorCount: z.number().optional(),
|
|
18
|
+
createdAt: z.string(),
|
|
19
|
+
databaseId: z.number(),
|
|
20
|
+
defaultBranchRef: z.object({ name: z.string() }).nullable(),
|
|
21
|
+
deleteBranchOnMerge: z.boolean(),
|
|
22
|
+
description: z.string().nullable(),
|
|
23
|
+
discussions: z.object({ totalCount: z.number() }),
|
|
24
|
+
diskUsage: z.number().nullable(),
|
|
25
|
+
forkCount: z.number(),
|
|
26
|
+
forkingAllowed: z.boolean(),
|
|
27
|
+
fundingLinks: z.array(z.object({
|
|
28
|
+
platform: z.string(),
|
|
29
|
+
url: z.string()
|
|
30
|
+
})),
|
|
31
|
+
gitattributes: z.object({ text: z.string().nullable() }).nullable(),
|
|
32
|
+
gitmodules: z.object({ text: z.string().nullable() }).nullable(),
|
|
33
|
+
hasDiscussionsEnabled: z.boolean(),
|
|
34
|
+
hasIssuesEnabled: z.boolean(),
|
|
35
|
+
hasProjectsEnabled: z.boolean(),
|
|
36
|
+
hasSponsorshipsEnabled: z.boolean(),
|
|
37
|
+
hasVulnerabilityAlertsEnabled: z.boolean(),
|
|
38
|
+
hasWikiEnabled: z.boolean(),
|
|
39
|
+
homepageUrl: z.string().nullable(),
|
|
40
|
+
isArchived: z.boolean(),
|
|
41
|
+
isDisabled: z.boolean(),
|
|
42
|
+
isFork: z.boolean(),
|
|
43
|
+
isInOrganization: z.boolean(),
|
|
44
|
+
isMirror: z.boolean(),
|
|
45
|
+
isPrivate: z.boolean(),
|
|
46
|
+
isSecurityPolicyEnabled: z.boolean(),
|
|
47
|
+
isTemplate: z.boolean(),
|
|
48
|
+
languages: z.object({ edges: z.array(z.object({
|
|
49
|
+
node: z.object({ name: z.string() }),
|
|
50
|
+
size: z.number()
|
|
51
|
+
})) }).nullable(),
|
|
52
|
+
latestRelease: z.object({
|
|
53
|
+
createdAt: z.string(),
|
|
54
|
+
releaseAssets: z.object({ nodes: z.array(z.object({ downloadCount: z.number() })) }),
|
|
55
|
+
tagName: z.string()
|
|
56
|
+
}).nullable(),
|
|
57
|
+
licenseInfo: z.object({
|
|
58
|
+
key: z.string(),
|
|
59
|
+
name: z.string(),
|
|
60
|
+
spdxId: z.string().nullable(),
|
|
61
|
+
url: z.string().nullable()
|
|
62
|
+
}).nullable(),
|
|
63
|
+
mergeCommitAllowed: z.boolean(),
|
|
64
|
+
mergeCommitMessage: z.string(),
|
|
65
|
+
mergeCommitTitle: z.string(),
|
|
66
|
+
mergedPullRequests: z.object({ totalCount: z.number() }),
|
|
67
|
+
mirrorUrl: z.string().nullable(),
|
|
68
|
+
name: z.string(),
|
|
69
|
+
nameWithOwner: z.string(),
|
|
70
|
+
openGraphImageUrl: z.string(),
|
|
71
|
+
openIssues: z.object({ totalCount: z.number() }),
|
|
72
|
+
openPullRequests: z.object({ totalCount: z.number() }),
|
|
73
|
+
owner: z.object({
|
|
74
|
+
__typename: z.string(),
|
|
75
|
+
login: z.string()
|
|
76
|
+
}),
|
|
77
|
+
parent: z.object({
|
|
78
|
+
defaultBranchRef: z.object({ name: z.string() }).nullable(),
|
|
79
|
+
name: z.string(),
|
|
80
|
+
nameWithOwner: z.string(),
|
|
81
|
+
owner: z.object({ login: z.string() }),
|
|
82
|
+
url: z.string()
|
|
83
|
+
}).nullable(),
|
|
84
|
+
primaryLanguage: z.object({ name: z.string() }).nullable(),
|
|
85
|
+
pushedAt: z.string().nullable(),
|
|
86
|
+
rebaseMergeAllowed: z.boolean(),
|
|
87
|
+
releases: z.object({ totalCount: z.number() }),
|
|
88
|
+
repositoryTopics: z.object({ nodes: z.array(z.object({ topic: z.object({ name: z.string() }) })) }),
|
|
89
|
+
securityPolicyUrl: z.string().nullable(),
|
|
90
|
+
squashMergeAllowed: z.boolean(),
|
|
91
|
+
squashMergeCommitMessage: z.string(),
|
|
92
|
+
squashMergeCommitTitle: z.string(),
|
|
93
|
+
sshUrl: z.string(),
|
|
94
|
+
stargazerCount: z.number(),
|
|
95
|
+
templateRepository: z.object({
|
|
96
|
+
name: z.string(),
|
|
97
|
+
owner: z.object({ login: z.string() }),
|
|
98
|
+
url: z.string()
|
|
99
|
+
}).nullable(),
|
|
100
|
+
updatedAt: z.string(),
|
|
101
|
+
url: z.string(),
|
|
102
|
+
usesCustomOpenGraphImage: z.boolean(),
|
|
103
|
+
visibility: z.string(),
|
|
104
|
+
vulnerabilityAlerts: z.object({ totalCount: z.number() }).nullable(),
|
|
105
|
+
watchers: z.object({ totalCount: z.number() }),
|
|
106
|
+
webCommitSignoffRequired: z.boolean()
|
|
107
|
+
}) });
|
|
108
|
+
/**
|
|
109
|
+
* Extract a GitHub owner/repo from git config remote URLs.
|
|
110
|
+
* Prefers the "origin" remote, falls back to the first GitHub remote found.
|
|
111
|
+
*/
|
|
112
|
+
function getGitHubRemoteFromConfig(remotes) {
|
|
113
|
+
if (!remotes) return void 0;
|
|
114
|
+
const sorted = Object.entries(remotes).toSorted(([a], [b]) => {
|
|
115
|
+
if (a === "origin") return -1;
|
|
116
|
+
if (b === "origin") return 1;
|
|
117
|
+
return 0;
|
|
118
|
+
});
|
|
119
|
+
for (const [, remote] of sorted) {
|
|
120
|
+
const { url } = remote;
|
|
121
|
+
if (!url) continue;
|
|
122
|
+
try {
|
|
123
|
+
const parsed = gitUrlParse(url);
|
|
124
|
+
if (parsed.source === "github.com" && parsed.owner && parsed.name) return {
|
|
125
|
+
owner: parsed.owner,
|
|
126
|
+
repo: parsed.name
|
|
127
|
+
};
|
|
128
|
+
} catch {}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const graphqlQuery = `
|
|
132
|
+
query($owner: String!, $repo: String!) {
|
|
133
|
+
repository(owner: $owner, name: $repo) {
|
|
134
|
+
name
|
|
135
|
+
nameWithOwner
|
|
136
|
+
owner { __typename login }
|
|
137
|
+
url
|
|
138
|
+
description
|
|
139
|
+
homepageUrl
|
|
140
|
+
createdAt
|
|
141
|
+
updatedAt
|
|
142
|
+
pushedAt
|
|
143
|
+
archivedAt
|
|
144
|
+
databaseId
|
|
145
|
+
isArchived
|
|
146
|
+
isDisabled
|
|
147
|
+
isFork
|
|
148
|
+
isInOrganization
|
|
149
|
+
isMirror
|
|
150
|
+
isPrivate
|
|
151
|
+
isTemplate
|
|
152
|
+
visibility
|
|
153
|
+
diskUsage
|
|
154
|
+
stargazerCount
|
|
155
|
+
forkCount
|
|
156
|
+
sshUrl
|
|
157
|
+
hasWikiEnabled
|
|
158
|
+
hasDiscussionsEnabled
|
|
159
|
+
hasIssuesEnabled
|
|
160
|
+
hasProjectsEnabled
|
|
161
|
+
hasSponsorshipsEnabled
|
|
162
|
+
hasVulnerabilityAlertsEnabled
|
|
163
|
+
isSecurityPolicyEnabled
|
|
164
|
+
securityPolicyUrl
|
|
165
|
+
openGraphImageUrl
|
|
166
|
+
usesCustomOpenGraphImage
|
|
167
|
+
autoMergeAllowed
|
|
168
|
+
allowUpdateBranch
|
|
169
|
+
deleteBranchOnMerge
|
|
170
|
+
forkingAllowed
|
|
171
|
+
mergeCommitAllowed
|
|
172
|
+
mergeCommitMessage
|
|
173
|
+
mergeCommitTitle
|
|
174
|
+
mirrorUrl
|
|
175
|
+
rebaseMergeAllowed
|
|
176
|
+
squashMergeAllowed
|
|
177
|
+
squashMergeCommitMessage
|
|
178
|
+
squashMergeCommitTitle
|
|
179
|
+
webCommitSignoffRequired
|
|
180
|
+
codeOfConduct { name }
|
|
181
|
+
contributingGuidelines { body }
|
|
182
|
+
fundingLinks { platform url }
|
|
183
|
+
licenseInfo { key name spdxId url }
|
|
184
|
+
defaultBranchRef { name }
|
|
185
|
+
primaryLanguage { name }
|
|
186
|
+
parent {
|
|
187
|
+
owner { login }
|
|
188
|
+
name
|
|
189
|
+
nameWithOwner
|
|
190
|
+
url
|
|
191
|
+
defaultBranchRef { name }
|
|
192
|
+
}
|
|
193
|
+
templateRepository {
|
|
194
|
+
owner { login }
|
|
195
|
+
name
|
|
196
|
+
url
|
|
197
|
+
}
|
|
198
|
+
gitattributes: object(expression: "HEAD:.gitattributes") {
|
|
199
|
+
... on Blob { text }
|
|
200
|
+
}
|
|
201
|
+
gitmodules: object(expression: "HEAD:.gitmodules") {
|
|
202
|
+
... on Blob { text }
|
|
203
|
+
}
|
|
204
|
+
openIssues: issues(states: OPEN) { totalCount }
|
|
205
|
+
closedIssues: issues(states: CLOSED) { totalCount }
|
|
206
|
+
openPullRequests: pullRequests(states: OPEN) { totalCount }
|
|
207
|
+
closedPullRequests: pullRequests(states: CLOSED) { totalCount }
|
|
208
|
+
mergedPullRequests: pullRequests(states: MERGED) { totalCount }
|
|
209
|
+
discussions { totalCount }
|
|
210
|
+
vulnerabilityAlerts(states: OPEN) { totalCount }
|
|
211
|
+
watchers { totalCount }
|
|
212
|
+
releases { totalCount }
|
|
213
|
+
latestRelease {
|
|
214
|
+
tagName
|
|
215
|
+
createdAt
|
|
216
|
+
releaseAssets(first: 100) {
|
|
217
|
+
nodes { downloadCount }
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
repositoryTopics(first: 50) {
|
|
221
|
+
nodes { topic { name } }
|
|
222
|
+
}
|
|
223
|
+
languages(first: 20, orderBy: { field: SIZE, direction: DESC }) {
|
|
224
|
+
edges {
|
|
225
|
+
node { name }
|
|
226
|
+
size
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
`;
|
|
232
|
+
async function checkHasPages(octokit, owner, repo) {
|
|
233
|
+
try {
|
|
234
|
+
return (await octokit.rest.repos.get({
|
|
235
|
+
owner,
|
|
236
|
+
repo
|
|
237
|
+
})).data.has_pages;
|
|
238
|
+
} catch {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
async function getUpstreamComparison(octokit, owner, repo, defaultBranch, parent) {
|
|
243
|
+
const parentBranch = parent.defaultBranchRef?.name;
|
|
244
|
+
if (!parentBranch) return void 0;
|
|
245
|
+
try {
|
|
246
|
+
const response = await octokit.rest.repos.compareCommitsWithBasehead({
|
|
247
|
+
basehead: `${parent.owner.login}:${parentBranch}...${owner}:${defaultBranch}`,
|
|
248
|
+
owner,
|
|
249
|
+
repo
|
|
250
|
+
});
|
|
251
|
+
return {
|
|
252
|
+
ahead: response.data.ahead_by,
|
|
253
|
+
behind: response.data.behind_by
|
|
254
|
+
};
|
|
255
|
+
} catch {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function countSubmodules(gitmodulesText) {
|
|
260
|
+
if (!gitmodulesText) return 0;
|
|
261
|
+
return gitmodulesText.match(/\[submodule\s/g)?.length ?? 0;
|
|
262
|
+
}
|
|
263
|
+
function detectLfs(gitattributesText) {
|
|
264
|
+
if (!gitattributesText) return false;
|
|
265
|
+
return gitattributesText.includes("filter=lfs");
|
|
266
|
+
}
|
|
267
|
+
function extractLanguages(data) {
|
|
268
|
+
const languages = {};
|
|
269
|
+
if (data.languages?.edges) for (const edge of data.languages.edges) languages[edge.node.name] = edge.size;
|
|
270
|
+
return languages;
|
|
271
|
+
}
|
|
272
|
+
function mapRepoData(data, extras) {
|
|
273
|
+
const releaseDownloadCount = (data.latestRelease?.releaseAssets.nodes.reduce((sum, asset) => sum + asset.downloadCount, 0) ?? 0) || void 0;
|
|
274
|
+
return {
|
|
275
|
+
archivedAt: data.archivedAt ?? void 0,
|
|
276
|
+
codeOfConduct: data.codeOfConduct?.name ?? void 0,
|
|
277
|
+
commitsAheadUpstream: extras.commitsAheadUpstream,
|
|
278
|
+
commitsBehindUpstream: extras.commitsBehindUpstream,
|
|
279
|
+
contributorCount: data.contributorCount,
|
|
280
|
+
createdAt: data.createdAt,
|
|
281
|
+
databaseId: data.databaseId,
|
|
282
|
+
defaultBranch: data.defaultBranchRef?.name ?? void 0,
|
|
283
|
+
description: data.description ?? void 0,
|
|
284
|
+
discussionCount: data.discussions.totalCount,
|
|
285
|
+
diskUsageBytes: data.diskUsage === null ? void 0 : data.diskUsage * 1e3,
|
|
286
|
+
forkCount: data.forkCount,
|
|
287
|
+
forkedFrom: data.parent?.url ?? void 0,
|
|
288
|
+
fundingLinks: data.fundingLinks.length > 0 ? data.fundingLinks.map((link) => ({
|
|
289
|
+
platform: link.platform,
|
|
290
|
+
url: link.url
|
|
291
|
+
})) : void 0,
|
|
292
|
+
hasContributing: data.contributingGuidelines !== null,
|
|
293
|
+
hasDiscussionsEnabled: data.hasDiscussionsEnabled,
|
|
294
|
+
hasIssuesEnabled: data.hasIssuesEnabled,
|
|
295
|
+
hasLfs: detectLfs(data.gitattributes?.text ?? void 0),
|
|
296
|
+
hasPages: extras.hasPages,
|
|
297
|
+
hasProjectsEnabled: data.hasProjectsEnabled,
|
|
298
|
+
hasSponsorshipsEnabled: data.hasSponsorshipsEnabled,
|
|
299
|
+
hasVulnerabilityAlertsEnabled: data.hasVulnerabilityAlertsEnabled,
|
|
300
|
+
hasWikiEnabled: data.hasWikiEnabled,
|
|
301
|
+
homepageUrl: data.homepageUrl === "" ? void 0 : data.homepageUrl ?? void 0,
|
|
302
|
+
isArchived: data.isArchived,
|
|
303
|
+
isDisabled: data.isDisabled,
|
|
304
|
+
isFork: data.isFork,
|
|
305
|
+
isInOrganization: data.isInOrganization,
|
|
306
|
+
isMirror: data.isMirror,
|
|
307
|
+
isPrivate: data.isPrivate,
|
|
308
|
+
isSecurityPolicyEnabled: data.isSecurityPolicyEnabled,
|
|
309
|
+
issueCountClosed: data.closedIssues.totalCount,
|
|
310
|
+
issueCountOpen: data.openIssues.totalCount,
|
|
311
|
+
isTemplate: data.isTemplate,
|
|
312
|
+
languages: extractLanguages(data),
|
|
313
|
+
licenseKey: data.licenseInfo?.key ?? void 0,
|
|
314
|
+
licenseName: data.licenseInfo?.name ?? void 0,
|
|
315
|
+
licenseSpdxId: data.licenseInfo?.spdxId === "NOASSERTION" ? void 0 : data.licenseInfo?.spdxId ?? void 0,
|
|
316
|
+
licenseUrl: data.licenseInfo?.url ?? void 0,
|
|
317
|
+
mirrorUrl: data.mirrorUrl ?? void 0,
|
|
318
|
+
name: data.name,
|
|
319
|
+
nameWithOwner: data.nameWithOwner,
|
|
320
|
+
openGraphImageUrl: data.openGraphImageUrl,
|
|
321
|
+
ownerLogin: data.owner.login,
|
|
322
|
+
ownerType: data.owner.__typename,
|
|
323
|
+
parentNameWithOwner: data.parent?.nameWithOwner ?? void 0,
|
|
324
|
+
primaryLanguage: data.primaryLanguage?.name ?? void 0,
|
|
325
|
+
pullRequestCountClosed: data.closedPullRequests.totalCount,
|
|
326
|
+
pullRequestCountMerged: data.mergedPullRequests.totalCount,
|
|
327
|
+
pullRequestCountOpen: data.openPullRequests.totalCount,
|
|
328
|
+
pushedAt: data.pushedAt ?? void 0,
|
|
329
|
+
releaseCount: data.releases.totalCount || void 0,
|
|
330
|
+
releaseDateLatest: data.latestRelease?.createdAt ?? void 0,
|
|
331
|
+
releaseDownloadCount,
|
|
332
|
+
releaseVersionLatest: data.latestRelease?.tagName ?? void 0,
|
|
333
|
+
securityPolicyUrl: data.securityPolicyUrl ?? void 0,
|
|
334
|
+
settings: {
|
|
335
|
+
allowUpdateBranch: data.allowUpdateBranch,
|
|
336
|
+
autoMergeAllowed: data.autoMergeAllowed,
|
|
337
|
+
deleteBranchOnMerge: data.deleteBranchOnMerge,
|
|
338
|
+
forkingAllowed: data.forkingAllowed,
|
|
339
|
+
mergeCommitAllowed: data.mergeCommitAllowed,
|
|
340
|
+
mergeCommitMessage: data.mergeCommitMessage,
|
|
341
|
+
mergeCommitTitle: data.mergeCommitTitle,
|
|
342
|
+
rebaseMergeAllowed: data.rebaseMergeAllowed,
|
|
343
|
+
squashMergeAllowed: data.squashMergeAllowed,
|
|
344
|
+
squashMergeCommitMessage: data.squashMergeCommitMessage,
|
|
345
|
+
squashMergeCommitTitle: data.squashMergeCommitTitle,
|
|
346
|
+
webCommitSignoffRequired: data.webCommitSignoffRequired
|
|
347
|
+
},
|
|
348
|
+
sshUrl: data.sshUrl,
|
|
349
|
+
stargazerCount: data.stargazerCount,
|
|
350
|
+
submoduleCount: countSubmodules(data.gitmodules?.text ?? void 0),
|
|
351
|
+
templateFrom: data.templateRepository?.url ?? void 0,
|
|
352
|
+
topics: data.repositoryTopics.nodes.map((n) => n.topic.name),
|
|
353
|
+
updatedAt: data.updatedAt,
|
|
354
|
+
url: data.url,
|
|
355
|
+
usesCustomOpenGraphImage: data.usesCustomOpenGraphImage,
|
|
356
|
+
visibility: data.visibility,
|
|
357
|
+
vulnerabilityAlertCount: data.vulnerabilityAlerts?.totalCount ?? void 0,
|
|
358
|
+
watcherCount: data.watchers.totalCount
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
const githubSource = defineSource({
|
|
362
|
+
async discover(context) {
|
|
363
|
+
let gitRemotes = ensureArray(context.metadata?.gitConfig).map((config) => config.data.remote).filter((remote) => remote !== void 0);
|
|
364
|
+
if (gitRemotes.length === 0 && !context.completedSources?.has("gitConfig")) {
|
|
365
|
+
log.warn(`Missing gitConfig in source context metadata for ${context.options.path}, extracting it now...`);
|
|
366
|
+
gitRemotes = ensureArray(await gitConfigSource.extract(context)).map((config) => config.data.remote).filter((remote) => remote !== void 0);
|
|
367
|
+
}
|
|
368
|
+
return [...new Set(gitRemotes.map((config) => getGitHubRemoteFromConfig(config)).filter((remote) => remote !== void 0).map((remote) => `${remote.owner}/${remote.repo}`))];
|
|
369
|
+
},
|
|
370
|
+
key: "github",
|
|
371
|
+
async parse(input, context) {
|
|
372
|
+
log.debug("Extracting GitHub metadata...");
|
|
373
|
+
const [owner, repo] = input.split("/");
|
|
374
|
+
const octokit = new Octokit(context.options.credentials?.githubToken ? { auth: context.options.credentials.githubToken } : void 0);
|
|
375
|
+
const [graphqlResult, hasPages] = await Promise.all([octokit.graphql(graphqlQuery, {
|
|
376
|
+
owner,
|
|
377
|
+
repo
|
|
378
|
+
}), checkHasPages(octokit, owner, repo)]);
|
|
379
|
+
const data = gitHubRepoSchema.parse(graphqlResult).repository;
|
|
380
|
+
let commitsAheadUpstream;
|
|
381
|
+
let commitsBehindUpstream;
|
|
382
|
+
if (data.isFork && data.parent && data.defaultBranchRef) {
|
|
383
|
+
const comparison = await getUpstreamComparison(octokit, owner, repo, data.defaultBranchRef.name, data.parent);
|
|
384
|
+
commitsAheadUpstream = comparison?.ahead;
|
|
385
|
+
commitsBehindUpstream = comparison?.behind;
|
|
386
|
+
}
|
|
387
|
+
return {
|
|
388
|
+
data: mapRepoData(data, {
|
|
389
|
+
commitsAheadUpstream,
|
|
390
|
+
commitsBehindUpstream,
|
|
391
|
+
hasPages
|
|
392
|
+
}),
|
|
393
|
+
source: `https://github.com/${owner}/${repo}`
|
|
394
|
+
};
|
|
395
|
+
},
|
|
396
|
+
phase: 2
|
|
397
|
+
});
|
|
398
|
+
//#endregion
|
|
399
|
+
export { githubSource };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { OneOrMany, SourceRecord } from "../source.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/lib/sources/go-go-mod.d.ts
|
|
5
|
+
declare const goModDataSchema: z.ZodObject<{
|
|
6
|
+
dependencies: z.ZodArray<z.ZodObject<{
|
|
7
|
+
module: z.ZodString;
|
|
8
|
+
version: z.ZodString;
|
|
9
|
+
}, z.core.$strip>>;
|
|
10
|
+
go_version: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
|
|
11
|
+
module: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
|
|
12
|
+
repository_url: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
|
|
13
|
+
tool_dependencies: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
/** Parsed go.mod metadata */
|
|
16
|
+
type GoMod = z.infer<typeof goModDataSchema>;
|
|
17
|
+
type GoGoModData = OneOrMany<SourceRecord<GoMod>> | undefined;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { GoGoModData };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { getMatches } from "../file-matching.js";
|
|
2
|
+
import { defineSource } from "../source.js";
|
|
3
|
+
import { nonEmptyString, optionalUrl, stringArray } from "../utilities/schema-primitives.js";
|
|
4
|
+
import { parseGoMod } from "../parsers/go-mod-parser.js";
|
|
5
|
+
import { readFile } from "node:fs/promises";
|
|
6
|
+
import { resolve } from "node:path";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
//#region src/lib/sources/go-go-mod.ts
|
|
9
|
+
const goModDependencySchema = z.object({
|
|
10
|
+
module: z.string(),
|
|
11
|
+
version: z.string()
|
|
12
|
+
});
|
|
13
|
+
const goModDataSchema = z.object({
|
|
14
|
+
dependencies: z.array(goModDependencySchema),
|
|
15
|
+
go_version: nonEmptyString,
|
|
16
|
+
module: nonEmptyString,
|
|
17
|
+
repository_url: optionalUrl,
|
|
18
|
+
tool_dependencies: stringArray
|
|
19
|
+
});
|
|
20
|
+
/** Parse a go.mod file string and validate through the schema. */
|
|
21
|
+
function parse(content) {
|
|
22
|
+
return goModDataSchema.parse(parseGoMod(content));
|
|
23
|
+
}
|
|
24
|
+
const goGoModSource = defineSource({
|
|
25
|
+
async discover(context) {
|
|
26
|
+
return getMatches(context.options, ["go.mod"]);
|
|
27
|
+
},
|
|
28
|
+
key: "goGoMod",
|
|
29
|
+
async parse(input, context) {
|
|
30
|
+
return {
|
|
31
|
+
data: parse(await readFile(resolve(context.options.path, input), "utf8")),
|
|
32
|
+
source: input
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
phase: 1
|
|
36
|
+
});
|
|
37
|
+
//#endregion
|
|
38
|
+
export { goGoModSource };
|