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,11 @@
1
+ import { ILogBasic, ILogLayer } from "lognow";
2
+
3
+ //#region src/lib/log.d.ts
4
+ /**
5
+ * Set the logger instance for the module.
6
+ * Export this for library consumers to inject their own logger.
7
+ * @param logger - Accepts either a LogLayer instance or a Console- or Stream-like log target
8
+ */
9
+ declare function setLogger(logger?: ILogBasic | ILogLayer): void;
10
+ //#endregion
11
+ export { setLogger };
@@ -0,0 +1,20 @@
1
+ import { name } from "./package.js";
2
+ import { createLogger, injectionHelper } from "lognow";
3
+ //#region src/lib/log.ts
4
+ /**
5
+ * The default logger instance for the library.
6
+ */
7
+ let log = createLogger({
8
+ logToConsole: { showTime: false },
9
+ name
10
+ });
11
+ /**
12
+ * Set the logger instance for the module.
13
+ * Export this for library consumers to inject their own logger.
14
+ * @param logger - Accepts either a LogLayer instance or a Console- or Stream-like log target
15
+ */
16
+ function setLogger(logger) {
17
+ log = injectionHelper(logger);
18
+ }
19
+ //#endregion
20
+ export { log, setLogger };
@@ -0,0 +1,151 @@
1
+ import { ArduinoLibraryPropertiesData } from "./sources/arduino-library-properties.js";
2
+ import { CinderCinderblockXmlData } from "./sources/cinder-cinderblock-xml.js";
3
+ import { CodeStatsData } from "./sources/code-stats.js";
4
+ import { CodeMetaJsonData } from "./sources/codemeta-json.js";
5
+ import { DependencyUpdatesData } from "./sources/dependency-updates.js";
6
+ import { FileStatsData } from "./sources/file-stats.js";
7
+ import { GitConfigData } from "./sources/git-config.js";
8
+ import { GitStatsData } from "./sources/git-stats.js";
9
+ import { GitHubData } from "./sources/github.js";
10
+ import { GoGoModData } from "./sources/go-go-mod.js";
11
+ import { GoGoreleaserYamlData } from "./sources/go-goreleaser-yaml.js";
12
+ import { JavaPomXmlData } from "./sources/java-pom-xml.js";
13
+ import { LicenseFileData } from "./sources/license-file.js";
14
+ import { MetadataFileData } from "./sources/metadata-file.js";
15
+ import { MetascopeData } from "./sources/metascope.js";
16
+ import { NodeNpmRegistryData } from "./sources/node-npm-registry.js";
17
+ import { NodePackageJsonData } from "./sources/node-package-json.js";
18
+ import { ObsidianPluginManifestJsonData } from "./sources/obsidian-plugin-manifest-json.js";
19
+ import { ObsidianPluginRegistryData } from "./sources/obsidian-plugin-registry.js";
20
+ import { OpenframeworksAddonConfigMkData } from "./sources/openframeworks-addon-config-mk.js";
21
+ import { OpenframeworksInstallXmlData } from "./sources/openframeworks-install-xml.js";
22
+ import { ProcessingLibraryPropertiesData } from "./sources/processing-library-properties.js";
23
+ import { ProcessingSketchPropertiesData } from "./sources/processing-sketch-properties.js";
24
+ import { PubliccodeYamlData } from "./sources/publiccode-yaml.js";
25
+ import { PythonPkgInfoData } from "./sources/python-pkg-info.js";
26
+ import { PythonPypiRegistryData } from "./sources/python-pypi-registry.js";
27
+ import { PythonPyprojectTomlData } from "./sources/python-pyproject-toml.js";
28
+ import { PythonSetupCfgData } from "./sources/python-setup-cfg.js";
29
+ import { PythonSetupPyData } from "./sources/python-setup-py.js";
30
+ import { ReadmeFileData } from "./sources/readme-file.js";
31
+ import { RubyGemspecData } from "./sources/ruby-gemspec.js";
32
+ import { RustCargoTomlData } from "./sources/rust-cargo-toml.js";
33
+ import { XcodeInfoPlistData } from "./sources/xcode-info-plist.js";
34
+ import { XcodeProjectPbxprojData } from "./sources/xcode-project-pbxproj.js";
35
+
36
+ //#region src/lib/metadata-types.d.ts
37
+ /**
38
+ * The complete metadata context assembled from all sources.
39
+ * Each key corresponds to a metadata source.
40
+ */
41
+ type MetadataContext = {
42
+ arduinoLibraryProperties: ArduinoLibraryPropertiesData;
43
+ cinderCinderblockXml: CinderCinderblockXmlData;
44
+ codemetaJson: CodeMetaJsonData;
45
+ codeStats: CodeStatsData;
46
+ dependencyUpdates: DependencyUpdatesData;
47
+ fileStats: FileStatsData;
48
+ gitConfig: GitConfigData;
49
+ github: GitHubData;
50
+ gitStats: GitStatsData;
51
+ goGoMod: GoGoModData;
52
+ goGoreleaserYaml: GoGoreleaserYamlData;
53
+ javaPomXml: JavaPomXmlData;
54
+ licenseFile: LicenseFileData;
55
+ metadataFile: MetadataFileData;
56
+ metascope: MetascopeData;
57
+ nodeNpmRegistry: NodeNpmRegistryData;
58
+ nodePackageJson: NodePackageJsonData;
59
+ obsidianPluginManifestJson: ObsidianPluginManifestJsonData;
60
+ obsidianPluginRegistry: ObsidianPluginRegistryData;
61
+ openframeworksAddonConfigMk: OpenframeworksAddonConfigMkData;
62
+ openframeworksInstallXml: OpenframeworksInstallXmlData;
63
+ processingLibraryProperties: ProcessingLibraryPropertiesData;
64
+ processingSketchProperties: ProcessingSketchPropertiesData;
65
+ publiccodeYaml: PubliccodeYamlData;
66
+ pythonPkgInfo: PythonPkgInfoData;
67
+ pythonPypiRegistry: PythonPypiRegistryData;
68
+ pythonPyprojectToml: PythonPyprojectTomlData;
69
+ pythonSetupCfg: PythonSetupCfgData;
70
+ pythonSetupPy: PythonSetupPyData;
71
+ readmeFile: ReadmeFileData;
72
+ rubyGemspec: RubyGemspecData;
73
+ rustCargoToml: RustCargoTomlData;
74
+ xcodeInfoPlist: XcodeInfoPlistData;
75
+ xcodeProjectPbxproj: XcodeProjectPbxprojData;
76
+ };
77
+ /**
78
+ * The name of a metadata source.
79
+ */
80
+ type SourceName = keyof MetadataContext;
81
+ /**
82
+ * User-supplied data passed to templates for parameterized ownership checks.
83
+ * All fields are optional; templates that don't need them can ignore the argument.
84
+ */
85
+ type TemplateData = {
86
+ [key: string]: unknown;
87
+ authorName?: string | string[];
88
+ githubAccount?: string | string[];
89
+ };
90
+ /**
91
+ * A template function that transforms MetadataContext into a custom shape.
92
+ * The optional second argument provides user-supplied template data.
93
+ */
94
+ type Template<T> = (context: MetadataContext, templateData: TemplateData) => T;
95
+ /**
96
+ * Identity wrapper for type inference in config files.
97
+ * Use this in `metascope.config.ts` to get autocomplete on available fields.
98
+ * @example
99
+ * ```typescript
100
+ * import { defineTemplate } from 'metascope'
101
+ *
102
+ * export default defineTemplate(({ codemetaJson, github }) => ({
103
+ * name: codemetaJson?.data.name,
104
+ * stars: github?.data.stargazerCount,
105
+ * }))
106
+ * ```
107
+ */
108
+ declare function defineTemplate<T>(transform: Template<T>): Template<T>;
109
+ /**
110
+ * API credentials for remote metadata sources.
111
+ */
112
+ type Credentials = {
113
+ githubToken?: string;
114
+ };
115
+ /**
116
+ * Base options shared by all `getMetadata` overloads.
117
+ */
118
+ type GetMetadataBaseOptions = {
119
+ /** When true (the default), all paths in the output (source, workspaceDirectories, etc.) are absolute. When false, paths are relative to the project directory. */absolute?: boolean; /** API credentials for remote sources. */
120
+ credentials?: Credentials; /** Skip web sources (npm registry, GitHub API, PyPI, etc.). */
121
+ offline?: boolean; /** Project directory path. Defaults to `'.'` (resolved to `process.cwd()` via `path.resolve`). */
122
+ path: string; /** Search for metadata files recursively in subdirectories. Defaults to false. */
123
+ recursive?: boolean; /** Ignore files specified .gitignore in the file tree. Defaults to true. */
124
+ respectIgnored?: boolean; /** Only run these specific sources. Defaults to all sources when undefined. */
125
+ sources?: SourceName[]; /** User-supplied data passed to templates. */
126
+ templateData?: TemplateData;
127
+ /**
128
+ * Directories to any monorepo workspaces... only supports yarn, npm, pnpm, lerna, and bolt at the moment
129
+ * Never includes the root path!
130
+ * False is disable, true is auto-discover which turns into string[], string[] is manual list relative to the project directory path...
131
+ */
132
+ workspaces?: boolean | string[];
133
+ };
134
+ /**
135
+ * Default values for optional fields in `GetMetadataBaseOptions`.
136
+ */
137
+ declare const DEFAULT_GET_METADATA_OPTIONS: Required<Omit<GetMetadataBaseOptions, 'credentials' | 'sources' | 'templateData'>>;
138
+ /**
139
+ * Options for `getMetadata` without a template (returns full `MetadataContext`).
140
+ */
141
+ type GetMetadataOptions = GetMetadataBaseOptions & {
142
+ /** Built-in template name or omit for full output. */template?: 'frontmatter' | 'metadata' | 'project' | (string & {});
143
+ };
144
+ /**
145
+ * Options for `getMetadata` with a template function (returns the template's return type).
146
+ */
147
+ type GetMetadataTemplateOptions<T> = GetMetadataBaseOptions & {
148
+ /** Template function that transforms MetadataContext into a custom shape. */template: Template<T>;
149
+ };
150
+ //#endregion
151
+ export { Credentials, DEFAULT_GET_METADATA_OPTIONS, GetMetadataBaseOptions, GetMetadataOptions, GetMetadataTemplateOptions, MetadataContext, SourceName, Template, TemplateData, defineTemplate };
@@ -0,0 +1,30 @@
1
+ //#region src/lib/metadata-types.ts
2
+ /**
3
+ * Identity wrapper for type inference in config files.
4
+ * Use this in `metascope.config.ts` to get autocomplete on available fields.
5
+ * @example
6
+ * ```typescript
7
+ * import { defineTemplate } from 'metascope'
8
+ *
9
+ * export default defineTemplate(({ codemetaJson, github }) => ({
10
+ * name: codemetaJson?.data.name,
11
+ * stars: github?.data.stargazerCount,
12
+ * }))
13
+ * ```
14
+ */
15
+ function defineTemplate(transform) {
16
+ return transform;
17
+ }
18
+ /**
19
+ * Default values for optional fields in `GetMetadataBaseOptions`.
20
+ */
21
+ const DEFAULT_GET_METADATA_OPTIONS = {
22
+ absolute: true,
23
+ offline: false,
24
+ path: ".",
25
+ recursive: false,
26
+ respectIgnored: true,
27
+ workspaces: true
28
+ };
29
+ //#endregion
30
+ export { DEFAULT_GET_METADATA_OPTIONS, defineTemplate };
@@ -0,0 +1,16 @@
1
+ import { GetMetadataOptions, GetMetadataTemplateOptions, MetadataContext, SourceName } from "./metadata-types.js";
2
+ import { TemplateMap, TemplateName } from "./templates/index.js";
3
+
4
+ //#region src/lib/metadata.d.ts
5
+ /** All available source key names, for runtime use (e.g. CLI choices). */
6
+ declare const sourceNames: SourceName[];
7
+ type PartialPath<T> = Omit<T, 'path'> & {
8
+ path?: string;
9
+ };
10
+ declare function getMetadata<K extends TemplateName>(options: PartialPath<Omit<GetMetadataOptions, 'template'> & {
11
+ template: K;
12
+ }>): Promise<TemplateMap[K]>;
13
+ declare function getMetadata<T>(options: PartialPath<GetMetadataTemplateOptions<T>>): Promise<T>;
14
+ declare function getMetadata(options?: PartialPath<GetMetadataOptions>): Promise<MetadataContext>;
15
+ //#endregion
16
+ export { getMetadata, sourceNames };
@@ -0,0 +1,235 @@
1
+ import { log } from "./log.js";
2
+ import { getTree, resetMatchCache } from "./file-matching.js";
3
+ import { DEFAULT_GET_METADATA_OPTIONS } from "./metadata-types.js";
4
+ import { stripUndefined } from "./utilities/template-helpers.js";
5
+ import { arduinoLibraryPropertiesSource } from "./sources/arduino-library-properties.js";
6
+ import { cinderCinderblockXmlSource } from "./sources/cinder-cinderblock-xml.js";
7
+ import { codeStatsSource } from "./sources/code-stats.js";
8
+ import { codemetaJsonSource } from "./sources/codemeta-json.js";
9
+ import { dependencyUpdatesSource } from "./sources/dependency-updates.js";
10
+ import { fileStatsSource } from "./sources/file-stats.js";
11
+ import { gitConfigSource } from "./sources/git-config.js";
12
+ import { gitStatsSource } from "./sources/git-stats.js";
13
+ import { githubSource } from "./sources/github.js";
14
+ import { goGoModSource } from "./sources/go-go-mod.js";
15
+ import { goGoreleaserYamlSource } from "./sources/go-goreleaser-yaml.js";
16
+ import { javaPomXmlSource } from "./sources/java-pom-xml.js";
17
+ import { licenseFileSource } from "./sources/license-file.js";
18
+ import { metadataFileSource } from "./sources/metadata-file.js";
19
+ import { metascopeSource } from "./sources/metascope.js";
20
+ import { nodePackageJsonSource } from "./sources/node-package-json.js";
21
+ import { nodeNpmRegistrySource } from "./sources/node-npm-registry.js";
22
+ import { obsidianPluginManifestJsonSource } from "./sources/obsidian-plugin-manifest-json.js";
23
+ import { obsidianPluginRegistrySource } from "./sources/obsidian-plugin-registry.js";
24
+ import { openframeworksAddonConfigMkSource } from "./sources/openframeworks-addon-config-mk.js";
25
+ import { openframeworksInstallXmlSource } from "./sources/openframeworks-install-xml.js";
26
+ import { processingLibraryPropertiesSource } from "./sources/processing-library-properties.js";
27
+ import { processingSketchPropertiesSource } from "./sources/processing-sketch-properties.js";
28
+ import { publiccodeYamlSource } from "./sources/publiccode-yaml.js";
29
+ import { pythonPkgInfoSource } from "./sources/python-pkg-info.js";
30
+ import { pythonPyprojectTomlSource } from "./sources/python-pyproject-toml.js";
31
+ import { pythonSetupCfgSource } from "./sources/python-setup-cfg.js";
32
+ import { pythonSetupPySource } from "./sources/python-setup-py.js";
33
+ import { pythonPypiRegistrySource } from "./sources/python-pypi-registry.js";
34
+ import { readmeFileSource } from "./sources/readme-file.js";
35
+ import { rubyGemspecSource } from "./sources/ruby-gemspec.js";
36
+ import { rustCargoTomlSource } from "./sources/rust-cargo-toml.js";
37
+ import { xcodeInfoPlistSource } from "./sources/xcode-info-plist.js";
38
+ import { xcodeProjectPbxprojSource } from "./sources/xcode-project-pbxproj.js";
39
+ import { isKeyOfTemplate, templates } from "./templates/index.js";
40
+ import { defu } from "defu";
41
+ import { execFile } from "node:child_process";
42
+ import { stat } from "node:fs/promises";
43
+ import { resolve } from "node:path";
44
+ import { promisify } from "node:util";
45
+ import prettyMs from "pretty-ms";
46
+ //#region src/lib/metadata.ts
47
+ const execFileAsync = promisify(execFile);
48
+ /**
49
+ * All registered metadata sources.
50
+ * Each source declares its `phase` number. Sources with the same phase run in parallel.
51
+ * Lower phases run first, and their accumulated results are available to later phases
52
+ * via `context` in `SourceContext`.
53
+ */
54
+ const sources = [
55
+ arduinoLibraryPropertiesSource,
56
+ cinderCinderblockXmlSource,
57
+ codemetaJsonSource,
58
+ gitConfigSource,
59
+ goGoModSource,
60
+ goGoreleaserYamlSource,
61
+ javaPomXmlSource,
62
+ licenseFileSource,
63
+ metadataFileSource,
64
+ metascopeSource,
65
+ nodePackageJsonSource,
66
+ obsidianPluginManifestJsonSource,
67
+ openframeworksAddonConfigMkSource,
68
+ openframeworksInstallXmlSource,
69
+ processingLibraryPropertiesSource,
70
+ processingSketchPropertiesSource,
71
+ publiccodeYamlSource,
72
+ pythonPkgInfoSource,
73
+ pythonPyprojectTomlSource,
74
+ pythonSetupCfgSource,
75
+ pythonSetupPySource,
76
+ readmeFileSource,
77
+ rubyGemspecSource,
78
+ rustCargoTomlSource,
79
+ xcodeInfoPlistSource,
80
+ xcodeProjectPbxprojSource,
81
+ codeStatsSource,
82
+ dependencyUpdatesSource,
83
+ fileStatsSource,
84
+ gitStatsSource,
85
+ githubSource,
86
+ nodeNpmRegistrySource,
87
+ obsidianPluginRegistrySource,
88
+ pythonPypiRegistrySource
89
+ ];
90
+ /** All available source key names, for runtime use (e.g. CLI choices). */
91
+ const sourceNames = sources.map((s) => s.key);
92
+ /**
93
+ * Resolve GitHub token from multiple sources, in precedence order.
94
+ */
95
+ async function resolveCredentials(credentials) {
96
+ if (credentials?.githubToken) return credentials;
97
+ const environmentToken = process.env.GITHUB_TOKEN;
98
+ if (environmentToken) return {
99
+ ...credentials,
100
+ githubToken: environmentToken
101
+ };
102
+ try {
103
+ const { stdout } = await execFileAsync("gh", ["auth", "token"]);
104
+ const token = stdout.trim();
105
+ if (token) return {
106
+ ...credentials,
107
+ githubToken: token
108
+ };
109
+ } catch {}
110
+ return credentials ?? {};
111
+ }
112
+ /**
113
+ * Resolve a template option to a template function.
114
+ * Accepts a built-in template name (string) or a template function.
115
+ */
116
+ function resolveTemplate(template) {
117
+ if (template === void 0) return void 0;
118
+ if (typeof template === "function") return template;
119
+ if (isKeyOfTemplate(template)) return templates[template];
120
+ log.warn(`Unknown template: "${template}". Using default (all fields).`);
121
+ }
122
+ /**
123
+ * Check availability and extract data from a set of sources in parallel,
124
+ * writing results into the provided MetadataContext.
125
+ */
126
+ async function runSources(phaseSources, sourceContext, result) {
127
+ const extractResults = await Promise.all(phaseSources.map(async (source) => {
128
+ try {
129
+ const startTime = performance.now();
130
+ const data = await source.extract(sourceContext);
131
+ const duration = Math.round(performance.now() - startTime);
132
+ log.debug(`Source "${source.key}" extracted in ${duration}ms`);
133
+ return {
134
+ data,
135
+ key: source.key
136
+ };
137
+ } catch (error) {
138
+ log.warn(`Source "${source.key}" extraction failed: ${error instanceof Error ? error.message : String(error)}`);
139
+ return {
140
+ data: void 0,
141
+ key: source.key
142
+ };
143
+ }
144
+ }));
145
+ for (const entry of extractResults) if (entry.data !== void 0) Object.assign(result, { [entry.key]: entry.data });
146
+ }
147
+ /**
148
+ * Extract metadata from a project directory.
149
+ */
150
+ async function getMetadata(options) {
151
+ const startTime = performance.now();
152
+ const resolvedOptions = defu(options ?? {}, DEFAULT_GET_METADATA_OPTIONS);
153
+ const absolutePath = resolve(resolvedOptions.path);
154
+ let stats;
155
+ try {
156
+ stats = await stat(absolutePath);
157
+ } catch {
158
+ throw new Error(`Path does not exist: ${absolutePath}`);
159
+ }
160
+ if (!stats.isDirectory()) throw new Error(`Path is not a directory: ${absolutePath}`);
161
+ const template = resolveTemplate(resolvedOptions.template);
162
+ resetMatchCache();
163
+ log.debug(`Building file tree (respectIgnored: ${resolvedOptions.respectIgnored})...`);
164
+ const [credentials, rootTree] = await Promise.all([resolveCredentials(resolvedOptions.credentials), getTree(absolutePath, resolvedOptions.respectIgnored)]);
165
+ log.debug(`Root file tree contains ${rootTree.length} entries`);
166
+ const context = {
167
+ arduinoLibraryProperties: void 0,
168
+ cinderCinderblockXml: void 0,
169
+ codemetaJson: void 0,
170
+ codeStats: void 0,
171
+ dependencyUpdates: void 0,
172
+ fileStats: void 0,
173
+ gitConfig: void 0,
174
+ github: void 0,
175
+ gitStats: void 0,
176
+ goGoMod: void 0,
177
+ goGoreleaserYaml: void 0,
178
+ javaPomXml: void 0,
179
+ licenseFile: void 0,
180
+ metadataFile: void 0,
181
+ metascope: void 0,
182
+ nodeNpmRegistry: void 0,
183
+ nodePackageJson: void 0,
184
+ obsidianPluginManifestJson: void 0,
185
+ obsidianPluginRegistry: void 0,
186
+ openframeworksAddonConfigMk: void 0,
187
+ openframeworksInstallXml: void 0,
188
+ processingLibraryProperties: void 0,
189
+ processingSketchProperties: void 0,
190
+ publiccodeYaml: void 0,
191
+ pythonPkgInfo: void 0,
192
+ pythonPypiRegistry: void 0,
193
+ pythonPyprojectToml: void 0,
194
+ pythonSetupCfg: void 0,
195
+ pythonSetupPy: void 0,
196
+ readmeFile: void 0,
197
+ rubyGemspec: void 0,
198
+ rustCargoToml: void 0,
199
+ xcodeInfoPlist: void 0,
200
+ xcodeProjectPbxproj: void 0
201
+ };
202
+ const activeSources = resolvedOptions.sources ? sources.filter((s) => resolvedOptions.sources.includes(s.key)) : sources;
203
+ const completedSources = /* @__PURE__ */ new Set();
204
+ const phases = new Set(activeSources.map((s) => s.phase));
205
+ for (const phase of [...phases].toSorted((a, b) => a - b)) {
206
+ const phaseSources = activeSources.filter((s) => s.phase === phase);
207
+ log.debug(`Phase ${phase}: Running ${phaseSources.length} sources...`);
208
+ await runSources(phaseSources, {
209
+ completedSources,
210
+ metadata: { ...context },
211
+ options: {
212
+ ...resolvedOptions,
213
+ credentials,
214
+ path: absolutePath
215
+ }
216
+ }, context);
217
+ for (const source of phaseSources) completedSources.add(source.key);
218
+ }
219
+ const metadataDuration = performance.now() - startTime;
220
+ if (context.metascope) context.metascope.data.durationMs = Math.round(metadataDuration);
221
+ log.debug(`Metadata duration: ${prettyMs(metadataDuration)}`);
222
+ if (template) {
223
+ const templateStartTime = performance.now();
224
+ const finalTemplateResult = stripUndefined(template(context, resolvedOptions.templateData ?? {})) ?? {};
225
+ const templateDuration = performance.now() - templateStartTime;
226
+ log.debug(`Template duration: ${prettyMs(templateDuration)}`);
227
+ log.debug(`Total duration: ${prettyMs(performance.now() - startTime)}`);
228
+ return finalTemplateResult;
229
+ }
230
+ const finalResult = stripUndefined(context);
231
+ log.debug(`Total duration: ${prettyMs(performance.now() - startTime)}`);
232
+ return finalResult;
233
+ }
234
+ //#endregion
235
+ export { getMetadata, sourceNames };
@@ -0,0 +1,5 @@
1
+ //#region package.json
2
+ var name = "metascope";
3
+ var version = "0.2.0";
4
+ //#endregion
5
+ export { name, version };
@@ -0,0 +1,43 @@
1
+ //#region src/lib/parsers/configparser-parser.ts
2
+ /**
3
+ * Parse a ConfigParser-style INI file into sections with key-value pairs.
4
+ * Handles Python ConfigParser conventions: multi-line values via indented
5
+ * continuation lines, `#` and `;` comments.
6
+ */
7
+ function parseConfigparser(content) {
8
+ const sections = {};
9
+ let currentSection = "";
10
+ let lastKey = "";
11
+ for (const line of content.split("\n")) {
12
+ const trimmed = line.trimEnd();
13
+ if (trimmed === "" || trimmed.startsWith("#") || trimmed.startsWith(";")) continue;
14
+ const sectionMatch = /^\[([^\]]+)\]/.exec(trimmed);
15
+ if (sectionMatch) {
16
+ currentSection = sectionMatch[1];
17
+ sections[currentSection] ??= {};
18
+ lastKey = "";
19
+ continue;
20
+ }
21
+ if (/^\s/.test(line) && lastKey && currentSection) {
22
+ const existing = sections[currentSection][lastKey];
23
+ const continuation = trimmed.trim();
24
+ if (continuation) sections[currentSection][lastKey] = existing ? `${existing}\n${continuation}` : continuation;
25
+ continue;
26
+ }
27
+ const kvMatch = /^([^=:]+)[=:](.*)$/.exec(trimmed);
28
+ if (kvMatch && currentSection) {
29
+ const key = kvMatch[1].trim();
30
+ const value = kvMatch[2].trim();
31
+ sections[currentSection] ??= {};
32
+ sections[currentSection][key] = value;
33
+ lastKey = key;
34
+ }
35
+ }
36
+ return sections;
37
+ }
38
+ /** Split a multi-line value into individual non-empty lines. */
39
+ function splitMultiline(value) {
40
+ return value.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
41
+ }
42
+ //#endregion
43
+ export { parseConfigparser, splitMultiline };