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.
Files changed (111) hide show
  1. package/dist/.DS_Store +0 -0
  2. package/dist/bin/cli.js +14 -14
  3. package/dist/lib/{chunk-DrSxFLj_.js → _virtual/_rolldown/runtime.js} +1 -1
  4. package/dist/lib/file-matching.js +152 -0
  5. package/dist/lib/index.d.ts +11 -1496
  6. package/dist/lib/index.js +6 -6215
  7. package/dist/lib/log.d.ts +11 -0
  8. package/dist/lib/log.js +20 -0
  9. package/dist/lib/metadata-types.d.ts +151 -0
  10. package/dist/lib/metadata-types.js +30 -0
  11. package/dist/lib/metadata.d.ts +16 -0
  12. package/dist/lib/metadata.js +235 -0
  13. package/dist/lib/package.js +5 -0
  14. package/dist/lib/parsers/configparser-parser.js +43 -0
  15. package/dist/lib/parsers/gemspec-parser.js +256 -0
  16. package/dist/lib/parsers/go-mod-parser.js +153 -0
  17. package/dist/lib/parsers/makefile-config-parser.js +102 -0
  18. package/dist/lib/parsers/properties-parser.js +31 -0
  19. package/dist/lib/parsers/rfc822-header-parser.js +48 -0
  20. package/dist/lib/parsers/setup-py-parser.js +173 -0
  21. package/dist/lib/source.d.ts +17 -0
  22. package/dist/lib/source.js +34 -0
  23. package/dist/lib/sources/arduino-library-properties.d.ts +45 -0
  24. package/dist/lib/sources/arduino-library-properties.js +208 -0
  25. package/dist/lib/sources/cinder-cinderblock-xml.d.ts +21 -0
  26. package/dist/lib/sources/cinder-cinderblock-xml.js +134 -0
  27. package/dist/lib/sources/code-stats.d.ts +14 -0
  28. package/dist/lib/sources/code-stats.js +40 -0
  29. package/dist/lib/sources/codemeta-json.d.ts +117 -0
  30. package/dist/lib/sources/codemeta-json.js +226 -0
  31. package/dist/lib/sources/dependency-updates.d.ts +22 -0
  32. package/dist/lib/sources/dependency-updates.js +132 -0
  33. package/dist/lib/sources/file-stats.d.ts +12 -0
  34. package/dist/lib/sources/file-stats.js +48 -0
  35. package/dist/lib/sources/git-config.d.ts +8 -0
  36. package/dist/lib/sources/git-config.js +21 -0
  37. package/dist/lib/sources/git-stats.d.ts +35 -0
  38. package/dist/lib/sources/git-stats.js +130 -0
  39. package/dist/lib/sources/github.d.ts +94 -0
  40. package/dist/lib/sources/github.js +399 -0
  41. package/dist/lib/sources/go-go-mod.d.ts +19 -0
  42. package/dist/lib/sources/go-go-mod.js +38 -0
  43. package/dist/lib/sources/go-goreleaser-yaml.d.ts +19 -0
  44. package/dist/lib/sources/go-goreleaser-yaml.js +152 -0
  45. package/dist/lib/sources/java-pom-xml.d.ts +52 -0
  46. package/dist/lib/sources/java-pom-xml.js +248 -0
  47. package/dist/lib/sources/license-file.d.ts +10 -0
  48. package/dist/lib/sources/license-file.js +26 -0
  49. package/dist/lib/sources/metadata-file.d.ts +14 -0
  50. package/dist/lib/sources/metadata-file.js +109 -0
  51. package/dist/lib/sources/metascope.d.ts +14 -0
  52. package/dist/lib/sources/metascope.js +35 -0
  53. package/dist/lib/sources/node-npm-registry.d.ts +19 -0
  54. package/dist/lib/sources/node-npm-registry.js +74 -0
  55. package/dist/lib/sources/node-package-json.d.ts +7 -0
  56. package/dist/lib/sources/node-package-json.js +27 -0
  57. package/dist/lib/sources/obsidian-plugin-manifest-json.d.ts +17 -0
  58. package/dist/lib/sources/obsidian-plugin-manifest-json.js +34 -0
  59. package/dist/lib/sources/obsidian-plugin-registry.d.ts +10 -0
  60. package/dist/lib/sources/obsidian-plugin-registry.js +44 -0
  61. package/dist/lib/sources/openframeworks-addon-config-mk.d.ts +17 -0
  62. package/dist/lib/sources/openframeworks-addon-config-mk.js +39 -0
  63. package/dist/lib/sources/openframeworks-install-xml.d.ts +20 -0
  64. package/dist/lib/sources/openframeworks-install-xml.js +153 -0
  65. package/dist/lib/sources/processing-library-properties.d.ts +44 -0
  66. package/dist/lib/sources/processing-library-properties.js +219 -0
  67. package/dist/lib/sources/processing-sketch-properties.d.ts +38 -0
  68. package/dist/lib/sources/processing-sketch-properties.js +185 -0
  69. package/dist/lib/sources/publiccode-yaml.d.ts +73 -0
  70. package/dist/lib/sources/publiccode-yaml.js +256 -0
  71. package/dist/lib/sources/python-pkg-info.d.ts +31 -0
  72. package/dist/lib/sources/python-pkg-info.js +115 -0
  73. package/dist/lib/sources/python-pypi-registry.d.ts +19 -0
  74. package/dist/lib/sources/python-pypi-registry.js +101 -0
  75. package/dist/lib/sources/python-pyproject-toml.d.ts +7 -0
  76. package/dist/lib/sources/python-pyproject-toml.js +30 -0
  77. package/dist/lib/sources/python-setup-cfg.d.ts +28 -0
  78. package/dist/lib/sources/python-setup-cfg.js +106 -0
  79. package/dist/lib/sources/python-setup-py.d.ts +28 -0
  80. package/dist/lib/sources/python-setup-py.js +48 -0
  81. package/dist/lib/sources/readme-file.d.ts +11 -0
  82. package/dist/lib/sources/readme-file.js +55 -0
  83. package/dist/lib/sources/ruby-gemspec.d.ts +44 -0
  84. package/dist/lib/sources/ruby-gemspec.js +62 -0
  85. package/dist/lib/sources/rust-cargo-toml.d.ts +40 -0
  86. package/dist/lib/sources/rust-cargo-toml.js +159 -0
  87. package/dist/lib/sources/xcode-info-plist.d.ts +22 -0
  88. package/dist/lib/sources/xcode-info-plist.js +199 -0
  89. package/dist/lib/sources/xcode-project-pbxproj.d.ts +21 -0
  90. package/dist/lib/sources/xcode-project-pbxproj.js +222 -0
  91. package/dist/lib/templates/codemeta.d.ts +47 -0
  92. package/dist/lib/templates/codemeta.js +494 -0
  93. package/dist/lib/templates/frontmatter.d.ts +87 -0
  94. package/dist/lib/templates/frontmatter.js +111 -0
  95. package/dist/lib/templates/index.d.ts +181 -0
  96. package/dist/lib/templates/index.js +22 -0
  97. package/dist/lib/templates/metadata.d.ts +17 -0
  98. package/dist/lib/templates/metadata.js +35 -0
  99. package/dist/lib/templates/project.d.ts +39 -0
  100. package/dist/lib/templates/project.js +51 -0
  101. package/dist/lib/utilities/codemeta-helpers.d.ts +39 -0
  102. package/dist/lib/utilities/codemeta-helpers.js +83 -0
  103. package/dist/lib/utilities/fetch.js +43 -0
  104. package/dist/lib/utilities/formatting.js +28 -0
  105. package/dist/lib/utilities/license-identification.js +141 -0
  106. package/dist/lib/utilities/schema-primitives.js +47 -0
  107. package/dist/lib/utilities/template-helpers.d.ts +135 -0
  108. package/dist/lib/utilities/template-helpers.js +310 -0
  109. package/dist/lib/utilities/tree-sitter-wasm.js +30 -0
  110. package/package.json +6 -6
  111. package/readme.md +62 -15
