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,111 @@
1
+ import { defineTemplate } from "../metadata-types.js";
2
+ import { REPLACEMENTS, dependencyNames, firstOf, isValidUrl, mixedStringsToArray, nonEmpty, toAlias, toBasicLicenses, toBasicNames, toLocalUrl, toMb, toStatus } from "../utilities/template-helpers.js";
3
+ import { codeMetaJsonDataSchema } from "../sources/codemeta-json.js";
4
+ import { codemeta } from "./codemeta.js";
5
+ import is from "@sindresorhus/is";
6
+ //#region src/lib/templates/frontmatter.ts
7
+ /**
8
+ * A compact, non-nested, polyglot overview of the project.
9
+ * Designed for Obsidian frontmatter — flat keys with natural language names,
10
+ * blending all available sources into a single trackable snapshot.
11
+ */
12
+ const frontmatter = defineTemplate((context, templateData) => {
13
+ const codemetaTemplateOutput = codemeta(context, templateData);
14
+ const codemeta$1 = codeMetaJsonDataSchema.parse(codemetaTemplateOutput);
15
+ const codeStats = firstOf(context.codeStats)?.data;
16
+ const dependencyUpdates = firstOf(context.dependencyUpdates);
17
+ const fileStats = firstOf(context.fileStats)?.data;
18
+ const cinderCinderblockXml = firstOf(context.cinderCinderblockXml)?.data;
19
+ const github = firstOf(context.github)?.data;
20
+ const gitStats = firstOf(context.gitStats)?.data;
21
+ const metascope = context.metascope?.data;
22
+ const nodeNpmRegistry = firstOf(context.nodeNpmRegistry)?.data;
23
+ const obsidianPluginManifestJson = firstOf(context.obsidianPluginManifestJson)?.data;
24
+ const obsidianPluginRegistry = firstOf(context.obsidianPluginRegistry)?.data;
25
+ const pythonPypiRegistry = firstOf(context.pythonPypiRegistry)?.data;
26
+ const primaryLanguages = mixedStringsToArray(codemeta$1.programmingLanguage ?? github?.primaryLanguage, REPLACEMENTS) ?? null;
27
+ const secondaryLanguages = mixedStringsToArray(codeStats?.total?.languages, REPLACEMENTS)?.filter((value) => !primaryLanguages?.includes(value)) ?? null;
28
+ const rawName = codemeta$1.name === "undefined" ? null : cinderCinderblockXml === void 0 ? codemeta$1.name : `Cinder ${codemeta$1.name}`;
29
+ const id = codemeta$1.identifier ?? rawName;
30
+ const name = is.nonEmptyString(rawName) ? toAlias(rawName) : void 0;
31
+ const aliases = id === name ? void 0 : id;
32
+ return {
33
+ Name: name ?? null,
34
+ ID: id ?? null,
35
+ Description: codemeta$1.description ?? null,
36
+ Author: mixedStringsToArray(toBasicNames(codemeta$1.author)) ?? null,
37
+ Contributor: mixedStringsToArray(toBasicNames(codemeta$1.contributor)) ?? null,
38
+ Maintainer: mixedStringsToArray(toBasicNames(codemeta$1.maintainer)) ?? null,
39
+ Version: codemeta$1.version ?? null,
40
+ Account: github?.ownerLogin ?? null,
41
+ Public: !(github?.isPrivate ?? false),
42
+ Fork: github?.isFork ?? false,
43
+ Published: Boolean(obsidianPluginRegistry?.url ?? nodeNpmRegistry?.url ?? pythonPypiRegistry?.url),
44
+ Status: toStatus(codemeta$1.codeRepository, codemeta$1.author, [...codemeta$1.contributor ?? [], ...codemeta$1.maintainer ?? []], github?.isFork ?? false, templateData.authorName, templateData.githubAccount),
45
+ Tags: codemeta$1.keywords ?? null,
46
+ Aliases: nonEmpty([aliases]) ?? null,
47
+ License: toBasicLicenses(codemeta$1.license) ?? null,
48
+ Language: primaryLanguages,
49
+ "Secondary Language": secondaryLanguages,
50
+ "Repo Path": metascope?.options.path === void 0 ? null : `file://${metascope.options.path}`,
51
+ "VS Code Path": metascope?.options.path === void 0 ? null : `vscode://file/${metascope.options.path}`,
52
+ "Readme Path": toLocalUrl(codemeta$1.readme, metascope?.options.path) ?? null,
53
+ "Homepage URL": codemeta$1.url !== void 0 && !codemeta$1.url.startsWith("https://github.com/") ? codemeta$1.url : null,
54
+ "Repo URL": codemeta$1.codeRepository ?? github?.url ?? null,
55
+ "Issues URL": codemeta$1.issueTracker ?? null,
56
+ "Readme URL": codemeta$1.readme !== void 0 && isValidUrl(codemeta$1.readme) ? codemeta$1.readme : null,
57
+ "Package URL": obsidianPluginRegistry?.url ?? nodeNpmRegistry?.url ?? pythonPypiRegistry?.url ?? null,
58
+ Created: codemeta$1.dateCreated ?? null,
59
+ "First Commit Date": gitStats?.commitDateFirst ?? null,
60
+ "Latest Commit Date": gitStats?.commitDateLast ?? null,
61
+ "Latest Push Date": github?.pushedAt ?? null,
62
+ "Latest Release Date": github?.releaseDateLatest ?? nodeNpmRegistry?.publishDateLatest ?? pythonPypiRegistry?.publishDateLatest ?? gitStats?.tagVersionDateLatest ?? null,
63
+ "Latest Release Version": obsidianPluginManifestJson?.version ?? nodeNpmRegistry?.versionLatest ?? pythonPypiRegistry?.versionLatest ?? github?.releaseVersionLatest ?? gitStats?.tagVersionLatest ?? null,
64
+ Stars: github?.stargazerCount ?? null,
65
+ Watchers: github?.watcherCount ?? null,
66
+ Contributors: github?.contributorCount ?? gitStats?.contributorCount ?? null,
67
+ Forks: github?.forkCount ?? null,
68
+ "Downloads Total": nodeNpmRegistry?.downloadsTotal ?? obsidianPluginRegistry?.downloadCount ?? pythonPypiRegistry?.downloads180Days ?? github?.releaseDownloadCount ?? null,
69
+ "Downloads Monthly": nodeNpmRegistry?.downloadsMonthly ?? pythonPypiRegistry?.downloadsMonthly ?? null,
70
+ Releases: github?.releaseCount ?? gitStats?.tagReleaseCount ?? null,
71
+ "Issues Open": github?.issueCountOpen ?? null,
72
+ "Issues Closed": github?.issueCountClosed ?? null,
73
+ "PRs Open": github?.pullRequestCountOpen ?? null,
74
+ "PRs Merged": github?.pullRequestCountMerged ?? null,
75
+ "PRs Closed": github?.pullRequestCountClosed ?? null,
76
+ "Vulnerability Alerts": github?.vulnerabilityAlertCount ?? null,
77
+ "Lines of Code": codeStats?.total?.code ?? null,
78
+ "Total Files": fileStats?.totalFileCount ?? null,
79
+ "Total Size MB": toMb(fileStats?.totalSizeBytes) ?? null,
80
+ "Tracked Files": gitStats?.trackedFileCount ?? null,
81
+ "Tracked Size MB": toMb(gitStats?.trackedSizeBytes) ?? null,
82
+ "GitHub Size MB": toMb(github?.diskUsageBytes) ?? null,
83
+ Dependencies: dependencyNames(codemeta$1, "prod") ?? null,
84
+ "Dev Dependencies": dependencyNames(codemeta$1, "dev") ?? null,
85
+ "Major Updates": dependencyUpdates?.data.major?.length ?? 0,
86
+ "Minor Updates": dependencyUpdates?.data.minor?.length ?? 0,
87
+ "Patch Updates": dependencyUpdates?.data.patch?.length ?? 0,
88
+ "Total Updates": dependencyUpdates?.extra?.total ?? 0,
89
+ Libyears: dependencyUpdates?.extra?.libyears ?? 0,
90
+ Runtime: codemeta$1.runtimePlatform ?? null,
91
+ "Operating System": codemeta$1.operatingSystem ?? null,
92
+ "Forked From": github?.forkedFrom ?? null,
93
+ "Fork Ahead": github?.commitsAheadUpstream ?? null,
94
+ "Fork Behind": github?.commitsBehindUpstream ?? null,
95
+ "Template From": github?.templateFrom ?? null,
96
+ Organization: github?.isInOrganization ?? false,
97
+ Monorepo: metascope?.workspaceDirectories === void 0 ? false : metascope.workspaceDirectories.length > 0,
98
+ "Git Commits": gitStats?.commitCount ?? null,
99
+ "Git Dirty Files": gitStats?.uncommittedFileCount ?? null,
100
+ "Git Remotes Ahead": gitStats?.totalAhead ?? null,
101
+ "Git Remotes Behind": gitStats?.totalBehind ?? null,
102
+ "Git LFS": gitStats?.hasLfs ?? github?.hasLfs ?? false,
103
+ "Git Tags": gitStats?.tagCount ?? null,
104
+ "Git Current Branch": gitStats?.branchCurrent ?? null,
105
+ "Git Branches": gitStats?.branchCount ?? null,
106
+ "Git Remotes": gitStats?.remoteCount ?? null,
107
+ "Git Submodules": gitStats?.submoduleCount ?? 0
108
+ };
109
+ });
110
+ //#endregion
111
+ export { frontmatter };
@@ -0,0 +1,181 @@
1
+ import { Template } from "../metadata-types.js";
2
+ import { CodemetaDependencyLd, CodemetaPersonOrOrgLd } from "../utilities/codemeta-helpers.js";
3
+ import { TemplateDataCodemeta } from "./codemeta.js";
4
+ import { TemplateDataFrontmatter } from "./frontmatter.js";
5
+ import { TemplateDataMetadata } from "./metadata.js";
6
+ import { TemplateDataProject } from "./project.js";
7
+ //#region src/lib/templates/index.d.ts
8
+ /**
9
+ * Built-in templates, keyed by name.
10
+ */
11
+ declare const templates: {
12
+ codemeta: Template<{
13
+ '@context': string;
14
+ '@type': string;
15
+ applicationCategory: string | undefined;
16
+ applicationSubCategory: string | undefined;
17
+ author: CodemetaPersonOrOrgLd[] | undefined;
18
+ buildInstructions: string | undefined;
19
+ codeRepository: string | undefined;
20
+ continuousIntegration: string | undefined;
21
+ contributor: CodemetaPersonOrOrgLd[] | undefined;
22
+ copyrightHolder: CodemetaPersonOrOrgLd[] | undefined;
23
+ copyrightYear: number | undefined;
24
+ dateCreated: string | undefined;
25
+ dateModified: string | undefined;
26
+ datePublished: string | undefined;
27
+ description: string | undefined;
28
+ developmentStatus: string | undefined;
29
+ downloadUrl: string | undefined;
30
+ funder: CodemetaPersonOrOrgLd[] | undefined;
31
+ funding: string | undefined;
32
+ identifier: string | undefined;
33
+ installUrl: string | undefined;
34
+ isAccessibleForFree: boolean | undefined;
35
+ issueTracker: string | undefined;
36
+ keywords: string[] | undefined;
37
+ license: string | undefined;
38
+ maintainer: CodemetaPersonOrOrgLd[] | undefined;
39
+ name: string | undefined;
40
+ operatingSystem: string[] | undefined;
41
+ programmingLanguage: string[] | undefined;
42
+ readme: string | undefined;
43
+ relatedLink: string | string[] | undefined;
44
+ releaseNotes: string | undefined;
45
+ runtimePlatform: string[] | undefined;
46
+ softwareHelp: string | undefined;
47
+ softwareRequirements: CodemetaDependencyLd[] | undefined;
48
+ softwareSuggestions: CodemetaDependencyLd[] | undefined;
49
+ targetProduct: Record<string, string> | undefined;
50
+ url: string | undefined;
51
+ version: string | undefined;
52
+ }>;
53
+ frontmatter: Template<{
54
+ Name: string | null;
55
+ ID: string | null;
56
+ Description: string | null;
57
+ Author: string[] | null;
58
+ Contributor: string[] | null;
59
+ Maintainer: string[] | null;
60
+ Version: string | null;
61
+ Account: string | null;
62
+ Public: boolean;
63
+ Fork: boolean;
64
+ Published: boolean;
65
+ Status: "unknown" | "maintainer" | "author" | "observer";
66
+ Tags: string[] | null;
67
+ Aliases: (string | null | undefined)[] | null;
68
+ License: string[] | null;
69
+ Language: string[] | null;
70
+ 'Secondary Language': string[] | null;
71
+ 'Repo Path': string | null;
72
+ 'VS Code Path': string | null;
73
+ 'Readme Path': string | null;
74
+ 'Homepage URL': string | null;
75
+ 'Repo URL': string | null;
76
+ 'Issues URL': string | null;
77
+ 'Readme URL': string | null;
78
+ 'Package URL': string | null;
79
+ Created: string | null;
80
+ 'First Commit Date': string | null;
81
+ 'Latest Commit Date': string | null;
82
+ 'Latest Push Date': string | null;
83
+ 'Latest Release Date': string | null;
84
+ 'Latest Release Version': string | null;
85
+ Stars: number | null;
86
+ Watchers: number | null;
87
+ Contributors: number | null;
88
+ Forks: number | null;
89
+ 'Downloads Total': number | null;
90
+ 'Downloads Monthly': number | null;
91
+ Releases: number | null;
92
+ 'Issues Open': number | null;
93
+ 'Issues Closed': number | null;
94
+ 'PRs Open': number | null;
95
+ 'PRs Merged': number | null;
96
+ 'PRs Closed': number | null;
97
+ 'Vulnerability Alerts': number | null;
98
+ 'Lines of Code': number | null;
99
+ 'Total Files': number | null;
100
+ 'Total Size MB': number | null;
101
+ 'Tracked Files': number | null;
102
+ 'Tracked Size MB': number | null;
103
+ 'GitHub Size MB': number | null;
104
+ Dependencies: string[] | null;
105
+ 'Dev Dependencies': string[] | null;
106
+ 'Major Updates': number;
107
+ 'Minor Updates': number;
108
+ 'Patch Updates': number;
109
+ 'Total Updates': number;
110
+ Libyears: number;
111
+ Runtime: string[] | null;
112
+ 'Operating System': string[] | null;
113
+ 'Forked From': string | null;
114
+ 'Fork Ahead': number | null;
115
+ 'Fork Behind': number | null;
116
+ 'Template From': string | null;
117
+ Organization: boolean;
118
+ Monorepo: boolean;
119
+ 'Git Commits': number | null;
120
+ 'Git Dirty Files': number | null;
121
+ 'Git Remotes Ahead': number | null;
122
+ 'Git Remotes Behind': number | null;
123
+ 'Git LFS': boolean;
124
+ 'Git Tags': number | null;
125
+ 'Git Current Branch': string | null;
126
+ 'Git Branches': number | null;
127
+ 'Git Remotes': number | null;
128
+ 'Git Submodules': number;
129
+ }>;
130
+ metadata: Template<{
131
+ description: string | undefined;
132
+ homepage: string | undefined;
133
+ topics: string[] | undefined;
134
+ }>;
135
+ project: Template<{
136
+ description: string | undefined;
137
+ firstCommitDate: string | undefined;
138
+ gitHubLink: string | undefined;
139
+ gitHubStarCount: number | undefined;
140
+ gitIsClean: boolean | undefined;
141
+ gitIsDirty: boolean | undefined;
142
+ gitRemoteCount: number | undefined;
143
+ homepage: string | undefined;
144
+ isAuthoredByMe: boolean | undefined;
145
+ isOnMyGitHub: boolean | undefined;
146
+ isOnNpm: boolean;
147
+ isPublic: boolean;
148
+ isRemoteAhead: boolean | undefined;
149
+ issueCount: number | undefined;
150
+ lastCommitDate: string | undefined;
151
+ license: string | undefined;
152
+ majorUpdateCount: number;
153
+ majorUpdateList: string[] | undefined;
154
+ npmDownloadCount: number | undefined;
155
+ readmePath: string | undefined;
156
+ repositoryPath: string | undefined;
157
+ semverUpdateCount: undefined;
158
+ semverUpdateList: undefined;
159
+ tags: string[] | undefined;
160
+ title: string | undefined;
161
+ type: "source" | "fork" | "unmaintained" | undefined;
162
+ usesPnpm: boolean;
163
+ usesSharedConfig: boolean;
164
+ version: string | undefined;
165
+ }>;
166
+ };
167
+ /**
168
+ * Maps built-in template names to their return types.
169
+ */
170
+ type TemplateMap = {
171
+ codemeta: TemplateDataCodemeta;
172
+ frontmatter: TemplateDataFrontmatter;
173
+ metadata: TemplateDataMetadata;
174
+ project: TemplateDataProject;
175
+ };
176
+ /**
177
+ * Names of built-in templates.
178
+ */
179
+ type TemplateName = keyof TemplateMap;
180
+ //#endregion
181
+ export { TemplateMap, TemplateName, templates };
@@ -0,0 +1,22 @@
1
+ import { codemeta } from "./codemeta.js";
2
+ import { frontmatter } from "./frontmatter.js";
3
+ import { metadata } from "./metadata.js";
4
+ import { project } from "./project.js";
5
+ //#region src/lib/templates/index.ts
6
+ /**
7
+ * Built-in templates, keyed by name.
8
+ */
9
+ const templates = {
10
+ codemeta,
11
+ frontmatter,
12
+ metadata,
13
+ project
14
+ };
15
+ /**
16
+ * Type guard
17
+ */
18
+ function isKeyOfTemplate(value) {
19
+ return typeof value === "string" && value in templates;
20
+ }
21
+ //#endregion
22
+ export { isKeyOfTemplate, templates };
@@ -0,0 +1,17 @@
1
+ import { Template } from "../metadata-types.js";
2
+ //#region src/lib/templates/metadata.d.ts
3
+ type TemplateDataMetadata = ReturnType<typeof metadata>;
4
+ /**
5
+ * A minimal metadata template for populating a GitHub repository's
6
+ * description, homepage, and topics via metadata.json / metadata.yaml.
7
+ *
8
+ * Builds on the codemeta template for baseline values, then lets any
9
+ * metadata.json source fields override the result.
10
+ */
11
+ declare const metadata: Template<{
12
+ description: string | undefined;
13
+ homepage: string | undefined;
14
+ topics: string[] | undefined;
15
+ }>;
16
+ //#endregion
17
+ export { TemplateDataMetadata };
@@ -0,0 +1,35 @@
1
+ import { defineTemplate } from "../metadata-types.js";
2
+ import { firstOf } from "../utilities/template-helpers.js";
3
+ import { codeMetaJsonDataSchema } from "../sources/codemeta-json.js";
4
+ import { codemeta } from "./codemeta.js";
5
+ //#region src/lib/templates/metadata.ts
6
+ /**
7
+ * Strip `git+` prefix and `.git` suffix from a URL.
8
+ */
9
+ function normalizeGitUrl(url) {
10
+ if (url === void 0) return void 0;
11
+ let normalized = url;
12
+ if (normalized.startsWith("git+")) normalized = normalized.slice(4);
13
+ if (normalized.endsWith(".git")) normalized = normalized.slice(0, -4);
14
+ return normalized;
15
+ }
16
+ /**
17
+ * A minimal metadata template for populating a GitHub repository's
18
+ * description, homepage, and topics via metadata.json / metadata.yaml.
19
+ *
20
+ * Builds on the codemeta template for baseline values, then lets any
21
+ * metadata.json source fields override the result.
22
+ */
23
+ const metadata = defineTemplate((context, templateData) => {
24
+ const codemetaTemplateOutput = codemeta(context, templateData);
25
+ const codemeta$1 = codeMetaJsonDataSchema.parse(codemetaTemplateOutput);
26
+ const metadataFile = firstOf(context.metadataFile)?.data;
27
+ const homepage = metadataFile?.homepage ?? codemeta$1.url ?? codemeta$1.codeRepository;
28
+ return {
29
+ description: metadataFile?.description ?? codemeta$1.description,
30
+ homepage: normalizeGitUrl(homepage),
31
+ topics: metadataFile?.keywords ?? codemeta$1.keywords
32
+ };
33
+ });
34
+ //#endregion
35
+ export { metadata };
@@ -0,0 +1,39 @@
1
+ import { Template } from "../metadata-types.js";
2
+ //#region src/lib/templates/project.d.ts
3
+ type TemplateDataProject = ReturnType<typeof project>;
4
+ /**
5
+ * Legacy structure used in AllWork desktop app
6
+ */
7
+ declare const project: Template<{
8
+ description: string | undefined;
9
+ firstCommitDate: string | undefined;
10
+ gitHubLink: string | undefined;
11
+ gitHubStarCount: number | undefined;
12
+ gitIsClean: boolean | undefined;
13
+ gitIsDirty: boolean | undefined;
14
+ gitRemoteCount: number | undefined;
15
+ homepage: string | undefined;
16
+ isAuthoredByMe: boolean | undefined;
17
+ isOnMyGitHub: boolean | undefined;
18
+ isOnNpm: boolean;
19
+ isPublic: boolean;
20
+ isRemoteAhead: boolean | undefined;
21
+ issueCount: number | undefined;
22
+ lastCommitDate: string | undefined;
23
+ license: string | undefined;
24
+ majorUpdateCount: number;
25
+ majorUpdateList: string[] | undefined;
26
+ npmDownloadCount: number | undefined;
27
+ readmePath: string | undefined;
28
+ repositoryPath: string | undefined;
29
+ semverUpdateCount: undefined;
30
+ semverUpdateList: undefined;
31
+ tags: string[] | undefined;
32
+ title: string | undefined;
33
+ type: "source" | "fork" | "unmaintained" | undefined;
34
+ usesPnpm: boolean;
35
+ usesSharedConfig: boolean;
36
+ version: string | undefined;
37
+ }>;
38
+ //#endregion
39
+ export { TemplateDataProject };
@@ -0,0 +1,51 @@
1
+ import { defineTemplate } from "../metadata-types.js";
2
+ import { firstOf, hasDependencyWithId, isAuthoredBy, isOnGithubAccountOf, toBasicLicenses, toLocalUrl, toStatusLegacy, usesPnpm } from "../utilities/template-helpers.js";
3
+ import { codeMetaJsonDataSchema } from "../sources/codemeta-json.js";
4
+ import { codemeta } from "./codemeta.js";
5
+ //#region src/lib/templates/project.ts
6
+ /**
7
+ * Legacy structure used in AllWork desktop app
8
+ */
9
+ const project = defineTemplate((context, templateData) => {
10
+ const codemetaTemplateOutput = codemeta(context, templateData);
11
+ const codemeta$1 = codeMetaJsonDataSchema.parse(codemetaTemplateOutput);
12
+ const dependencyUpdates = firstOf(context.dependencyUpdates);
13
+ const github = firstOf(context.github)?.data;
14
+ const gitStats = firstOf(context.gitStats)?.data;
15
+ const metascope = context.metascope?.data;
16
+ const nodeNpmRegistry = firstOf(context.nodeNpmRegistry)?.data;
17
+ const nodePackageJson = firstOf(context.nodePackageJson);
18
+ return {
19
+ description: codemeta$1.description,
20
+ firstCommitDate: gitStats?.commitDateFirst,
21
+ gitHubLink: github?.url,
22
+ gitHubStarCount: github?.stargazerCount,
23
+ gitIsClean: gitStats?.isClean,
24
+ gitIsDirty: gitStats?.isDirty,
25
+ gitRemoteCount: gitStats?.remoteCount,
26
+ homepage: github?.homepageUrl ?? codemeta$1.url ?? github?.url,
27
+ isAuthoredByMe: isAuthoredBy(codemeta$1.author, templateData.authorName),
28
+ isOnMyGitHub: isOnGithubAccountOf(codemeta$1.codeRepository, templateData.githubAccount),
29
+ isOnNpm: nodeNpmRegistry?.url !== void 0,
30
+ isPublic: !(github?.isPrivate ?? false),
31
+ isRemoteAhead: gitStats?.isRemoteAhead,
32
+ issueCount: github?.issueCountOpen,
33
+ lastCommitDate: gitStats?.commitDateLast,
34
+ license: toBasicLicenses(codemeta$1.license ?? github?.licenseSpdxId)?.at(0),
35
+ majorUpdateCount: dependencyUpdates?.data.major?.length ?? 0,
36
+ majorUpdateList: dependencyUpdates?.data.major?.map((value) => value.name),
37
+ npmDownloadCount: nodeNpmRegistry?.downloadsTotal,
38
+ readmePath: toLocalUrl(codemeta$1.readme, metascope?.options.path),
39
+ repositoryPath: metascope?.options.path === void 0 ? void 0 : `file://${metascope.options.path}`,
40
+ semverUpdateCount: void 0,
41
+ semverUpdateList: void 0,
42
+ tags: codemeta$1.keywords,
43
+ title: codemeta$1.name,
44
+ type: toStatusLegacy(codemeta$1.codeRepository, codemeta$1.author, templateData.authorName, templateData.githubAccount),
45
+ usesPnpm: usesPnpm(nodePackageJson),
46
+ usesSharedConfig: hasDependencyWithId("@kitschpatrol/shared-config", codemeta$1),
47
+ version: codemeta$1.version
48
+ };
49
+ });
50
+ //#endregion
51
+ export { project };
@@ -0,0 +1,39 @@
1
+ //#region src/lib/utilities/codemeta-helpers.d.ts
2
+ /**
3
+ * Helpers for building codemeta JSON-LD objects.
4
+ *
5
+ * Provides type-safe constructors for Person/Organization and SoftwareApplication
6
+ * dependency nodes, plus deduplication and license URL normalization.
7
+ */
8
+ /**
9
+ * An Organization node in codemeta JSON-LD.
10
+ */
11
+ type CodemetaOrganizationLd = {
12
+ '@type': 'Organization';
13
+ name: string;
14
+ };
15
+ /**
16
+ * A Person or Organization node in codemeta JSON-LD.
17
+ */
18
+ type CodemetaPersonOrOrgLd = {
19
+ '@id'?: string;
20
+ '@type': 'Organization' | 'Person';
21
+ affiliation?: CodemetaOrganizationLd;
22
+ email?: string;
23
+ familyName?: string;
24
+ givenName?: string;
25
+ name?: string;
26
+ url?: string;
27
+ };
28
+ /**
29
+ * A software dependency node in codemeta JSON-LD.
30
+ */
31
+ type CodemetaDependencyLd = {
32
+ '@type': 'SoftwareApplication';
33
+ identifier?: string;
34
+ name: string;
35
+ runtimePlatform?: string;
36
+ version?: string;
37
+ };
38
+ //#endregion
39
+ export { CodemetaDependencyLd, CodemetaPersonOrOrgLd };
@@ -0,0 +1,83 @@
1
+ import is from "@sindresorhus/is";
2
+ //#region src/lib/utilities/codemeta-helpers.ts
3
+ /**
4
+ * Helpers for building codemeta JSON-LD objects.
5
+ *
6
+ * Provides type-safe constructors for Person/Organization and SoftwareApplication
7
+ * dependency nodes, plus deduplication and license URL normalization.
8
+ */
9
+ /**
10
+ * Build a codemeta JSON-LD Person or Organization from flexible inputs.
11
+ * Returns undefined if no identifying information (name, givenName+familyName, or email) is present.
12
+ *
13
+ * Works with person shapes from any metascope source — the caller maps
14
+ * source-specific field names into this common parameter object.
15
+ */
16
+ function toPersonOrOrgLd(options) {
17
+ const hasName = is.nonEmptyStringAndNotWhitespace(options.name);
18
+ const hasGivenName = is.nonEmptyStringAndNotWhitespace(options.givenName);
19
+ const hasFamilyName = is.nonEmptyStringAndNotWhitespace(options.familyName);
20
+ const hasEmail = is.nonEmptyStringAndNotWhitespace(options.email);
21
+ if (!hasName && !hasGivenName && !hasFamilyName && !hasEmail) return void 0;
22
+ const person = { "@type": options.type ?? "Person" };
23
+ if (is.nonEmptyStringAndNotWhitespace(options.id)) person["@id"] = options.id;
24
+ if (hasName) person.name = options.name;
25
+ if (hasGivenName) person.givenName = options.givenName;
26
+ if (hasFamilyName) person.familyName = options.familyName;
27
+ if (hasEmail) person.email = options.email;
28
+ if (is.nonEmptyStringAndNotWhitespace(options.url)) person.url = options.url;
29
+ if (is.nonEmptyStringAndNotWhitespace(options.affiliation)) person.affiliation = {
30
+ "@type": "Organization",
31
+ name: options.affiliation
32
+ };
33
+ return person;
34
+ }
35
+ /**
36
+ * Deduplicate persons by name (case-insensitive, trimmed).
37
+ * Keeps the first occurrence, so callers should place higher-priority sources first.
38
+ * Returns undefined if the result is empty.
39
+ */
40
+ function deduplicatePersonsOrOrgs(persons) {
41
+ const seen = /* @__PURE__ */ new Map();
42
+ for (const person of persons) {
43
+ const key = (person.name ?? ([person.givenName, person.familyName].filter(Boolean).join(" ") || void 0) ?? person.email ?? "").toLowerCase().trim();
44
+ if (key.length > 0 && !seen.has(key)) seen.set(key, person);
45
+ }
46
+ const result = [...seen.values()];
47
+ return result.length > 0 ? result : void 0;
48
+ }
49
+ /**
50
+ * Build a codemeta JSON-LD SoftwareApplication dependency node.
51
+ */
52
+ function toDependencyLd(name, version, identifier, runtimePlatform) {
53
+ const dep = {
54
+ "@type": "SoftwareApplication",
55
+ name
56
+ };
57
+ if (is.nonEmptyStringAndNotWhitespace(version)) dep.version = version;
58
+ if (is.nonEmptyStringAndNotWhitespace(identifier)) dep.identifier = identifier;
59
+ if (is.nonEmptyStringAndNotWhitespace(runtimePlatform)) dep.runtimePlatform = runtimePlatform;
60
+ return dep;
61
+ }
62
+ /**
63
+ * Deduplicate dependencies by name (case-insensitive).
64
+ * Keeps the first occurrence. Returns undefined if the result is empty.
65
+ */
66
+ function deduplicateDependencies(deps) {
67
+ const seen = /* @__PURE__ */ new Map();
68
+ for (const dep of deps) {
69
+ const key = dep.name.toLowerCase().trim();
70
+ if (key.length > 0 && !seen.has(key)) seen.set(key, dep);
71
+ }
72
+ const result = [...seen.values()];
73
+ return result.length > 0 ? result : void 0;
74
+ }
75
+ /**
76
+ * Normalize a license identifier to an SPDX URL.
77
+ * Handles bare SPDX IDs ("MIT") and existing SPDX URLs.
78
+ */
79
+ function toSpdxLicenseUrl(spdxId) {
80
+ return `https://spdx.org/licenses/${spdxId.replace("https://spdx.org/licenses/", "").replace("http://spdx.org/licenses/", "")}`;
81
+ }
82
+ //#endregion
83
+ export { deduplicateDependencies, deduplicatePersonsOrOrgs, toDependencyLd, toPersonOrOrgLd, toSpdxLicenseUrl };
@@ -0,0 +1,43 @@
1
+ import { log } from "../log.js";
2
+ //#region src/lib/utilities/fetch.ts
3
+ /**
4
+ * Fetch with automatic retries and exponential backoff.
5
+ * Retries on network errors and 429/5xx responses.
6
+ */
7
+ async function fetchWithRetry(url, options, maxRetries = 5) {
8
+ let lastError;
9
+ for (let attempt = 0; attempt <= maxRetries; attempt++) try {
10
+ const response = await fetch(url, options);
11
+ if ((response.status === 429 || response.status >= 500) && attempt < maxRetries) {
12
+ const delay = getDelay(attempt, response);
13
+ log.warn(`Fetch ${url} returned ${response.status}, retrying in ${delay}ms (attempt ${attempt + 1}/${maxRetries})`);
14
+ await sleep(delay);
15
+ continue;
16
+ }
17
+ return response;
18
+ } catch (error) {
19
+ lastError = error;
20
+ if (attempt < maxRetries) {
21
+ const delay = getDelay(attempt);
22
+ log.warn(`Fetch ${url} failed: ${error instanceof Error ? error.message : String(error)}, retrying in ${delay}ms (attempt ${attempt + 1}/${maxRetries})`);
23
+ await sleep(delay);
24
+ }
25
+ }
26
+ throw lastError;
27
+ }
28
+ function getDelay(attempt, response) {
29
+ const backoff = 1e3 * 2 ** attempt;
30
+ const retryAfter = response?.headers.get("retry-after");
31
+ if (retryAfter) {
32
+ const seconds = Number(retryAfter);
33
+ if (!Number.isNaN(seconds)) return Math.max(seconds * 1e3, backoff);
34
+ }
35
+ return backoff;
36
+ }
37
+ async function sleep(ms) {
38
+ return new Promise((resolve) => {
39
+ setTimeout(resolve, ms);
40
+ });
41
+ }
42
+ //#endregion
43
+ export { fetchWithRetry };
@@ -0,0 +1,28 @@
1
+ import { DEFAULT_GET_METADATA_OPTIONS } from "../metadata-types.js";
2
+ import { relative } from "node:path";
3
+ //#region src/lib/utilities/formatting.ts
4
+ /**
5
+ * Format an absolute path as either absolute or relative, based on the `absolute` option.
6
+ * When relative, paths identical to `basePath` are returned as `'.'`.
7
+ * Correctly handles Windows paths (normalizes to POSIX) and ignores URLs.
8
+ */
9
+ function formatPath(absolutePath, basePath, absolute = DEFAULT_GET_METADATA_OPTIONS.absolute) {
10
+ if (/^[a-z]+:\/\//i.test(absolutePath)) return absolutePath;
11
+ if (absolute) return absolutePath.replaceAll("\\", "/");
12
+ const relativePath = relative(basePath, absolutePath).replaceAll("\\", "/");
13
+ return relativePath === "" ? "." : relativePath;
14
+ }
15
+ /**
16
+ * Process an array of items in batches to avoid resource limits.
17
+ */
18
+ async function batchMap(items, mapper, batchSize = 50) {
19
+ const results = [];
20
+ for (let index = 0; index < items.length; index += batchSize) {
21
+ const chunk = items.slice(index, index + batchSize);
22
+ const chunkResults = await Promise.all(chunk.map(async (item) => mapper(item)));
23
+ results.push(...chunkResults);
24
+ }
25
+ return results;
26
+ }
27
+ //#endregion
28
+ export { batchMap, formatPath };