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
|
@@ -27,10 +27,10 @@ import is from "@sindresorhus/is";
|
|
|
27
27
|
* Set `INFER_TARGET_PRODUCT` to `true` to enable heuristic inference of
|
|
28
28
|
* `targetProduct` from available signals (bin field, browser field, etc.).
|
|
29
29
|
*/
|
|
30
|
-
const PEP508_NAME_REGEX = /^[\w
|
|
31
|
-
const DATE_ONLY_REGEX = /^\d{4}-\d{2}-\d{2}
|
|
32
|
-
const DATETIME_DATE_REGEX = /^(\d{4}-\d{2}-\d{2})T
|
|
33
|
-
const TRAILING_DOT_GIT_REGEX = /\.git
|
|
30
|
+
const PEP508_NAME_REGEX = /^[\w.\-]+/v;
|
|
31
|
+
const DATE_ONLY_REGEX = /^\d{4}-\d{2}-\d{2}$/v;
|
|
32
|
+
const DATETIME_DATE_REGEX = /^(\d{4}-\d{2}-\d{2})T/v;
|
|
33
|
+
const TRAILING_DOT_GIT_REGEX = /\.git$/v;
|
|
34
34
|
const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXml, codemetaJson: codemetaRaw, codeStats, fileStats, github: githubRaw, gitStats: gitRaw, goGoMod, javaPomXml, licenseFile, metascope, nodeNpmRegistry: npmRaw, nodePackageJson, obsidianPluginManifestJson, openframeworksAddonConfigMk, openframeworksInstallXml, processingLibraryProperties, publiccodeYaml, pythonPkgInfo, pythonPypiRegistry: pypiRaw, pythonPyprojectToml, pythonSetupCfg, pythonSetupPy, readmeFile, rubyGemspec, rustCargoToml, xcodeInfoPlist }) => {
|
|
35
35
|
const cm = firstOf(codemetaRaw);
|
|
36
36
|
const github = firstOf(githubRaw);
|
|
@@ -40,7 +40,7 @@ const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXm
|
|
|
40
40
|
const package_ = firstOf(nodePackageJson);
|
|
41
41
|
const pyproject = firstOf(pythonPyprojectToml);
|
|
42
42
|
const setupPy = firstOf(pythonSetupPy);
|
|
43
|
-
const
|
|
43
|
+
const setupConfig = firstOf(pythonSetupCfg);
|
|
44
44
|
const pkgInfo = firstOf(pythonPkgInfo);
|
|
45
45
|
const cargo = firstOf(rustCargoToml);
|
|
46
46
|
const gem = firstOf(rubyGemspec);
|
|
@@ -58,9 +58,9 @@ const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXm
|
|
|
58
58
|
const readmeFileFirst = firstOf(readmeFile);
|
|
59
59
|
const fileStatsFirst = firstOf(fileStats);
|
|
60
60
|
const poetry = pyproject?.data.tool?.poetry;
|
|
61
|
-
const name = package_?.data.name ?? pyproject?.data.project?.name ?? poetry?.name ?? setupPy?.data.name ??
|
|
62
|
-
const description = package_?.data.description ?? pyproject?.data.project?.description ?? poetry?.description ?? setupPy?.data.description ??
|
|
63
|
-
const version = package_?.data.version ?? pyproject?.data.project?.version ?? poetry?.version ?? setupPy?.data.version ??
|
|
61
|
+
const name = package_?.data.name ?? pyproject?.data.project?.name ?? poetry?.name ?? setupPy?.data.name ?? setupConfig?.data.name ?? pkgInfo?.data.name ?? cargo?.data.name ?? gem?.data.name ?? pom?.data.name ?? goMod?.data.module ?? arduino?.data.name ?? processing?.data.name ?? ofAddon?.data.name ?? ofInstall?.data.name ?? cinder?.data.name ?? xcode?.data.name ?? obsidian?.data.name ?? publiccode?.data.name ?? cm?.data.name ?? readmeFileFirst?.data.name ?? fileStatsFirst?.data.folderName;
|
|
62
|
+
const description = package_?.data.description ?? pyproject?.data.project?.description ?? poetry?.description ?? setupPy?.data.description ?? setupConfig?.data.description ?? pkgInfo?.data.summary ?? cargo?.data.description ?? gem?.data.summary ?? pom?.data.description ?? arduino?.data.sentence ?? processing?.data.sentence ?? ofAddon?.data.description ?? ofInstall?.data.description ?? cinder?.data.summary ?? xcode?.data.description ?? obsidian?.data.description ?? publiccode?.data.description?.shortDescription ?? cm?.data.description ?? github?.data.description;
|
|
63
|
+
const version = package_?.data.version ?? pyproject?.data.project?.version ?? poetry?.version ?? setupPy?.data.version ?? setupConfig?.data.version ?? pkgInfo?.data.version ?? cargo?.data.version ?? gem?.data.version ?? pom?.data.version ?? arduino?.data.version ?? processing?.data.prettyVersion ?? ofInstall?.data.version ?? cinder?.data.version ?? xcode?.data.version ?? obsidian?.data.version ?? publiccode?.data.softwareVersion ?? cm?.data.version ?? cm?.data.softwareVersion;
|
|
64
64
|
const identifier = pom?.data.identifier ?? cinder?.data.id ?? obsidian?.data.id ?? xcode?.data.identifier ?? package_?.data.name ?? cm?.data.identifier;
|
|
65
65
|
const ecosystemAuthors = [
|
|
66
66
|
...package_?.data.author ? [toPersonOrOrgLd({
|
|
@@ -68,17 +68,17 @@ const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXm
|
|
|
68
68
|
name: package_.data.author.name,
|
|
69
69
|
url: package_.data.author.url
|
|
70
70
|
})] : [],
|
|
71
|
-
...(pyproject?.data.project?.authors ?? []).map((a) => is.plainObject(a) ?
|
|
71
|
+
...(pyproject?.data.project?.authors ?? []).map((a) => toPersonOrOrgLd(is.plainObject(a) ? {
|
|
72
72
|
email: a.email,
|
|
73
73
|
name: a.name
|
|
74
|
-
}
|
|
75
|
-
...setupPy?.data.author ? [toPersonOrOrgLd({
|
|
74
|
+
} : { name: a })),
|
|
75
|
+
...setupPy?.data.author !== void 0 && setupPy.data.author !== "" ? [toPersonOrOrgLd({
|
|
76
76
|
email: setupPy.data.author_email,
|
|
77
77
|
name: setupPy.data.author
|
|
78
78
|
})] : [],
|
|
79
|
-
...
|
|
80
|
-
email:
|
|
81
|
-
name:
|
|
79
|
+
...setupConfig?.data.author !== void 0 && setupConfig.data.author !== "" ? [toPersonOrOrgLd({
|
|
80
|
+
email: setupConfig.data.author_email,
|
|
81
|
+
name: setupConfig.data.author
|
|
82
82
|
})] : [],
|
|
83
83
|
...(cargo?.data.authors ?? []).map((a) => toPersonOrOrgLd({
|
|
84
84
|
email: a.email,
|
|
@@ -99,14 +99,14 @@ const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXm
|
|
|
99
99
|
name: a.name,
|
|
100
100
|
url: a.url
|
|
101
101
|
})),
|
|
102
|
-
...ofAddon?.data.author ? [toPersonOrOrgLd({ name: ofAddon.data.author })] : [],
|
|
103
|
-
...ofInstall?.data.author ? [toPersonOrOrgLd({ name: ofInstall.data.author })] : [],
|
|
102
|
+
...ofAddon?.data.author !== void 0 && ofAddon.data.author !== "" ? [toPersonOrOrgLd({ name: ofAddon.data.author })] : [],
|
|
103
|
+
...ofInstall?.data.author !== void 0 && ofInstall.data.author !== "" ? [toPersonOrOrgLd({ name: ofInstall.data.author })] : [],
|
|
104
104
|
...(cinder?.data.author ?? []).map((a) => toPersonOrOrgLd({ name: a })),
|
|
105
|
-
...xcode?.data.author ? [toPersonOrOrgLd({
|
|
105
|
+
...xcode?.data.author !== void 0 && xcode.data.author !== "" ? [toPersonOrOrgLd({
|
|
106
106
|
email: xcode.data.authorEmail,
|
|
107
107
|
name: xcode.data.author
|
|
108
108
|
})] : [],
|
|
109
|
-
...obsidian?.data.author ? [toPersonOrOrgLd({
|
|
109
|
+
...obsidian?.data.author !== void 0 && obsidian.data.author !== "" ? [toPersonOrOrgLd({
|
|
110
110
|
name: obsidian.data.author,
|
|
111
111
|
url: obsidian.data.authorUrl
|
|
112
112
|
})] : [],
|
|
@@ -127,11 +127,11 @@ const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXm
|
|
|
127
127
|
url: p.url
|
|
128
128
|
}));
|
|
129
129
|
const author = resolvePersonsOrOrgs(ecosystemAuthors, cmAuthors);
|
|
130
|
-
const ecosystemContributors = [...collectArrayField(nodePackageJson, (d) => d.contributors?.map((c) => is.plainObject(c) ?
|
|
130
|
+
const ecosystemContributors = [...collectArrayField(nodePackageJson, (d) => d.contributors?.map((c) => toPersonOrOrgLd(is.plainObject(c) ? {
|
|
131
131
|
email: c.email,
|
|
132
132
|
name: c.name,
|
|
133
133
|
url: c.url
|
|
134
|
-
}
|
|
134
|
+
} : { name: c }))), ...(pom?.data.contributors ?? []).map((c) => toPersonOrOrgLd({
|
|
135
135
|
affiliation: c.organization,
|
|
136
136
|
email: c.email,
|
|
137
137
|
name: c.name,
|
|
@@ -149,24 +149,24 @@ const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXm
|
|
|
149
149
|
}));
|
|
150
150
|
const contributor = resolvePersonsOrOrgs(ecosystemContributors, cmContributors);
|
|
151
151
|
const ecosystemMaintainers = [
|
|
152
|
-
...collectArrayField(nodePackageJson, (d) => d.maintainers?.map((c) => is.plainObject(c) ?
|
|
152
|
+
...collectArrayField(nodePackageJson, (d) => d.maintainers?.map((c) => toPersonOrOrgLd(is.plainObject(c) ? {
|
|
153
153
|
email: c.email,
|
|
154
154
|
name: c.name,
|
|
155
155
|
url: c.url
|
|
156
|
-
}
|
|
157
|
-
...(pyproject?.data.project?.maintainers ?? []).map((m) => is.plainObject(m) ?
|
|
156
|
+
} : { name: c }))),
|
|
157
|
+
...(pyproject?.data.project?.maintainers ?? []).map((m) => toPersonOrOrgLd(is.plainObject(m) ? {
|
|
158
158
|
email: m.email,
|
|
159
159
|
name: m.name
|
|
160
|
-
}
|
|
161
|
-
...setupPy?.data.maintainer ? [toPersonOrOrgLd({
|
|
160
|
+
} : { name: m })),
|
|
161
|
+
...setupPy?.data.maintainer !== void 0 && setupPy.data.maintainer !== "" ? [toPersonOrOrgLd({
|
|
162
162
|
email: setupPy.data.maintainer_email,
|
|
163
163
|
name: setupPy.data.maintainer
|
|
164
164
|
})] : [],
|
|
165
|
-
...
|
|
166
|
-
email:
|
|
167
|
-
name:
|
|
165
|
+
...setupConfig?.data.maintainer !== void 0 && setupConfig.data.maintainer !== "" ? [toPersonOrOrgLd({
|
|
166
|
+
email: setupConfig.data.maintainer_email,
|
|
167
|
+
name: setupConfig.data.maintainer
|
|
168
168
|
})] : [],
|
|
169
|
-
...pkgInfo?.data.maintainer ? [toPersonOrOrgLd({
|
|
169
|
+
...pkgInfo?.data.maintainer !== void 0 && pkgInfo.data.maintainer !== "" ? [toPersonOrOrgLd({
|
|
170
170
|
email: pkgInfo.data.maintainer_email,
|
|
171
171
|
name: pkgInfo.data.maintainer
|
|
172
172
|
})] : [],
|
|
@@ -186,7 +186,7 @@ const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXm
|
|
|
186
186
|
url: p.url
|
|
187
187
|
}));
|
|
188
188
|
const maintainer = resolvePersonsOrOrgs(ecosystemMaintainers, cmMaintainers);
|
|
189
|
-
const ecosystemCopyrightHolders = [...publiccode?.data.mainCopyrightOwner ? [toPersonOrOrgLd({ name: publiccode.data.mainCopyrightOwner })] : [], ...xcode?.data.copyrightHolder ? [toPersonOrOrgLd({ name: xcode.data.copyrightHolder })] : []];
|
|
189
|
+
const ecosystemCopyrightHolders = [...publiccode?.data.mainCopyrightOwner !== void 0 && publiccode.data.mainCopyrightOwner !== "" ? [toPersonOrOrgLd({ name: publiccode.data.mainCopyrightOwner })] : [], ...xcode?.data.copyrightHolder !== void 0 && xcode.data.copyrightHolder !== "" ? [toPersonOrOrgLd({ name: xcode.data.copyrightHolder })] : []];
|
|
190
190
|
const cmCopyrightHolders = cm?.data.copyrightHolder?.map((p) => toPersonOrOrgLd({
|
|
191
191
|
affiliation: p.affiliation,
|
|
192
192
|
email: p.email,
|
|
@@ -208,16 +208,16 @@ const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXm
|
|
|
208
208
|
type: p.type,
|
|
209
209
|
url: p.url
|
|
210
210
|
})));
|
|
211
|
-
const
|
|
212
|
-
const programmingLanguage = nonEmpty([...github?.data.primaryLanguage ? [github.data.primaryLanguage] : [], ...cm?.data.programmingLanguage ?? []]) ?? nonEmpty(Object.keys(github?.data.languages ?? {})) ?? loc?.data.total?.languages.slice(0, 1);
|
|
211
|
+
const codeRepo = github?.data.url ?? cargo?.data.repository ?? pom?.data.scmUrl ?? goMod?.data.repository_url ?? publiccode?.data.url ?? arduino?.data.repository ?? cinder?.data.git ?? cm?.data.codeRepository ?? repoUrlFromPackageJson(package_?.data.repository) ?? caseInsensitiveLookup(pyproject?.data.project?.urls, "repository") ?? poetry?.repository;
|
|
212
|
+
const programmingLanguage = nonEmpty([...github?.data.primaryLanguage !== void 0 && github.data.primaryLanguage !== "" ? [github.data.primaryLanguage] : [], ...cm?.data.programmingLanguage ?? []]) ?? nonEmpty(Object.keys(github?.data.languages ?? {})) ?? loc?.data.total?.languages.slice(0, 1);
|
|
213
213
|
const runtimePlatform = nonEmpty([
|
|
214
214
|
...Object.keys(package_?.data.engines ?? {}),
|
|
215
|
-
...goMod?.data.go_version ? [`go ${goMod.data.go_version}`] : [],
|
|
216
|
-
...cargo?.data.rustVersion ? [`rust ${cargo.data.rustVersion}`] : [],
|
|
217
|
-
...pyproject?.data.project?.requiresPython ? [`python ${pyproject.data.project.requiresPython}`] : [],
|
|
218
|
-
...setupPy?.data.python_requires ? [`python ${setupPy.data.python_requires}`] : [],
|
|
219
|
-
...gem?.data.required_ruby_version ? [`ruby ${gem.data.required_ruby_version}`] : [],
|
|
220
|
-
...pom?.data.javaVersion ? [`java ${pom.data.javaVersion}`] : [],
|
|
215
|
+
...goMod?.data.go_version !== void 0 && goMod.data.go_version !== "" ? [`go ${goMod.data.go_version}`] : [],
|
|
216
|
+
...cargo?.data.rustVersion !== void 0 && cargo.data.rustVersion !== "" ? [`rust ${cargo.data.rustVersion}`] : [],
|
|
217
|
+
...pyproject?.data.project?.requiresPython !== void 0 && pyproject.data.project.requiresPython !== "" ? [`python ${pyproject.data.project.requiresPython}`] : [],
|
|
218
|
+
...setupPy?.data.python_requires !== void 0 && setupPy.data.python_requires !== "" ? [`python ${setupPy.data.python_requires}`] : [],
|
|
219
|
+
...gem?.data.required_ruby_version !== void 0 && gem.data.required_ruby_version !== "" ? [`ruby ${gem.data.required_ruby_version}`] : [],
|
|
220
|
+
...pom?.data.javaVersion !== void 0 && pom.data.javaVersion !== "" ? [`java ${pom.data.javaVersion}`] : [],
|
|
221
221
|
...cm?.data.runtimePlatform ?? []
|
|
222
222
|
]);
|
|
223
223
|
const operatingSystem = nonEmpty([
|
|
@@ -227,9 +227,9 @@ const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXm
|
|
|
227
227
|
...cinder?.data.supports ?? [],
|
|
228
228
|
...xcode?.data.operatingSystems ?? []
|
|
229
229
|
]);
|
|
230
|
-
const
|
|
231
|
-
const
|
|
232
|
-
const
|
|
230
|
+
const appCategory = cm?.data.applicationCategory ?? xcode?.data.applicationCategory ?? arduino?.data.category ?? publiccode?.data.softwareType;
|
|
231
|
+
const appSubCategory = cm?.data.applicationSubCategory;
|
|
232
|
+
const runtimeDependencies = collectRuntimeDependencies({
|
|
233
233
|
arduino,
|
|
234
234
|
cargo,
|
|
235
235
|
cinder,
|
|
@@ -243,23 +243,23 @@ const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXm
|
|
|
243
243
|
publiccode,
|
|
244
244
|
pyproject,
|
|
245
245
|
rubyGemspec,
|
|
246
|
-
setupCfg,
|
|
246
|
+
setupCfg: setupConfig,
|
|
247
247
|
setupPy
|
|
248
248
|
});
|
|
249
|
-
const softwareRequirements =
|
|
250
|
-
const
|
|
249
|
+
const softwareRequirements = runtimeDependencies.length > 0 ? deduplicateDependencies(runtimeDependencies) : cm?.data.softwareRequirements?.map((d) => toDependencyLd(d.name ?? d.identifier ?? "", d.version, d.identifier, d.runtimePlatform));
|
|
250
|
+
const developmentDependencies = collectDevelopmentDependencies({
|
|
251
251
|
cargo,
|
|
252
252
|
gem,
|
|
253
253
|
javaPomXml,
|
|
254
254
|
nodePackageJson,
|
|
255
255
|
rubyGemspec
|
|
256
256
|
});
|
|
257
|
-
const softwareSuggestions =
|
|
257
|
+
const softwareSuggestions = developmentDependencies.length > 0 ? deduplicateDependencies(developmentDependencies) : cm?.data.softwareSuggestions?.map((d) => toDependencyLd(d.name ?? d.identifier ?? "", d.version, d.identifier, d.runtimePlatform));
|
|
258
258
|
const dateCreated = git?.data.commitDateFirst ?? github?.data.createdAt ?? cm?.data.dateCreated;
|
|
259
259
|
const dateModified = git?.data.commitDateLast ?? github?.data.pushedAt ?? cm?.data.dateModified;
|
|
260
260
|
const datePublished = npm?.data.publishDateLatest ?? pypi?.data.publishDateLatest ?? publiccode?.data.releaseDate ?? github?.data.releaseDateLatest ?? git?.data.tagVersionDateLatest ?? cm?.data.datePublished;
|
|
261
261
|
const copyrightYear = xcode?.data.copyrightYear ?? pom?.data.inceptionYear ?? (cm?.data.copyrightYear === void 0 ? void 0 : String(cm.data.copyrightYear));
|
|
262
|
-
const rawLicense = package_?.data.license ?? cargo?.data.license ?? resolvePythonLicense(pyproject?.data.project?.license) ?? setupPy?.data.license ??
|
|
262
|
+
const rawLicense = package_?.data.license ?? cargo?.data.license ?? resolvePythonLicense(pyproject?.data.project?.license) ?? setupPy?.data.license ?? setupConfig?.data.license ?? gem?.data.license ?? firstPomLicense(pom) ?? arduino?.data.license ?? cinder?.data.license ?? publiccode?.data.license ?? github?.data.licenseSpdxId ?? collectField(licenseFile, (d) => d.match?.spdxId)[0] ?? resolveCmLicense(cm?.data.license);
|
|
263
263
|
const license = is.nonEmptyStringAndNotWhitespace(rawLicense) ? isProprietaryLicenseSentinel(rawLicense) ? rawLicense : toSpdxLicenseUrl(rawLicense) : void 0;
|
|
264
264
|
const isAccessibleForFree = cm?.data.isAccessibleForFree ?? (github?.data.isPrivate === false ? true : void 0);
|
|
265
265
|
const keywords = nonEmpty(deduplicateStrings([
|
|
@@ -267,7 +267,7 @@ const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXm
|
|
|
267
267
|
...pyproject?.data.project?.keywords ?? [],
|
|
268
268
|
...poetry?.keywords ?? [],
|
|
269
269
|
...setupPy?.data.keywords ?? [],
|
|
270
|
-
...
|
|
270
|
+
...setupConfig?.data.keywords ?? [],
|
|
271
271
|
...pkgInfo?.data.keywords ?? [],
|
|
272
272
|
...cargo?.data.keywords ?? [],
|
|
273
273
|
...ofAddon?.data.tags ?? [],
|
|
@@ -275,7 +275,7 @@ const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXm
|
|
|
275
275
|
...github?.data.topics ?? [],
|
|
276
276
|
...cm?.data.keywords ?? []
|
|
277
277
|
]));
|
|
278
|
-
const url = stripReadmeFragment(package_?.data.homepage) ?? caseInsensitiveLookup(pyproject?.data.project?.urls, "homepage") ?? poetry?.homepage ?? cargo?.data.homepage ?? setupPy?.data.url ??
|
|
278
|
+
const url = stripReadmeFragment(package_?.data.homepage) ?? caseInsensitiveLookup(pyproject?.data.project?.urls, "homepage") ?? poetry?.homepage ?? cargo?.data.homepage ?? setupPy?.data.url ?? setupConfig?.data.url ?? pkgInfo?.data.home_page ?? gem?.data.homepage ?? pom?.data.url ?? arduino?.data.url ?? processing?.data.url ?? ofAddon?.data.url ?? ofInstall?.data.siteUrl ?? cinder?.data.url ?? xcode?.data.url ?? publiccode?.data.landingUrl ?? github?.data.homepageUrl ?? cm?.data.url ?? caseInsensitiveLookup(pyproject?.data.project?.urls, "repository") ?? poetry?.repository;
|
|
279
279
|
const downloadUrl = ofInstall?.data.downloadUrl ?? processing?.data.download ?? npm?.data.url ?? pypi?.data.url ?? cm?.data.downloadUrl;
|
|
280
280
|
const issueTracker = bugsUrlFromPackageJson(package_?.data.bugs) ?? pom?.data.issueManagementUrl ?? cm?.data.issueTracker ?? (github?.data.hasIssuesEnabled ? `${github.data.url}/issues` : void 0);
|
|
281
281
|
const continuousIntegration = pom?.data.ciManagementUrl ?? cm?.data.continuousIntegration;
|
|
@@ -283,22 +283,22 @@ const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXm
|
|
|
283
283
|
const developmentStatus = publiccode?.data.developmentStatus ?? cm?.data.developmentStatus;
|
|
284
284
|
const funding = cm?.data.funding;
|
|
285
285
|
const buildInstructions = cm?.data.buildInstructions;
|
|
286
|
-
const readme = readmeUrl(firstOf(readmeFile),
|
|
286
|
+
const readme = readmeUrl(firstOf(readmeFile), codeRepo, github?.data.defaultBranch ?? git?.data.branchCurrent, firstOf(metascope)?.data.options.path) ?? cm?.data.readme;
|
|
287
287
|
const releaseNotes = cm?.data.releaseNotes;
|
|
288
288
|
const installUrl = cm?.data.installUrl;
|
|
289
289
|
const relatedLink = cm?.data.relatedLink;
|
|
290
290
|
return stripUndefined({
|
|
291
291
|
"@context": "https://w3id.org/codemeta/3.0",
|
|
292
292
|
"@type": "SoftwareSourceCode",
|
|
293
|
-
applicationCategory,
|
|
294
|
-
applicationSubCategory,
|
|
293
|
+
applicationCategory: appCategory,
|
|
294
|
+
applicationSubCategory: appSubCategory,
|
|
295
295
|
author,
|
|
296
296
|
buildInstructions,
|
|
297
|
-
codeRepository,
|
|
297
|
+
codeRepository: codeRepo,
|
|
298
298
|
continuousIntegration,
|
|
299
299
|
contributor,
|
|
300
300
|
copyrightHolder,
|
|
301
|
-
copyrightYear:
|
|
301
|
+
copyrightYear: toCopyrightYear(copyrightYear),
|
|
302
302
|
dateCreated: toDateOnly(dateCreated),
|
|
303
303
|
dateModified: toDateOnly(dateModified),
|
|
304
304
|
datePublished: toDateOnly(datePublished),
|
|
@@ -354,62 +354,62 @@ function resolvePersonsOrOrgs(ecosystemPersons, fallbackPersons) {
|
|
|
354
354
|
/**
|
|
355
355
|
* Collect runtime dependencies from all ecosystem sources.
|
|
356
356
|
*/
|
|
357
|
-
function
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
return
|
|
357
|
+
function collectRuntimeDependencies(sources) {
|
|
358
|
+
const dependencies = [];
|
|
359
|
+
dependencies.push(...collectArrayField(sources.nodePackageJson, (d) => objectEntriesToDependencies(d.dependencies)));
|
|
360
|
+
dependencies.push(...(sources.pyproject?.data.project?.dependencies ?? []).map((dependency) => parsePep508Dependency(dependency)));
|
|
361
|
+
dependencies.push(...(sources.setupPy?.data.install_requires ?? []).map((dependency) => parsePep508Dependency(dependency)));
|
|
362
|
+
dependencies.push(...(sources.setupCfg?.data.install_requires ?? []).map((dependency) => parsePep508Dependency(dependency)));
|
|
363
|
+
dependencies.push(...(sources.pkgInfo?.data.requires_dist ?? []).map((dependency) => parsePep508Dependency(dependency)));
|
|
364
|
+
dependencies.push(...(sources.cargo?.data.dependencies ?? []).map((d) => toDependencyLd(d.name, d.version)));
|
|
365
|
+
dependencies.push(...collectArrayField(sources.rubyGemspec, (d) => d.dependencies.filter((dependency) => dependency.type === "runtime").map((dependency) => toDependencyLd(dependency.name, dependency.requirements.join(", ")))));
|
|
366
|
+
dependencies.push(...collectArrayField(sources.javaPomXml, (d) => d.dependencies.map((dependency) => toDependencyLd(dependency.artifactId, dependency.version, `${dependency.groupId}:${dependency.artifactId}`))));
|
|
367
|
+
dependencies.push(...collectArrayField(sources.goGoMod, (d) => d.dependencies.map((dependency) => toDependencyLd(dependency.module, dependency.version))));
|
|
368
|
+
dependencies.push(...(sources.arduino?.data.depends ?? []).map((d) => toDependencyLd(d.name, d.versionConstraint)));
|
|
369
|
+
dependencies.push(...(sources.ofAddon?.data.dependencies ?? []).map((d) => toDependencyLd(d)));
|
|
370
|
+
dependencies.push(...(sources.ofInstall?.data.requirements ?? []).map((d) => toDependencyLd(d)));
|
|
371
|
+
dependencies.push(...(sources.cinder?.data.requires ?? []).map((d) => toDependencyLd(d)));
|
|
372
|
+
dependencies.push(...(sources.publiccode?.data.dependencies ?? []).map((d) => toDependencyLd(d.name, d.version)));
|
|
373
|
+
return dependencies;
|
|
374
374
|
}
|
|
375
375
|
/**
|
|
376
376
|
* Collect dev dependencies from ecosystem sources.
|
|
377
377
|
*/
|
|
378
|
-
function
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
return
|
|
378
|
+
function collectDevelopmentDependencies(sources) {
|
|
379
|
+
const dependencies = [];
|
|
380
|
+
dependencies.push(...collectArrayField(sources.nodePackageJson, (d) => objectEntriesToDependencies(d.devDependencies)));
|
|
381
|
+
dependencies.push(...(sources.cargo?.data.devDependencies ?? []).map((d) => toDependencyLd(d.name, d.version)));
|
|
382
|
+
dependencies.push(...collectArrayField(sources.rubyGemspec, (d) => d.dependencies.filter((dependency) => dependency.type === "development").map((dependency) => toDependencyLd(dependency.name, dependency.requirements.join(", ")))));
|
|
383
|
+
dependencies.push(...collectArrayField(sources.javaPomXml, (d) => d.devDependencies.map((dependency) => toDependencyLd(dependency.artifactId, dependency.version, `${dependency.groupId}:${dependency.artifactId}`))));
|
|
384
|
+
return dependencies;
|
|
385
385
|
}
|
|
386
386
|
/**
|
|
387
387
|
* Convert a Record<name, version> dependency map to CodemetaDependencyLd[].
|
|
388
388
|
*/
|
|
389
|
-
function
|
|
390
|
-
if (
|
|
391
|
-
return Object.entries(
|
|
389
|
+
function objectEntriesToDependencies(dependencies) {
|
|
390
|
+
if (dependencies === void 0) return;
|
|
391
|
+
return Object.entries(dependencies).map(([dependencyName, dependencyVersion]) => toDependencyLd(dependencyName, dependencyVersion));
|
|
392
392
|
}
|
|
393
393
|
/**
|
|
394
394
|
* Parse a PEP 508 dependency string ("package>=1.0") into a
|
|
395
395
|
* CodemetaDependencyLd.
|
|
396
396
|
*/
|
|
397
|
-
function
|
|
398
|
-
const trimmed =
|
|
397
|
+
function parsePep508Dependency(dependency) {
|
|
398
|
+
const trimmed = dependency.trim();
|
|
399
399
|
const nameMatch = PEP508_NAME_REGEX.exec(trimmed);
|
|
400
400
|
if (nameMatch) {
|
|
401
|
-
const
|
|
402
|
-
return toDependencyLd(nameMatch[0],
|
|
401
|
+
const dependencyVersion = trimmed.slice(nameMatch[0].length).trim();
|
|
402
|
+
return toDependencyLd(nameMatch[0], dependencyVersion.length > 0 ? dependencyVersion : void 0);
|
|
403
403
|
}
|
|
404
404
|
return toDependencyLd(trimmed);
|
|
405
405
|
}
|
|
406
406
|
/**
|
|
407
407
|
* Extract URL from package.json repository field (string or {url}).
|
|
408
408
|
*/
|
|
409
|
-
function
|
|
410
|
-
if (
|
|
411
|
-
if (typeof
|
|
412
|
-
return
|
|
409
|
+
function repoUrlFromPackageJson(repo) {
|
|
410
|
+
if (repo === void 0) return;
|
|
411
|
+
if (typeof repo === "string") return repo;
|
|
412
|
+
return repo.url;
|
|
413
413
|
}
|
|
414
414
|
/**
|
|
415
415
|
* Extract URL from package.json bugs field.
|
|
@@ -442,6 +442,15 @@ function resolveCmLicense(cmLicense) {
|
|
|
442
442
|
return Array.isArray(cmLicense) ? cmLicense[0] : cmLicense;
|
|
443
443
|
}
|
|
444
444
|
/**
|
|
445
|
+
* Parse a copyright year string to a leading integer year, or undefined when it
|
|
446
|
+
* contains no parseable year (0 and NaN both collapse to undefined).
|
|
447
|
+
*/
|
|
448
|
+
function toCopyrightYear(copyrightYear) {
|
|
449
|
+
if (!is.nonEmptyStringAndNotWhitespace(copyrightYear)) return;
|
|
450
|
+
const year = Number.parseInt(copyrightYear, 10);
|
|
451
|
+
return year === 0 || Number.isNaN(year) ? void 0 : year;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
445
454
|
* Deduplicate strings case-insensitively, preserving first occurrence casing.
|
|
446
455
|
*/
|
|
447
456
|
function deduplicateStrings(strings) {
|
|
@@ -450,7 +459,7 @@ function deduplicateStrings(strings) {
|
|
|
450
459
|
const key = s.toLowerCase().trim();
|
|
451
460
|
if (key.length > 0 && !seen.has(key)) seen.set(key, s);
|
|
452
461
|
}
|
|
453
|
-
return
|
|
462
|
+
return seen.values().toArray();
|
|
454
463
|
}
|
|
455
464
|
/**
|
|
456
465
|
* Case-insensitive lookup in a string record (e.g. pyproject.toml
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Template } from "../metadata-types.js";
|
|
2
|
+
import "../index.js";
|
|
2
3
|
//#region src/lib/templates/frontmatter.d.ts
|
|
3
4
|
type TemplateDataFrontmatter = ReturnType<typeof frontmatter>;
|
|
4
5
|
/**
|
|
@@ -18,7 +19,7 @@ declare const frontmatter: Template<{
|
|
|
18
19
|
Public: boolean;
|
|
19
20
|
Fork: boolean;
|
|
20
21
|
Published: boolean;
|
|
21
|
-
Status: "
|
|
22
|
+
Status: "author" | "maintainer" | "unknown" | "observer";
|
|
22
23
|
Tags: string[] | null;
|
|
23
24
|
Aliases: (string | null | undefined)[] | null;
|
|
24
25
|
License: string[] | null;
|
|
@@ -70,7 +70,7 @@ const frontmatter = defineTemplate((context, templateData) => {
|
|
|
70
70
|
Forks: github?.forkCount ?? null,
|
|
71
71
|
"Downloads Total": nodeNpmRegistry?.downloadsTotal ?? obsidianPluginRegistry?.downloadCount ?? pythonPypiRegistry?.downloads180Days ?? github?.releaseDownloadCount ?? null,
|
|
72
72
|
"Downloads Monthly": nodeNpmRegistry?.downloadsMonthly ?? pythonPypiRegistry?.downloadsMonthly ?? null,
|
|
73
|
-
CI: ciStatus ? titleCase(ciStatus)
|
|
73
|
+
CI: ciStatus === void 0 ? null : titleCase(ciStatus),
|
|
74
74
|
"CI URL": ciUrl ?? null,
|
|
75
75
|
Releases: github?.releaseCount ?? gitStats?.tagReleaseCount ?? null,
|
|
76
76
|
"Issues Open": github?.issueCountOpen ?? null,
|
|
@@ -5,6 +5,7 @@ import { TemplateDataCodemetaJson } from "./codemeta-json.js";
|
|
|
5
5
|
import { TemplateDataFrontmatter } from "./frontmatter.js";
|
|
6
6
|
import { TemplateDataMetadata } from "./metadata.js";
|
|
7
7
|
import { TemplateDataProject } from "./project.js";
|
|
8
|
+
import "../index.js";
|
|
8
9
|
//#region src/lib/templates/index.d.ts
|
|
9
10
|
/**
|
|
10
11
|
* Built-in templates, keyed by name.
|
|
@@ -157,7 +158,7 @@ declare const templates: {
|
|
|
157
158
|
Public: boolean;
|
|
158
159
|
Fork: boolean;
|
|
159
160
|
Published: boolean;
|
|
160
|
-
Status: "
|
|
161
|
+
Status: "author" | "maintainer" | "unknown" | "observer";
|
|
161
162
|
Tags: string[] | null;
|
|
162
163
|
Aliases: (string | null | undefined)[] | null;
|
|
163
164
|
License: string[] | null;
|
|
@@ -18,7 +18,7 @@ const templates = {
|
|
|
18
18
|
* Type guard
|
|
19
19
|
*/
|
|
20
20
|
function isKeyOfTemplate(value) {
|
|
21
|
-
return typeof value === "string" && value
|
|
21
|
+
return typeof value === "string" && Object.hasOwn(templates, value);
|
|
22
22
|
}
|
|
23
23
|
//#endregion
|
|
24
24
|
export { isKeyOfTemplate, templates };
|
|
@@ -42,36 +42,37 @@ function toPersonOrOrgLd(options) {
|
|
|
42
42
|
function deduplicatePersonsOrOrgs(persons) {
|
|
43
43
|
const seen = /* @__PURE__ */ new Map();
|
|
44
44
|
for (const person of persons) {
|
|
45
|
-
const
|
|
45
|
+
const fullName = [person.givenName, person.familyName].filter(Boolean).join(" ");
|
|
46
|
+
const key = (person.name ?? (fullName === "" ? void 0 : fullName) ?? person.email ?? "").toLowerCase().trim();
|
|
46
47
|
if (key.length > 0 && !seen.has(key)) seen.set(key, person);
|
|
47
48
|
}
|
|
48
|
-
const result =
|
|
49
|
+
const result = seen.values().toArray();
|
|
49
50
|
return result.length > 0 ? result : void 0;
|
|
50
51
|
}
|
|
51
52
|
/**
|
|
52
53
|
* Build a codemeta JSON-LD SoftwareApplication dependency node.
|
|
53
54
|
*/
|
|
54
55
|
function toDependencyLd(name, version, identifier, runtimePlatform) {
|
|
55
|
-
const
|
|
56
|
+
const dependency = {
|
|
56
57
|
"@type": "SoftwareApplication",
|
|
57
58
|
name
|
|
58
59
|
};
|
|
59
|
-
if (is.nonEmptyStringAndNotWhitespace(version))
|
|
60
|
-
if (is.nonEmptyStringAndNotWhitespace(identifier))
|
|
61
|
-
if (is.nonEmptyStringAndNotWhitespace(runtimePlatform))
|
|
62
|
-
return
|
|
60
|
+
if (is.nonEmptyStringAndNotWhitespace(version)) dependency.version = version;
|
|
61
|
+
if (is.nonEmptyStringAndNotWhitespace(identifier)) dependency.identifier = identifier;
|
|
62
|
+
if (is.nonEmptyStringAndNotWhitespace(runtimePlatform)) dependency.runtimePlatform = runtimePlatform;
|
|
63
|
+
return dependency;
|
|
63
64
|
}
|
|
64
65
|
/**
|
|
65
66
|
* Deduplicate dependencies by name (case-insensitive). Keeps the first
|
|
66
67
|
* occurrence. Returns undefined if the result is empty.
|
|
67
68
|
*/
|
|
68
|
-
function deduplicateDependencies(
|
|
69
|
+
function deduplicateDependencies(dependencies) {
|
|
69
70
|
const seen = /* @__PURE__ */ new Map();
|
|
70
|
-
for (const
|
|
71
|
-
const key =
|
|
72
|
-
if (key.length > 0 && !seen.has(key)) seen.set(key,
|
|
71
|
+
for (const dependency of dependencies) {
|
|
72
|
+
const key = dependency.name.toLowerCase().trim();
|
|
73
|
+
if (key.length > 0 && !seen.has(key)) seen.set(key, dependency);
|
|
73
74
|
}
|
|
74
|
-
const result =
|
|
75
|
+
const result = seen.values().toArray();
|
|
75
76
|
return result.length > 0 ? result : void 0;
|
|
76
77
|
}
|
|
77
78
|
/**
|
|
@@ -81,7 +82,7 @@ function deduplicateDependencies(deps) {
|
|
|
81
82
|
function toSpdxLicenseUrl(spdxId) {
|
|
82
83
|
return `https://spdx.org/licenses/${spdxId.replace("https://spdx.org/licenses/", "").replace("http://spdx.org/licenses/", "")}`;
|
|
83
84
|
}
|
|
84
|
-
const SEE_LICENSE_IN_REGEX = /^see license in /
|
|
85
|
+
const SEE_LICENSE_IN_REGEX = /^see license in /iv;
|
|
85
86
|
/**
|
|
86
87
|
* Detect npm package.json sentinel license values that are not SPDX
|
|
87
88
|
* identifiers: `"UNLICENSED"` (proprietary, all rights reserved) and `"SEE
|
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
import { log } from "../log.js";
|
|
2
2
|
//#region src/lib/utilities/fetch.ts
|
|
3
|
+
const MIN_FETCH_INTERVAL_MS = 300;
|
|
4
|
+
let fetchChain = Promise.resolve();
|
|
5
|
+
let lastFetchStart = 0;
|
|
6
|
+
async function waitForFetchTurn() {
|
|
7
|
+
const previous = fetchChain;
|
|
8
|
+
const turn = (async () => {
|
|
9
|
+
await previous;
|
|
10
|
+
const wait = lastFetchStart + MIN_FETCH_INTERVAL_MS - Date.now();
|
|
11
|
+
if (wait > 0) await sleep(wait);
|
|
12
|
+
lastFetchStart = Date.now();
|
|
13
|
+
})();
|
|
14
|
+
fetchChain = turn;
|
|
15
|
+
return turn;
|
|
16
|
+
}
|
|
3
17
|
/**
|
|
4
18
|
* Fetch with automatic retries and exponential backoff. Retries on network
|
|
5
|
-
* errors and 429/5xx responses.
|
|
19
|
+
* errors and 429/5xx responses. Request starts are paced globally to stay under
|
|
20
|
+
* per-IP rate limits.
|
|
6
21
|
*/
|
|
7
22
|
async function fetchWithRetry(url, options, maxRetries = 5) {
|
|
8
23
|
let lastError;
|
|
9
24
|
for (let attempt = 0; attempt <= maxRetries; attempt++) try {
|
|
25
|
+
await waitForFetchTurn();
|
|
10
26
|
const response = await fetch(url, options);
|
|
11
27
|
if ((response.status === 429 || response.status >= 500) && attempt < maxRetries) {
|
|
12
28
|
const delay = getDelay(attempt, response);
|
|
@@ -28,7 +44,7 @@ async function fetchWithRetry(url, options, maxRetries = 5) {
|
|
|
28
44
|
function getDelay(attempt, response) {
|
|
29
45
|
const backoff = 1e3 * 2 ** attempt;
|
|
30
46
|
const retryAfter = response?.headers.get("retry-after");
|
|
31
|
-
if (retryAfter) {
|
|
47
|
+
if (retryAfter !== null && retryAfter !== void 0 && retryAfter !== "") {
|
|
32
48
|
const seconds = Number(retryAfter);
|
|
33
49
|
if (!Number.isNaN(seconds)) return Math.max(seconds * 1e3, backoff);
|
|
34
50
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_GET_METADATA_OPTIONS } from "../metadata-types.js";
|
|
2
2
|
import { relative } from "node:path";
|
|
3
3
|
//#region src/lib/utilities/formatting.ts
|
|
4
|
-
const URL_PROTOCOL_REGEX = /^[a-z]+:\/\//
|
|
4
|
+
const URL_PROTOCOL_REGEX = /^[a-z]+:\/\//iv;
|
|
5
5
|
/**
|
|
6
6
|
* Format an absolute path as either absolute or relative, based on the
|
|
7
7
|
* `absolute` option. When relative, paths identical to `basePath` are returned
|
|
@@ -16,10 +16,10 @@ function getGitHubRemoteFromConfig(remotes) {
|
|
|
16
16
|
});
|
|
17
17
|
for (const [, remote] of sorted) {
|
|
18
18
|
const { url } = remote;
|
|
19
|
-
if (
|
|
19
|
+
if (url === void 0 || url === "") continue;
|
|
20
20
|
try {
|
|
21
21
|
const parsed = gitUrlParse(url);
|
|
22
|
-
if (parsed.source === "github.com" && parsed.owner && parsed.name) return {
|
|
22
|
+
if (parsed.source === "github.com" && parsed.owner !== "" && parsed.name !== "") return {
|
|
23
23
|
owner: parsed.owner,
|
|
24
24
|
repo: parsed.name
|
|
25
25
|
};
|
|
@@ -15,10 +15,15 @@
|
|
|
15
15
|
* - YAML front matter stripping
|
|
16
16
|
*/
|
|
17
17
|
type LicenseMatch = {
|
|
18
|
-
/** Dice coefficient confidence score (0–1). */
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
/** Dice coefficient confidence score (0–1). */
|
|
19
|
+
confidence: number;
|
|
20
|
+
/** Full license name (e.g. "MIT License", "Apache License 2.0"). */
|
|
21
|
+
name: string;
|
|
22
|
+
/** Whether the license is OSI approved. */
|
|
23
|
+
osiApproved: boolean;
|
|
24
|
+
/** SPDX license identifier (e.g. "MIT", "Apache-2.0"). */
|
|
25
|
+
spdxId: string;
|
|
26
|
+
/** SPDX license URL. */
|
|
22
27
|
spdxUrl: string;
|
|
23
28
|
};
|
|
24
29
|
//#endregion
|