@@ -0,0 +1,19 @@
1
+ import { OneOrMany, SourceRecord } from "../source.js";
2
+ import { z } from "zod";
3
+
4
+ //#region src/lib/sources/go-goreleaser-yaml.d.ts
5
+ declare const goreleaserDataSchema: z.ZodObject<{
6
+ description: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
7
+ homepage: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
8
+ license: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
9
+ maintainer: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
10
+ operating_systems: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
11
+ project_name: 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
+ vendor: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
14
+ }, z.core.$strip>;
15
+ /** Parsed goreleaser metadata */
16
+ type Goreleaser = z.infer<typeof goreleaserDataSchema>;
17
+ type GoGoreleaserYamlData = OneOrMany<SourceRecord<Goreleaser>> | undefined;
18
+ //#endregion
19
+ export { GoGoreleaserYamlData };
@@ -0,0 +1,152 @@
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 { readFile } from "node:fs/promises";
5
+ import { resolve } from "node:path";
6
+ import is from "@sindresorhus/is";
7
+ import { z } from "zod";
8
+ import { parse } from "yaml";
9
+ //#region src/lib/sources/go-goreleaser-yaml.ts
10
+ const goreleaserDataSchema = z.object({
11
+ description: nonEmptyString,
12
+ homepage: optionalUrl,
13
+ license: nonEmptyString,
14
+ maintainer: nonEmptyString,
15
+ operating_systems: stringArray,
16
+ project_name: nonEmptyString,
17
+ repository_url: optionalUrl,
18
+ vendor: nonEmptyString
19
+ });
20
+ /** Map Go OS identifiers to human-readable names. */
21
+ const GOOS_MAP = {
22
+ aix: "AIX",
23
+ android: "Android",
24
+ darwin: "macOS",
25
+ dragonfly: "DragonFly BSD",
26
+ freebsd: "FreeBSD",
27
+ illumos: "illumos",
28
+ ios: "iOS",
29
+ js: "JavaScript",
30
+ linux: "Linux",
31
+ netbsd: "NetBSD",
32
+ openbsd: "OpenBSD",
33
+ plan9: "Plan 9",
34
+ solaris: "Solaris",
35
+ wasip1: "WASI",
36
+ windows: "Windows"
37
+ };
38
+ function isPlainObject(value) {
39
+ return typeof value === "object" && value !== null && !Array.isArray(value);
40
+ }
41
+ function isNonEmptyString(value) {
42
+ return typeof value === "string" && value.trim().length > 0;
43
+ }
44
+ /**
45
+ * Get the first non-empty string value of a given field from an array of
46
+ * package-manager section entries. Skips Go template strings (containing `{{`).
47
+ */
48
+ function firstString(sections, field) {
49
+ for (const section of sections) if (isPlainObject(section)) {
50
+ const value = section[field];
51
+ if (isNonEmptyString(value) && !value.includes("{{")) return value.trim();
52
+ }
53
+ }
54
+ /**
55
+ * Collect all section entries for a given key, handling both v1 singular
56
+ * and v2 plural forms.
57
+ */
58
+ function collectSections(data, ...keys) {
59
+ const result = [];
60
+ for (const key of keys) {
61
+ const value = data[key];
62
+ if (is.array(value)) result.push(...value);
63
+ else if (isPlainObject(value)) result.push(value);
64
+ }
65
+ return result;
66
+ }
67
+ /**
68
+ * Parse a .goreleaser.yml/.yaml file and return structured metadata.
69
+ *
70
+ * Aggregates metadata from multiple package-manager sections (nfpms, brews,
71
+ * scoops, snapcrafts, chocolateys, winget, aurs) with defined priority.
72
+ * Extracts operating systems from builds[].goos.
73
+ */
74
+ function parse$1(source) {
75
+ let data;
76
+ try {
77
+ data = parse(source);
78
+ } catch {
79
+ return;
80
+ }
81
+ if (!isPlainObject(data)) return void 0;
82
+ const result = {
83
+ description: void 0,
84
+ homepage: void 0,
85
+ license: void 0,
86
+ maintainer: void 0,
87
+ operating_systems: [],
88
+ project_name: void 0,
89
+ repository_url: void 0,
90
+ vendor: void 0
91
+ };
92
+ if (isNonEmptyString(data.project_name)) result.project_name = data.project_name;
93
+ const nfpms = collectSections(data, "nfpms", "nfpm");
94
+ const brews = collectSections(data, "brews", "brew", "homebrew_casks");
95
+ const snaps = collectSections(data, "snapcrafts", "snapcraft");
96
+ const scoops = collectSections(data, "scoops", "scoop");
97
+ const chocs = collectSections(data, "chocolateys", "chocolatey");
98
+ const winget = collectSections(data, "winget");
99
+ const aurs = collectSections(data, "aurs", "aur");
100
+ const krews = collectSections(data, "krews", "krew");
101
+ const allSections = [
102
+ ...nfpms,
103
+ ...brews,
104
+ ...snaps,
105
+ ...scoops,
106
+ ...chocs,
107
+ ...winget,
108
+ ...aurs,
109
+ ...krews
110
+ ];
111
+ result.description = firstString(allSections, "description") ?? firstString(snaps, "summary") ?? firstString(chocs, "summary") ?? firstString(winget, "short_description");
112
+ result.homepage = firstString(allSections, "homepage") ?? firstString(chocs, "project_url");
113
+ result.license = firstString(allSections, "license");
114
+ result.maintainer = firstString(nfpms, "maintainer") ?? firstString(aurs, "maintainer");
115
+ result.vendor = firstString(nfpms, "vendor") ?? firstString(chocs, "owners") ?? firstString(winget, "publisher");
116
+ if (isPlainObject(data.release)) {
117
+ const { release } = data;
118
+ if (isPlainObject(release.github)) {
119
+ const gh = release.github;
120
+ if (typeof gh.owner === "string" && typeof gh.name === "string") result.repository_url = `https://github.com/${gh.owner}/${gh.name}`;
121
+ } else if (isPlainObject(release.gitlab)) {
122
+ const gl = release.gitlab;
123
+ if (typeof gl.owner === "string" && typeof gl.name === "string") result.repository_url = `https://gitlab.com/${gl.owner}/${gl.name}`;
124
+ }
125
+ }
126
+ const goosSet = /* @__PURE__ */ new Set();
127
+ const builds = collectSections(data, "builds", "build");
128
+ for (const build of builds) if (isPlainObject(build)) {
129
+ const { goos } = build;
130
+ if (Array.isArray(goos)) {
131
+ for (const os of goos) if (typeof os === "string") goosSet.add(os.toLowerCase());
132
+ }
133
+ }
134
+ result.operating_systems = [...goosSet].map((os) => GOOS_MAP[os] ?? os.charAt(0).toUpperCase() + os.slice(1));
135
+ return goreleaserDataSchema.parse(result);
136
+ }
137
+ const goGoreleaserYamlSource = defineSource({
138
+ async discover(context) {
139
+ return getMatches(context.options, [".goreleaser.yml", ".goreleaser.yaml"]);
140
+ },
141
+ key: "goGoreleaserYaml",
142
+ async parse(input, context) {
143
+ const data = parse$1(await readFile(resolve(context.options.path, input), "utf8"));
144
+ if (data !== void 0) return {
145
+ data,
146
+ source: input
147
+ };
148
+ },
149
+ phase: 1
150
+ });
151
+ //#endregion
152
+ export { goGoreleaserYamlSource };
@@ -0,0 +1,52 @@
1
+ import { OneOrMany, SourceRecord } from "../source.js";
2
+ import { z } from "zod";
3
+
4
+ //#region src/lib/sources/java-pom-xml.d.ts
5
+ declare const pomXmlSchema: z.ZodObject<{
6
+ artifactId: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
7
+ ciManagementUrl: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
8
+ contributors: z.ZodArray<z.ZodObject<{
9
+ email: z.ZodOptional<z.ZodString>;
10
+ name: z.ZodString;
11
+ organization: z.ZodOptional<z.ZodString>;
12
+ url: z.ZodOptional<z.ZodString>;
13
+ }, z.core.$strip>>;
14
+ dependencies: z.ZodArray<z.ZodObject<{
15
+ artifactId: z.ZodString;
16
+ groupId: z.ZodString;
17
+ version: z.ZodOptional<z.ZodString>;
18
+ }, z.core.$strip>>;
19
+ description: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
20
+ devDependencies: z.ZodArray<z.ZodObject<{
21
+ artifactId: z.ZodString;
22
+ groupId: z.ZodString;
23
+ version: z.ZodOptional<z.ZodString>;
24
+ }, z.core.$strip>>;
25
+ developers: z.ZodArray<z.ZodObject<{
26
+ email: z.ZodOptional<z.ZodString>;
27
+ name: z.ZodString;
28
+ organization: z.ZodOptional<z.ZodString>;
29
+ url: z.ZodOptional<z.ZodString>;
30
+ }, z.core.$strip>>;
31
+ groupId: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
32
+ identifier: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
33
+ inceptionYear: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
34
+ issueManagementUrl: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
35
+ javaVersion: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
36
+ licenses: z.ZodArray<z.ZodObject<{
37
+ name: z.ZodOptional<z.ZodString>;
38
+ url: z.ZodOptional<z.ZodString>;
39
+ }, z.core.$strip>>;
40
+ name: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
41
+ organization: z.ZodOptional<z.ZodObject<{
42
+ name: z.ZodString;
43
+ url: z.ZodOptional<z.ZodString>;
44
+ }, z.core.$strip>>;
45
+ scmUrl: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
46
+ url: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
47
+ version: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
48
+ }, z.core.$strip>;
49
+ type PomXml = z.infer<typeof pomXmlSchema>;
50
+ type JavaPomXmlData = OneOrMany<SourceRecord<PomXml>> | undefined;
51
+ //#endregion
52
+ export { JavaPomXmlData };
@@ -0,0 +1,248 @@
1
+ import { getMatches } from "../file-matching.js";
2
+ import { defineSource } from "../source.js";
3
+ import { nonEmptyString, optionalUrl } from "../utilities/schema-primitives.js";
4
+ import { ensureArray } from "../utilities/template-helpers.js";
5
+ import { readFile } from "node:fs/promises";
6
+ import { resolve } from "node:path";
7
+ import is from "@sindresorhus/is";
8
+ import { z } from "zod";
9
+ import { XMLParser } from "fast-xml-parser";
10
+ //#region src/lib/sources/java-pom-xml.ts
11
+ /**
12
+ * Source and parser for Maven `pom.xml` files.
13
+ *
14
+ * Extracts project metadata from Maven POM (Project Object Model) files,
15
+ * including coordinates (groupId/artifactId), developers, contributors,
16
+ * licenses, dependencies (with test scope separation), SCM info, CI/issue
17
+ * management URLs, and organization details.
18
+ *
19
+ * Uses `fast-xml-parser` with namespace prefix removal and attribute ignoring.
20
+ */
21
+ const pomXmlPersonEntrySchema = z.object({
22
+ email: z.string().optional(),
23
+ name: z.string(),
24
+ organization: z.string().optional(),
25
+ url: z.string().optional()
26
+ });
27
+ const pomXmlLicenseEntrySchema = z.object({
28
+ name: z.string().optional(),
29
+ url: z.string().optional()
30
+ });
31
+ const pomXmlDependencyEntrySchema = z.object({
32
+ artifactId: z.string(),
33
+ groupId: z.string(),
34
+ version: z.string().optional()
35
+ });
36
+ const pomXmlOrganizationSchema = z.object({
37
+ name: z.string(),
38
+ url: z.string().optional()
39
+ });
40
+ const pomXmlSchema = z.object({
41
+ artifactId: nonEmptyString,
42
+ ciManagementUrl: optionalUrl,
43
+ contributors: z.array(pomXmlPersonEntrySchema),
44
+ dependencies: z.array(pomXmlDependencyEntrySchema),
45
+ description: nonEmptyString,
46
+ devDependencies: z.array(pomXmlDependencyEntrySchema),
47
+ developers: z.array(pomXmlPersonEntrySchema),
48
+ groupId: nonEmptyString,
49
+ identifier: nonEmptyString,
50
+ inceptionYear: nonEmptyString,
51
+ issueManagementUrl: optionalUrl,
52
+ javaVersion: nonEmptyString,
53
+ licenses: z.array(pomXmlLicenseEntrySchema),
54
+ name: nonEmptyString,
55
+ organization: pomXmlOrganizationSchema.optional(),
56
+ scmUrl: optionalUrl,
57
+ url: optionalUrl,
58
+ version: nonEmptyString
59
+ });
60
+ /**
61
+ * Parse a Maven `pom.xml` content string into a structured object.
62
+ * Returns undefined if the XML is malformed or missing the `<project>` root element.
63
+ */
64
+ function parse(content) {
65
+ const parser = new XMLParser({
66
+ ignoreAttributes: true,
67
+ parseTagValue: false,
68
+ removeNSPrefix: true
69
+ });
70
+ let data;
71
+ try {
72
+ const parsed = parser.parse(content);
73
+ if (!is.plainObject(parsed)) return void 0;
74
+ data = parsed;
75
+ } catch {
76
+ return;
77
+ }
78
+ if (!is.plainObject(data.project)) return void 0;
79
+ const { project } = data;
80
+ const groupId = getString(project.groupId);
81
+ const artifactId = getString(project.artifactId);
82
+ const { dependencies, devDependencies } = parseDependencies(project);
83
+ return pomXmlSchema.parse({
84
+ artifactId,
85
+ ciManagementUrl: getNestedUrl(project.ciManagement),
86
+ contributors: parsePersonEntries(project.contributors, "contributor"),
87
+ dependencies,
88
+ description: getString(project.description),
89
+ devDependencies,
90
+ developers: parsePersonEntries(project.developers, "developer"),
91
+ groupId,
92
+ identifier: groupId && artifactId ? `${groupId}.${artifactId}` : void 0,
93
+ inceptionYear: getString(project.inceptionYear),
94
+ issueManagementUrl: getNestedUrl(project.issueManagement),
95
+ javaVersion: parseJavaVersion(project),
96
+ licenses: parseLicenses(project),
97
+ name: resolveName(project, groupId, artifactId),
98
+ organization: parseOrganization(project),
99
+ scmUrl: parseScmUrl(project),
100
+ url: getString(project.url),
101
+ version: getString(project.version)
102
+ });
103
+ }
104
+ /**
105
+ * Get a trimmed non-empty string from a parsed XML value.
106
+ * Returns undefined for empty strings, non-strings, whitespace-only, or Maven variable references.
107
+ */
108
+ function getString(value) {
109
+ if (typeof value !== "string") return void 0;
110
+ const trimmed = value.trim();
111
+ if (trimmed.length === 0) return void 0;
112
+ return trimmed;
113
+ }
114
+ /**
115
+ * Get a string, additionally filtering out Maven variable references ($).
116
+ */
117
+ function getCleanString(value) {
118
+ const s = getString(value);
119
+ if (s?.includes("$")) return void 0;
120
+ return s;
121
+ }
122
+ /**
123
+ * Resolve Maven variable references in a project name.
124
+ */
125
+ function resolveName(project, groupId, artifactId) {
126
+ const name = getString(project.name);
127
+ if (!name) return void 0;
128
+ let resolved = name;
129
+ if (groupId) resolved = resolved.replaceAll("${project.groupId}", groupId);
130
+ if (artifactId) resolved = resolved.replaceAll("${project.artifactId}", artifactId);
131
+ return resolved;
132
+ }
133
+ /**
134
+ * Extract a URL from a nested object (e.g. `<ciManagement><url>...</url></ciManagement>`).
135
+ * Filters out Maven variable references.
136
+ */
137
+ function getNestedUrl(container) {
138
+ if (!is.plainObject(container)) return void 0;
139
+ return getCleanString(container.url);
140
+ }
141
+ /**
142
+ * Parse person entries (developers or contributors) from POM XML.
143
+ */
144
+ function parsePersonEntries(container, childKey) {
145
+ if (!is.plainObject(container)) return [];
146
+ const children = container[childKey];
147
+ const results = [];
148
+ for (const entry of ensureArray(children)) {
149
+ if (!is.plainObject(entry)) continue;
150
+ const name = getString(entry.name);
151
+ if (!name) continue;
152
+ results.push({
153
+ email: getString(entry.email),
154
+ name,
155
+ organization: getString(entry.organization),
156
+ url: getString(entry.url)
157
+ });
158
+ }
159
+ return results;
160
+ }
161
+ /**
162
+ * Parse license entries from `<licenses><license>...</license></licenses>`.
163
+ */
164
+ function parseLicenses(project) {
165
+ if (!is.plainObject(project.licenses)) return [];
166
+ const results = [];
167
+ for (const entry of ensureArray(project.licenses.license)) {
168
+ if (!is.plainObject(entry)) continue;
169
+ const name = getString(entry.name);
170
+ const url = getString(entry.url);
171
+ if (name ?? url) results.push({
172
+ name,
173
+ url
174
+ });
175
+ }
176
+ return results;
177
+ }
178
+ /**
179
+ * Parse dependencies, separating test-scope into devDependencies.
180
+ */
181
+ function parseDependencies(project) {
182
+ const dependencies = [];
183
+ const devDependencies = [];
184
+ if (!is.plainObject(project.dependencies)) return {
185
+ dependencies,
186
+ devDependencies
187
+ };
188
+ for (const entry of ensureArray(project.dependencies.dependency)) {
189
+ if (!is.plainObject(entry)) continue;
190
+ const groupId = getString(entry.groupId);
191
+ const artifactId = getString(entry.artifactId);
192
+ if (!groupId || !artifactId) continue;
193
+ const dep = {
194
+ artifactId,
195
+ groupId,
196
+ version: getCleanString(entry.version)
197
+ };
198
+ if (getString(entry.scope) === "test") devDependencies.push(dep);
199
+ else dependencies.push(dep);
200
+ }
201
+ return {
202
+ dependencies,
203
+ devDependencies
204
+ };
205
+ }
206
+ /**
207
+ * Parse SCM URL, filtering out Maven variable references.
208
+ */
209
+ function parseScmUrl(project) {
210
+ if (!is.plainObject(project.scm)) return void 0;
211
+ return getCleanString(project.scm.url);
212
+ }
213
+ /**
214
+ * Parse organization from `<organization>` element.
215
+ */
216
+ function parseOrganization(project) {
217
+ if (!is.plainObject(project.organization)) return void 0;
218
+ const name = getString(project.organization.name);
219
+ if (!name) return void 0;
220
+ return {
221
+ name,
222
+ url: getString(project.organization.url)
223
+ };
224
+ }
225
+ /**
226
+ * Extract Java version from project properties.
227
+ * Checks `java.version`, `maven.compiler.source`, and `java.compiler.source`.
228
+ */
229
+ function parseJavaVersion(project) {
230
+ if (!is.plainObject(project.properties)) return void 0;
231
+ return getCleanString(project.properties["java.version"]) ?? getCleanString(project.properties["maven.compiler.source"]) ?? getCleanString(project.properties["java.compiler.source"]);
232
+ }
233
+ const javaPomXmlSource = defineSource({
234
+ async discover(context) {
235
+ return getMatches(context.options, ["pom.xml"]);
236
+ },
237
+ key: "javaPomXml",
238
+ async parse(input, context) {
239
+ const data = parse(await readFile(resolve(context.options.path, input), "utf8"));
240
+ if (data !== void 0) return {
241
+ data,
242
+ source: input
243
+ };
244
+ },
245
+ phase: 1
246
+ });
247
+ //#endregion
248
+ export { javaPomXmlSource };
@@ -0,0 +1,10 @@
1
+ import { OneOrMany, SourceRecord } from "../source.js";
2
+
3
+ //#region src/lib/sources/license-file.d.ts
4
+ type LicenseMatch = {
5
+ /** Match confidence between 0 and 1. */confidence: number; /** SPDX license identifier (e.g. "MIT"). */
6
+ spdxId: string;
7
+ };
8
+ type LicenseFileData = OneOrMany<SourceRecord<LicenseMatch>> | undefined;
9
+ //#endregion
10
+ export { LicenseFileData };
@@ -0,0 +1,26 @@
1
+ import { getMatches } from "../file-matching.js";
2
+ import { defineSource } from "../source.js";
3
+ import { identifyLicense } from "../utilities/license-identification.js";
4
+ import { readFile } from "node:fs/promises";
5
+ import { resolve } from "node:path";
6
+ //#region src/lib/sources/license-file.ts
7
+ const licenseFileSource = defineSource({
8
+ async discover(context) {
9
+ return getMatches(context.options, ["{,un}licen{c,s}e{,.*}", "copying{,.lesser}{,.*}"]);
10
+ },
11
+ key: "licenseFile",
12
+ async parse(input, context) {
13
+ const match = identifyLicense(await readFile(resolve(context.options.path, input), "utf8"));
14
+ if (!match) return;
15
+ return {
16
+ data: {
17
+ confidence: match.confidence,
18
+ spdxId: match.spdxId
19
+ },
20
+ source: input
21
+ };
22
+ },
23
+ phase: 1
24
+ });
25
+ //#endregion
26
+ export { licenseFileSource };
@@ -0,0 +1,14 @@
1
+ import { OneOrMany, SourceRecord } from "../source.js";
2
+ import { z } from "zod";
3
+
4
+ //#region src/lib/sources/metadata-file.d.ts
5
+ declare const metadataSchema: z.ZodObject<{
6
+ description: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
7
+ homepage: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
8
+ keywords: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
9
+ repository: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
10
+ }, z.core.$strip>;
11
+ type Metadata = z.infer<typeof metadataSchema>;
12
+ type MetadataFileData = OneOrMany<SourceRecord<Metadata>> | undefined;
13
+ //#endregion
14
+ export { MetadataFileData };
@@ -0,0 +1,109 @@
1
+ import { getMatches } from "../file-matching.js";
2
+ import { defineSource } from "../source.js";
3
+ import { nonEmptyString, optionalUrl, parseJsonRecord, stringArray } from "../utilities/schema-primitives.js";
4
+ import { splitCommaSeparated } from "../utilities/template-helpers.js";
5
+ import { readFile } from "node:fs/promises";
6
+ import { resolve } from "node:path";
7
+ import is from "@sindresorhus/is";
8
+ import { z } from "zod";
9
+ import { parse } from "yaml";
10
+ //#region src/lib/sources/metadata-file.ts
11
+ /**
12
+ * Source and parser for custom `metadata.json` / `metadata.yaml` / `metadata.yml` files.
13
+ *
14
+ * This is a simple custom format with synonymous field names for common
15
+ * project metadata. It supports JSON and YAML formats.
16
+ *
17
+ * Field mapping (with fallback chains):
18
+ * description → description
19
+ * homepage | url | repository (normalized) | website → homepage
20
+ * keywords | tags | topics → keywords
21
+ * repository (normalized) → repository
22
+ */
23
+ const metadataSchema = z.object({
24
+ description: nonEmptyString,
25
+ homepage: optionalUrl,
26
+ keywords: stringArray,
27
+ repository: optionalUrl
28
+ });
29
+ /**
30
+ * Parse a metadata file content string into a structured object.
31
+ * The `format` parameter determines whether to parse as JSON or YAML.
32
+ * Returns undefined if the content is malformed or not an object.
33
+ */
34
+ function parse$1(content, format) {
35
+ let data;
36
+ if (format === "json") data = parseJsonRecord(content);
37
+ else try {
38
+ const parsed = parse(content);
39
+ data = is.plainObject(parsed) ? parsed : void 0;
40
+ } catch {
41
+ return;
42
+ }
43
+ if (data === void 0) return;
44
+ const repository = isString(data.repository) ? normalizeRepoUrl(data.repository) : void 0;
45
+ const homepage = nonEmpty(data.homepage) ?? nonEmpty(data.url) ?? repository ?? nonEmpty(data.website);
46
+ const keywords = parseKeywords(data.keywords) ?? parseKeywords(data.tags) ?? parseKeywords(data.topics) ?? [];
47
+ return metadataSchema.parse({
48
+ description: data.description,
49
+ homepage,
50
+ keywords,
51
+ repository
52
+ });
53
+ }
54
+ /** Return a trimmed string if the value is a non-empty string, else undefined. */
55
+ function nonEmpty(value) {
56
+ if (typeof value !== "string") return void 0;
57
+ const trimmed = value.trim();
58
+ return trimmed.length > 0 ? trimmed : void 0;
59
+ }
60
+ /** Type guard for strings. */
61
+ function isString(value) {
62
+ return typeof value === "string";
63
+ }
64
+ /** Normalize a repository URL by stripping git+ prefix and .git suffix. */
65
+ function normalizeRepoUrl(url) {
66
+ let normalized = url;
67
+ if (normalized.startsWith("git+")) normalized = normalized.slice(4);
68
+ if (normalized.endsWith(".git")) normalized = normalized.slice(0, -4);
69
+ return normalized;
70
+ }
71
+ /** Parse keywords from an array of strings or a comma-delimited string. */
72
+ function parseKeywords(value) {
73
+ if (typeof value === "string") {
74
+ const parsed = splitCommaSeparated(value);
75
+ return parsed.length > 0 ? parsed : void 0;
76
+ }
77
+ if (Array.isArray(value)) {
78
+ const strings = value.filter((v) => typeof v === "string");
79
+ return strings.length > 0 ? strings : void 0;
80
+ }
81
+ }
82
+ /** Determine the format of a metadata file by its extension. */
83
+ function getFormat(file) {
84
+ if (file.endsWith(".json")) return "json";
85
+ if (file.endsWith(".yaml") || file.endsWith(".yml")) return "yaml";
86
+ }
87
+ const metadataFileSource = defineSource({
88
+ async discover(context) {
89
+ return getMatches(context.options, [
90
+ "metadata.json",
91
+ "metadata.yaml",
92
+ "metadata.yml"
93
+ ]);
94
+ },
95
+ key: "metadataFile",
96
+ async parse(input, context) {
97
+ const format = getFormat(input);
98
+ if (format !== void 0) {
99
+ const data = parse$1(await readFile(resolve(context.options.path, input), "utf8"), format);
100
+ if (data !== void 0) return {
101
+ data,
102
+ source: input
103
+ };
104
+ }
105
+ },
106
+ phase: 1
107
+ });
108
+ //#endregion
109
+ export { metadataFileSource };
@@ -0,0 +1,14 @@
1
+ import { SourceRecord } from "../source.js";
2
+ import { GetMetadataBaseOptions } from "../metadata-types.js";
3
+
4
+ //#region src/lib/sources/metascope.d.ts
5
+ type MetascopeInfo = {
6
+ /** Total scan duration in milliseconds. */durationMs: number; /** Resolved options used for this scan (credentials excluded). */
7
+ options: Omit<GetMetadataBaseOptions, 'credentials'>; /** ISO 8601 timestamp of when the scan was performed. */
8
+ scannedAt: string; /** Version of the metascope library used. */
9
+ version: string; /** Workspaces Resolved */
10
+ workspaceDirectories: string[];
11
+ };
12
+ type MetascopeData = SourceRecord<MetascopeInfo> | undefined;
13
+ //#endregion
14
+ export { MetascopeData };
@@ -0,0 +1,35 @@
1
+ import { version } from "../package.js";
2
+ import { getWorkspaces } from "../file-matching.js";
3
+ import { formatPath } from "../utilities/formatting.js";
4
+ import { defineSource } from "../source.js";
5
+ //#region src/lib/sources/metascope.ts
6
+ const metascopeSource = defineSource({
7
+ async discover(context) {
8
+ return [context.options.path];
9
+ },
10
+ key: "metascope",
11
+ async parse(input, context) {
12
+ const { absolute, offline, path: basePath, recursive, respectIgnored, templateData, workspaces } = context.options;
13
+ return {
14
+ data: {
15
+ durationMs: 0,
16
+ options: {
17
+ absolute,
18
+ offline,
19
+ path: formatPath(basePath, basePath, absolute),
20
+ recursive,
21
+ respectIgnored,
22
+ templateData,
23
+ workspaces
24
+ },
25
+ scannedAt: (/* @__PURE__ */ new Date()).toISOString(),
26
+ version,
27
+ workspaceDirectories: getWorkspaces(basePath, workspaces).map((directory) => formatPath(directory, basePath, absolute))
28
+ },
29
+ source: input
30
+ };
31
+ },
32
+ phase: 1
33
+ });
34
+ //#endregion
35
+ export { metascopeSource };