metascope 0.7.0 → 0.7.2

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 (80) hide show
  1. package/dist/bin/chunk-Bdh3yLIe.js +1 -0
  2. package/dist/bin/cli.js +308 -284
  3. package/dist/bin/dns-CUigd8AG.js +1 -0
  4. package/dist/bin/{jiti-D2Njwwqq.js → jiti-BTBDwj9g.js} +2 -2
  5. package/dist/bin/renovate-DxDKd5Ft.js +1 -0
  6. package/dist/bin/shared-CTlQdTfh.js +5 -0
  7. package/dist/lib/file-matching.js +20 -13
  8. package/dist/lib/log.d.ts +6 -4
  9. package/dist/lib/log.js +5 -3
  10. package/dist/lib/metadata-types.d.ts +33 -21
  11. package/dist/lib/metadata-types.js +8 -9
  12. package/dist/lib/metadata.js +7 -7
  13. package/dist/lib/package.js +1 -1
  14. package/dist/lib/parsers/gemspec-parser.js +16 -14
  15. package/dist/lib/parsers/go-mod-parser.js +13 -10
  16. package/dist/lib/parsers/makefile-config-parser.js +20 -17
  17. package/dist/lib/parsers/properties-parser.js +3 -3
  18. package/dist/lib/parsers/rfc822-header-parser.js +4 -4
  19. package/dist/lib/parsers/setup-py-parser.js +3 -4
  20. package/dist/lib/source.d.ts +1 -0
  21. package/dist/lib/source.js +5 -4
  22. package/dist/lib/sources/arduino-library-properties.d.ts +10 -10
  23. package/dist/lib/sources/arduino-library-properties.js +32 -15
  24. package/dist/lib/sources/cinder-cinderblock-xml.d.ts +11 -11
  25. package/dist/lib/sources/cinder-cinderblock-xml.js +21 -9
  26. package/dist/lib/sources/codemeta-json.d.ts +66 -66
  27. package/dist/lib/sources/codemeta-json.js +27 -23
  28. package/dist/lib/sources/git-stats.js +1 -1
  29. package/dist/lib/sources/github-actions.js +9 -2
  30. package/dist/lib/sources/github.js +1 -1
  31. package/dist/lib/sources/go-go-mod.d.ts +4 -4
  32. package/dist/lib/sources/go-goreleaser-yaml.d.ts +8 -8
  33. package/dist/lib/sources/go-goreleaser-yaml.js +5 -4
  34. package/dist/lib/sources/java-pom-xml.d.ts +12 -12
  35. package/dist/lib/sources/java-pom-xml.js +38 -19
  36. package/dist/lib/sources/metadata-file.d.ts +4 -4
  37. package/dist/lib/sources/metadata-file.js +15 -12
  38. package/dist/lib/sources/node-npm-registry.js +1 -1
  39. package/dist/lib/sources/openframeworks-addon-config-mk.d.ts +7 -7
  40. package/dist/lib/sources/openframeworks-addon-config-mk.js +7 -0
  41. package/dist/lib/sources/openframeworks-install-xml.d.ts +10 -10
  42. package/dist/lib/sources/openframeworks-install-xml.js +24 -14
  43. package/dist/lib/sources/processing-library-properties.d.ts +8 -8
  44. package/dist/lib/sources/processing-library-properties.js +25 -10
  45. package/dist/lib/sources/processing-sketch-properties.d.ts +16 -16
  46. package/dist/lib/sources/processing-sketch-properties.js +51 -7
  47. package/dist/lib/sources/publiccode-yaml.d.ts +23 -23
  48. package/dist/lib/sources/publiccode-yaml.js +37 -5
  49. package/dist/lib/sources/python-pkg-info.d.ts +18 -18
  50. package/dist/lib/sources/python-pkg-info.js +2 -2
  51. package/dist/lib/sources/python-setup-cfg.d.ts +14 -14
  52. package/dist/lib/sources/python-setup-cfg.js +2 -2
  53. package/dist/lib/sources/python-setup-py.d.ts +14 -14
  54. package/dist/lib/sources/readme-file.js +9 -2
  55. package/dist/lib/sources/ruby-gemspec.d.ts +22 -22
  56. package/dist/lib/sources/ruby-gemspec.js +1 -0
  57. package/dist/lib/sources/rust-cargo-toml.d.ts +14 -14
  58. package/dist/lib/sources/rust-cargo-toml.js +29 -10
  59. package/dist/lib/sources/xcode-info-plist.d.ts +12 -12
  60. package/dist/lib/sources/xcode-info-plist.js +48 -24
  61. package/dist/lib/sources/xcode-project-pbxproj.d.ts +8 -8
  62. package/dist/lib/sources/xcode-project-pbxproj.js +22 -12
  63. package/dist/lib/templates/codemeta-json.d.ts +4 -5
  64. package/dist/lib/templates/codemeta-json.js +4 -5
  65. package/dist/lib/templates/codemeta.js +30 -30
  66. package/dist/lib/templates/metadata.d.ts +2 -2
  67. package/dist/lib/templates/metadata.js +3 -3
  68. package/dist/lib/utilities/codemeta-helpers.d.ts +3 -2
  69. package/dist/lib/utilities/codemeta-helpers.js +14 -12
  70. package/dist/lib/utilities/fetch.js +2 -2
  71. package/dist/lib/utilities/formatting.js +4 -3
  72. package/dist/lib/utilities/github.js +3 -3
  73. package/dist/lib/utilities/license-identification.d.ts +3 -1
  74. package/dist/lib/utilities/license-identification.js +21 -25
  75. package/dist/lib/utilities/schema-primitives.js +16 -13
  76. package/dist/lib/utilities/template-helpers.js +3 -3
  77. package/package.json +14 -14
  78. package/readme.md +7 -3
  79. package/dist/.DS_Store +0 -0
  80. package/dist/bin/chunk-BjEoQXZ0.js +0 -1
@@ -11,8 +11,8 @@ import { escapePath, glob } from "tinyglobby";
11
11
  const matchCache = /* @__PURE__ */ new Map();
12
12
  const workspaceCache = /* @__PURE__ */ new Map();
13
13
  /**
14
- * Clear the memoized file tree and workspace caches. Call between test runs
15
- * or when the same path needs to be re-scanned.
14
+ * Clear the memoized file tree and workspace caches. Call between test runs or
15
+ * when the same path needs to be re-scanned.
16
16
  */
17
17
  function resetMatchCache() {
18
18
  matchCache.clear();
@@ -26,8 +26,9 @@ const DEFAULT_IGNORE = [
26
26
  "**/.DS_Store"
27
27
  ];
28
28
  /**
29
- * Get the full recursive file tree for a directory, memoized by path + respectIgnored.
30
- * Returns relative POSIX paths (internal to tinyglobby; callers receive absolute paths via getMatches).
29
+ * Get the full recursive file tree for a directory, memoized by path +
30
+ * respectIgnored. Returns relative POSIX paths (internal to tinyglobby; callers
31
+ * receive absolute paths via getMatches).
31
32
  */
32
33
  async function getTree(path, respectIgnored) {
33
34
  const key = `${path}\0${respectIgnored ? "1" : "0"}`;
@@ -93,13 +94,15 @@ function validateWorkspaces(directory, workspaces) {
93
94
  return validated;
94
95
  }
95
96
  /**
96
- * Get workspace locations for a directory, memoized by directory path.
97
- * Returns all found workspace location paths as absolute paths.
97
+ * Get workspace locations for a directory, memoized by directory path. Returns
98
+ * all found workspace location paths as absolute paths.
99
+ *
100
+ * Directories to any monorepo workspaces... only supports yarn, npm, pnpm,
101
+ * lerna, and bolt at the moment. Never includes the root path!
98
102
  *
99
- * Directories to any monorepo workspaces... only supports yarn, npm, pnpm, lerna, and bolt at the moment.
100
- * Never includes the root path!
101
103
  * @param directory - The root directory to search from
102
- * @param workspaces - `false` to disable, `true` to auto-discover, `string[]` for a manual list
104
+ * @param workspaces - `false` to disable, `true` to auto-discover, `string[]`
105
+ * for a manual list
103
106
  */
104
107
  function getWorkspaces(directory, workspaces = true) {
105
108
  if (workspaces === false) return [];
@@ -122,11 +125,15 @@ const DEFAULT_MATCH_OPTIONS = {
122
125
  * - Memoizes the file tree internally (keyed by path + respectIgnored)
123
126
  * - Auto-prepends `**\/` to patterns when `options.recursive` is true
124
127
  * - Always uses case-insensitive matching
125
- * - When `options.workspaces` is set, also matches files in workspace directories dynamically.
126
- * @param options - Must include `path`; optionally `recursive`, `respectIgnored`, and `workspaces`
127
- * @param patterns - Root-relative glob patterns (e.g. `['package.json']`, `['*.gemspec']`)
128
+ * - When `options.workspaces` is set, also matches files in workspace directories
129
+ * dynamically.
130
+ *
131
+ * @param options - Must include `path`; optionally `recursive`,
132
+ * `respectIgnored`, and `workspaces`
133
+ * @param patterns - Root-relative glob patterns (e.g. `['package.json']`,
134
+ * `['*.gemspec']`)
128
135
  * @param patternsRecursive - Optionally explicitly specify recursive pattern
129
- * variation, otherwise `**\/` is prepended automatically
136
+ * variation, otherwise `**\/` is prepended automatically
130
137
  */
131
138
  async function getMatches(options, patterns, patternsRecursive) {
132
139
  const resolved = defu(options, DEFAULT_MATCH_OPTIONS);
package/dist/lib/log.d.ts CHANGED
@@ -2,10 +2,12 @@ import { ILogBasic, ILogLayer } from "lognow";
2
2
 
3
3
  //#region src/lib/log.d.ts
4
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
5
+ * Set the logger instance for the module. Export this for library consumers to
6
+ * inject their own logger.
7
+ *
8
+ * @param logger - Accepts either a LogLayer instance or a Console- or
9
+ * Stream-like log target
8
10
  */
9
- declare function setLogger(logger?: ILogBasic | ILogLayer): void;
11
+ declare function setLogger(logger?: ILogBasic | ILogLayer<unknown>): void;
10
12
  //#endregion
11
13
  export { setLogger };
package/dist/lib/log.js CHANGED
@@ -9,9 +9,11 @@ let log = createLogger({
9
9
  name
10
10
  });
11
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
12
+ * Set the logger instance for the module. Export this for library consumers to
13
+ * inject their own logger.
14
+ *
15
+ * @param logger - Accepts either a LogLayer instance or a Console- or
16
+ * Stream-like log target
15
17
  */
16
18
  function setLogger(logger) {
17
19
  log = injectionHelper(logger);
@@ -36,8 +36,8 @@ import { XcodeProjectPbxprojData } from "./sources/xcode-project-pbxproj.js";
36
36
 
37
37
  //#region src/lib/metadata-types.d.ts
38
38
  /**
39
- * The complete metadata context assembled from all sources.
40
- * Each key corresponds to a metadata source.
39
+ * The complete metadata context assembled from all sources. Each key
40
+ * corresponds to a metadata source.
41
41
  */
42
42
  type MetadataContext = {
43
43
  arduinoLibraryProperties: ArduinoLibraryPropertiesData;
@@ -82,7 +82,8 @@ type MetadataContext = {
82
82
  type SourceName = keyof MetadataContext;
83
83
  /**
84
84
  * User-supplied data passed to templates for parameterized ownership checks.
85
- * All fields are optional; templates that don't need them can ignore the argument.
85
+ * All fields are optional; templates that don't need them can ignore the
86
+ * argument.
86
87
  */
87
88
  type TemplateData = {
88
89
  [key: string]: unknown;
@@ -90,22 +91,21 @@ type TemplateData = {
90
91
  githubAccount?: string | string[];
91
92
  };
92
93
  /**
93
- * A template function that transforms MetadataContext into a custom shape.
94
- * The optional second argument provides user-supplied template data.
94
+ * A template function that transforms MetadataContext into a custom shape. The
95
+ * optional second argument provides user-supplied template data.
95
96
  */
96
97
  type Template<T> = (context: MetadataContext, templateData: TemplateData) => T;
97
98
  /**
98
- * Identity wrapper for type inference in config files.
99
- * Use this in `metascope.config.ts` to get autocomplete on available fields.
99
+ * Identity wrapper for type inference in config files. Use this in
100
+ * `metascope.config.ts` to get autocomplete on available fields.
101
+ *
100
102
  * @example
101
- * ```typescript
102
- * import { defineTemplate } from 'metascope'
103
+ * import { defineTemplate } from 'metascope'
103
104
  *
104
- * export default defineTemplate(({ codemetaJson, github }) => ({
105
- * name: codemetaJson?.data.name,
106
- * stars: github?.data.stargazerCount,
107
- * }))
108
- * ```
105
+ * export default defineTemplate(({ codemetaJson, github }) => ({
106
+ * name: codemetaJson?.data.name,
107
+ * stars: github?.data.stargazerCount,
108
+ * }))
109
109
  */
110
110
  declare function defineTemplate<T>(transform: Template<T>): Template<T>;
111
111
  /**
@@ -118,18 +118,28 @@ type Credentials = {
118
118
  * Base options shared by all `getMetadata` overloads.
119
119
  */
120
120
  type GetMetadataBaseOptions = {
121
- /** 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. */
121
+ /**
122
+ * When true (the default), all paths in the output (source,
123
+ * workspaceDirectories, etc.) are absolute. When false, paths are relative to
124
+ * the project directory.
125
+ */
126
+ absolute?: boolean; /** API credentials for remote sources. */
122
127
  credentials?: Credentials; /** Skip web sources (npm registry, GitHub API, PyPI, etc.). */
123
- offline?: boolean; /** Project directory path. Defaults to `'.'` (resolved to `process.cwd()` via `path.resolve`). */
128
+ offline?: boolean;
129
+ /**
130
+ * Project directory path. Defaults to `'.'` (resolved to `process.cwd()` via
131
+ * `path.resolve`).
132
+ */
124
133
  path: string; /** Search for metadata files recursively in subdirectories. Defaults to false. */
125
134
  recursive?: boolean; /** Ignore files specified .gitignore in the file tree. Defaults to true. */
126
135
  respectIgnored?: boolean; /** Only run these specific sources. Defaults to all sources when undefined. */
127
136
  sources?: SourceName[]; /** User-supplied data passed to templates. */
128
137
  templateData?: TemplateData;
129
138
  /**
130
- * Directories to any monorepo workspaces... only supports yarn, npm, pnpm, lerna, and bolt at the moment
131
- * Never includes the root path!
132
- * False is disable, true is auto-discover which turns into string[], string[] is manual list relative to the project directory path...
139
+ * Directories to any monorepo workspaces... only supports yarn, npm, pnpm,
140
+ * lerna, and bolt at the moment Never includes the root path! False is
141
+ * disable, true is auto-discover which turns into string[], string[] is
142
+ * manual list relative to the project directory path...
133
143
  */
134
144
  workspaces?: boolean | string[];
135
145
  };
@@ -138,13 +148,15 @@ type GetMetadataBaseOptions = {
138
148
  */
139
149
  declare const DEFAULT_GET_METADATA_OPTIONS: Required<Omit<GetMetadataBaseOptions, 'credentials' | 'sources' | 'templateData'>>;
140
150
  /**
141
- * Options for `getMetadata` without a template (returns full `MetadataContext`).
151
+ * Options for `getMetadata` without a template (returns full
152
+ * `MetadataContext`).
142
153
  */
143
154
  type GetMetadataOptions = GetMetadataBaseOptions & {
144
155
  /** Built-in template name or omit for full output. */template?: 'frontmatter' | 'metadata' | 'project' | (string & {});
145
156
  };
146
157
  /**
147
- * Options for `getMetadata` with a template function (returns the template's return type).
158
+ * Options for `getMetadata` with a template function (returns the template's
159
+ * return type).
148
160
  */
149
161
  type GetMetadataTemplateOptions<T> = GetMetadataBaseOptions & {
150
162
  /** Template function that transforms MetadataContext into a custom shape. */template: Template<T>;
@@ -1,16 +1,15 @@
1
1
  //#region src/lib/metadata-types.ts
2
2
  /**
3
- * Identity wrapper for type inference in config files.
4
- * Use this in `metascope.config.ts` to get autocomplete on available fields.
3
+ * Identity wrapper for type inference in config files. Use this in
4
+ * `metascope.config.ts` to get autocomplete on available fields.
5
+ *
5
6
  * @example
6
- * ```typescript
7
- * import { defineTemplate } from 'metascope'
7
+ * import { defineTemplate } from 'metascope'
8
8
  *
9
- * export default defineTemplate(({ codemetaJson, github }) => ({
10
- * name: codemetaJson?.data.name,
11
- * stars: github?.data.stargazerCount,
12
- * }))
13
- * ```
9
+ * export default defineTemplate(({ codemetaJson, github }) => ({
10
+ * name: codemetaJson?.data.name,
11
+ * stars: github?.data.stargazerCount,
12
+ * }))
14
13
  */
15
14
  function defineTemplate(transform) {
16
15
  return transform;
@@ -47,10 +47,10 @@ import prettyMs from "pretty-ms";
47
47
  //#region src/lib/metadata.ts
48
48
  const execFileAsync = promisify(execFile);
49
49
  /**
50
- * All registered metadata sources.
51
- * Each source declares its `phase` number. Sources with the same phase run in parallel.
52
- * Lower phases run first, and their accumulated results are available to later phases
53
- * via `context` in `SourceContext`.
50
+ * All registered metadata sources. Each source declares its `phase` number.
51
+ * Sources with the same phase run in parallel. Lower phases run first, and
52
+ * their accumulated results are available to later phases via `context` in
53
+ * `SourceContext`.
54
54
  */
55
55
  const sources = [
56
56
  arduinoLibraryPropertiesSource,
@@ -112,11 +112,11 @@ async function resolveCredentials(credentials) {
112
112
  return credentials ?? {};
113
113
  }
114
114
  /**
115
- * Resolve a template option to a template function.
116
- * Accepts a built-in template name (string) or a template function.
115
+ * Resolve a template option to a template function. Accepts a built-in template
116
+ * name (string) or a template function.
117
117
  */
118
118
  function resolveTemplate(template) {
119
- if (template === void 0) return void 0;
119
+ if (template === void 0) return;
120
120
  if (typeof template === "function") return template;
121
121
  if (isKeyOfTemplate(template)) return templates[template];
122
122
  log.warn(`Unknown template: "${template}". Using default (all fields).`);
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
2
  var name = "metascope";
3
- var version = "0.7.0";
3
+ var version = "0.7.2";
4
4
  //#endregion
5
5
  export { name, version };
@@ -74,9 +74,11 @@ function extractStringArray(node) {
74
74
  return single === void 0 ? [] : [single];
75
75
  }
76
76
  /**
77
- * Attempt to extract a usable value from an arbitrary RHS node.
78
- * Returns string | string[] | null — we intentionally skip expressions
79
- * we can't statically evaluate (method calls, constants, etc.).
77
+ * Attempt to extract a usable value from an arbitrary RHS node. Returns string
78
+ *
79
+ * | string[] | null — we intentionally skip expressions we can't statically
80
+ *
81
+ * Evaluate (method calls, constants, etc.).
80
82
  */
81
83
  function extractValue(node) {
82
84
  if (node.type === "array" || node.type === "string_array") return extractStringArray(node);
@@ -89,7 +91,7 @@ function extractValue(node) {
89
91
  }
90
92
  if (node.type === "true") return "true";
91
93
  if (node.type === "false") return "false";
92
- if (node.type === "nil") return void 0;
94
+ if (node.type === "nil") return;
93
95
  return extractString(node);
94
96
  }
95
97
  /** Resolve the attribute name from the LHS of `spec.foo = ...` */
@@ -102,9 +104,9 @@ const DEP_METHODS = {
102
104
  add_runtime_dependency: "runtime"
103
105
  };
104
106
  function tryParseDependency(node) {
105
- if (node.type !== "call" && node.type !== "method_call") return void 0;
107
+ if (node.type !== "call" && node.type !== "method_call") return;
106
108
  const methodNode = node.childForFieldName("method");
107
- if (!methodNode) return void 0;
109
+ if (!methodNode) return;
108
110
  let methodName;
109
111
  if (methodNode.type === "call") methodName = methodNode.childForFieldName("method")?.text ?? void 0;
110
112
  else if (methodNode.type === "identifier") methodName = methodNode.text;
@@ -119,14 +121,14 @@ function tryParseDependency(node) {
119
121
  break;
120
122
  }
121
123
  }
122
- if (!methodName || !DEP_METHODS[methodName]) return void 0;
124
+ if (!methodName || !DEP_METHODS[methodName]) return;
123
125
  const depType = DEP_METHODS[methodName];
124
126
  const arguments_ = node.childForFieldName("arguments");
125
- if (!arguments_) return void 0;
127
+ if (!arguments_) return;
126
128
  const argumentNodes = children(arguments_);
127
- if (argumentNodes.length === 0) return void 0;
129
+ if (argumentNodes.length === 0) return;
128
130
  const depName = extractString(argumentNodes[0]);
129
- if (!depName) return void 0;
131
+ if (!depName) return;
130
132
  return {
131
133
  name: depName,
132
134
  requirements: argumentNodes.slice(1).map((element) => extractString(element)).filter((s) => s !== void 0),
@@ -157,12 +159,12 @@ function setArrayAttribute(spec, key, value) {
157
159
  * Parse a `.gemspec` file's contents and return a plain object with the
158
160
  * extracted fields.
159
161
  *
160
- * Uses tree-sitter with the Ruby grammar to walk the AST, so it can handle
161
- * most real-world gemspec patterns without executing Ruby.
162
+ * Uses tree-sitter with the Ruby grammar to walk the AST, so it can handle most
163
+ * real-world gemspec patterns without executing Ruby.
162
164
  *
163
165
  * Fields that reference Ruby constants (e.g. `Foo::VERSION`) or dynamic
164
- * expressions (e.g. `Dir.glob(...)`) will be `null` / empty — the parser
165
- * only extracts statically determinable values.
166
+ * expressions (e.g. `Dir.glob(...)`) will be `null` / empty — the parser only
167
+ * extracts statically determinable values.
166
168
  */
167
169
  async function parseGemspec(source) {
168
170
  const parser = await initParser();
@@ -20,9 +20,9 @@ const HOST_SEGMENTS = {
20
20
  function moduleToRepoUrl(modulePath) {
21
21
  const segments = modulePath.split("/");
22
22
  const host = segments[0];
23
- if (!host) return void 0;
23
+ if (!host) return;
24
24
  const needed = HOST_SEGMENTS[host];
25
- if (!needed || segments.length < needed) return void 0;
25
+ if (!needed || segments.length < needed) return;
26
26
  let repoPath = segments.slice(0, needed).join("/");
27
27
  repoPath = repoPath.replace(MAJOR_VERSION_SUFFIX_REGEX, "");
28
28
  return `https://${repoPath}`;
@@ -41,7 +41,7 @@ function parseRequireLine(line) {
41
41
  const indirect = isIndirect(line);
42
42
  const clean = stripComment(line);
43
43
  const match = MODULE_VERSION_REGEX.exec(clean);
44
- if (!match) return void 0;
44
+ if (!match) return;
45
45
  const version = match[2].replace(INCOMPATIBLE_SUFFIX_REGEX, "");
46
46
  return {
47
47
  indirect,
@@ -49,16 +49,19 @@ function parseRequireLine(line) {
49
49
  version
50
50
  };
51
51
  }
52
- /** Parse a replace-style line: `old [version] => new version` or `old [version] => ./local` */
52
+ /**
53
+ * Parse a replace-style line: `old [version] => new version` or `old [version]
54
+ * => ./local`
55
+ */
53
56
  function parseReplaceLine(line) {
54
57
  const parts = stripComment(line).split("=>");
55
- if (parts.length !== 2) return void 0;
58
+ if (parts.length !== 2) return;
56
59
  const left = parts[0].trim().split(WHITESPACE_REGEX);
57
60
  const right = parts[1].trim().split(WHITESPACE_REGEX);
58
61
  const from = left[0];
59
- if (!from || right.length === 0) return void 0;
62
+ if (!from || right.length === 0) return;
60
63
  const target = right[0];
61
- if (!target) return void 0;
64
+ if (!target) return;
62
65
  if (target.startsWith("./") || target.startsWith("../") || target.startsWith("/")) return {
63
66
  from,
64
67
  to: "local"
@@ -74,14 +77,14 @@ function parseReplaceLine(line) {
74
77
  /** Parse a tool-style line: just a module path. */
75
78
  function parseToolLine(line) {
76
79
  const clean = stripComment(line).trim();
77
- if (clean.length === 0) return void 0;
80
+ if (clean.length === 0) return;
78
81
  return clean.split(WHITESPACE_REGEX)[0] || void 0;
79
82
  }
80
83
  /**
81
84
  * Parse a go.mod file and return structured metadata.
82
85
  *
83
- * Extracts module identity, Go version, direct dependencies (skipping
84
- * indirect ones), tool dependencies, and applies replace directives.
86
+ * Extracts module identity, Go version, direct dependencies (skipping indirect
87
+ * ones), tool dependencies, and applies replace directives.
85
88
  */
86
89
  function parseGoMod(source) {
87
90
  const data = {
@@ -2,23 +2,26 @@
2
2
  /**
3
3
  * Parser for Makefile-style configuration files.
4
4
  *
5
- * These files use a GNU Makefile-like syntax with section headers (lines
6
- * ending in `:`) and variable assignments (`VAR = value` or `VAR += value`).
7
- * This parser extracts metadata from the `meta:` section and structural
8
- * information (dependencies, platform sections) from the rest of the file.
5
+ * These files use a GNU Makefile-like syntax with section headers (lines ending
6
+ * in `:`) and variable assignments (`VAR = value` or `VAR += value`). This
7
+ * parser extracts metadata from the `meta:` section and structural information
8
+ * (dependencies, platform sections) from the rest of the file.
9
9
  *
10
- * The parser is intentionally simple — no Make variable expansion, no
11
- * includes, no conditionals. It mirrors the line-by-line algorithm used
12
- * by the openFrameworks Project Generator.
10
+ * The parser is intentionally simple — no Make variable expansion, no includes,
11
+ * no conditionals. It mirrors the line-by-line algorithm used by the
12
+ * openFrameworks Project Generator.
13
13
  */
14
14
  const INLINE_COMMENT_REGEX = /#.*$/;
15
- /** Section header pattern: a word (with optional hyphens/slashes) followed by a colon. */
15
+ /**
16
+ * Section header pattern: a word (with optional hyphens/slashes) followed by a
17
+ * colon.
18
+ */
16
19
  const SECTION_RE = /^[\w/][\w/-]*:$/;
17
- /** Variable assignment pattern: VARNAME = value or VARNAME += value */
20
+ /** Variable assignment pattern: VARNAME = value or VARNAME += value */
18
21
  const ASSIGNMENT_RE = /^(\w+)\s*(\+?=)\s*(.*)/;
19
22
  /**
20
- * Sections that are not platform-specific and should be excluded
21
- * from operatingSystem inference.
23
+ * Sections that are not platform-specific and should be excluded from
24
+ * operatingSystem inference.
22
25
  */
23
26
  const NON_PLATFORM_SECTIONS = new Set([
24
27
  "all",
@@ -74,20 +77,20 @@ function parseMakefileConfig(content) {
74
77
  };
75
78
  }
76
79
  /**
77
- * Get a single string value from the meta variables map.
78
- * Joins multiple tokens with spaces (for values split across `+=` lines).
79
- * Returns undefined for empty/whitespace-only results.
80
+ * Get a single string value from the meta variables map. Joins multiple tokens
81
+ * with spaces (for values split across `+=` lines). Returns undefined for
82
+ * empty/whitespace-only results.
80
83
  */
81
84
  function singleValue(variables, key) {
82
85
  const values = variables.get(key);
83
- if (!values || values.length === 0) return void 0;
86
+ if (!values || values.length === 0) return;
84
87
  const joined = values.join(" ").trim();
85
88
  return joined.length > 0 ? joined : void 0;
86
89
  }
87
90
  /**
88
91
  * Tokenize a value string, handling both bare tokens and "quoted multi-word"
89
- * tokens. For example:
90
- * `"computer vision" "opencv" bare` → `["computer vision", "opencv", "bare"]`
92
+ * tokens. For example: `"computer vision" "opencv" bare` → `["computer vision",
93
+ * "opencv", "bare"]`
91
94
  */
92
95
  function tokenizeValues(raw) {
93
96
  const trimmed = raw.trim();
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * Parser for Java `*.properties` files (key=value format).
4
4
  *
5
- * Used by both Arduino and Processing IDE library managers. These are
6
- * flat UTF-8 properties files with no sections or nesting. Comment lines
7
- * start with `#`. Only the first `=` on each line is the delimiter.
5
+ * Used by both Arduino and Processing IDE library managers. These are flat
6
+ * UTF-8 properties files with no sections or nesting. Comment lines start with
7
+ * `#`. Only the first `=` on each line is the delimiter.
8
8
  *
9
9
  * Returns raw key-value pairs — all domain-specific validation and
10
10
  * transformation is handled by the consuming source.
@@ -10,9 +10,9 @@ const MULTI_VALUE_HEADERS = new Set([
10
10
  "Supported-Platform"
11
11
  ]);
12
12
  /**
13
- * Parse RFC 822-style headers from PKG-INFO / METADATA content.
14
- * Multi-value headers are collected into newline-separated strings.
15
- * Stops at the first blank line (which separates headers from body).
13
+ * Parse RFC 822-style headers from PKG-INFO / METADATA content. Multi-value
14
+ * headers are collected into newline-separated strings. Stops at the first
15
+ * blank line (which separates headers from body).
16
16
  */
17
17
  function parseRfc822Headers(content) {
18
18
  const headers = {};
@@ -37,7 +37,7 @@ function parseRfc822Headers(content) {
37
37
  /** Extract body text after the first blank line. */
38
38
  function extractRfc822Body(content) {
39
39
  const blankIndex = content.indexOf("\n\n");
40
- if (blankIndex === -1) return void 0;
40
+ if (blankIndex === -1) return;
41
41
  return content.slice(blankIndex + 2).trim() || void 0;
42
42
  }
43
43
  /** Split newline-separated multi-value into array. */
@@ -101,10 +101,9 @@ const STRING_ATTRS = new Set([
101
101
  /**
102
102
  * Parse a setup.py file and return structured metadata.
103
103
  *
104
- * Uses tree-sitter with the Python grammar to find the `setup()` call
105
- * and extract keyword arguments. Only statically determinable values
106
- * (string/list literals) are extracted — variables and dynamic expressions
107
- * are skipped.
104
+ * Uses tree-sitter with the Python grammar to find the `setup()` call and
105
+ * extract keyword arguments. Only statically determinable values (string/list
106
+ * literals) are extracted — variables and dynamic expressions are skipped.
108
107
  */
109
108
  async function parseSetupPy(source) {
110
109
  const parser = await initParser();
@@ -5,6 +5,7 @@
5
5
  type OneOrMany<T> = T | T[];
6
6
  /**
7
7
  * A unified record returned by every metadata source.
8
+ *
8
9
  * @template D The shape of the primary data extracted from the source.
9
10
  * @template E The shape of any additional computed/derived fields.
10
11
  */
@@ -2,8 +2,9 @@ import { log } from "./log.js";
2
2
  import { formatPath } from "./utilities/formatting.js";
3
3
  //#region src/lib/source.ts
4
4
  /**
5
- * Define a metadata source with `discover` + `parse`.
6
- * Automatically wires them into an `extract` implementation that handles:
5
+ * Define a metadata source with `discover` + `parse`. Automatically wires them
6
+ * into an `extract` implementation that handles:
7
+ *
7
8
  * - Empty input check (returns undefined)
8
9
  * - Per-input try/catch with log.warn
9
10
  * - Filtering undefined results from parse
@@ -14,7 +15,7 @@ function defineSource(config) {
14
15
  ...config,
15
16
  async extract(context) {
16
17
  const inputs = await config.discover(context);
17
- if (inputs.length === 0) return void 0;
18
+ if (inputs.length === 0) return;
18
19
  const results = [];
19
20
  for (const input of inputs) try {
20
21
  const result = await config.parse(input, context);
@@ -25,7 +26,7 @@ function defineSource(config) {
25
26
  } catch (error) {
26
27
  log.warn(`Failed to process "${input}": ${error instanceof Error ? error.message : String(error)}`);
27
28
  }
28
- if (results.length === 0) return void 0;
29
+ if (results.length === 0) return;
29
30
  return results.length === 1 ? results[0] : results;
30
31
  }
31
32
  };
@@ -3,7 +3,7 @@ import { z } from "zod";
3
3
 
4
4
  //#region src/lib/sources/arduino-library-properties.d.ts
5
5
  declare const arduinoLibraryPropertiesSchema: z.ZodObject<{
6
- architectures: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
6
+ architectures: z.ZodDefault<z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>>;
7
7
  authors: z.ZodArray<z.ZodObject<{
8
8
  email: z.ZodOptional<z.ZodString>;
9
9
  name: z.ZodString;
@@ -24,20 +24,20 @@ declare const arduinoLibraryPropertiesSchema: z.ZodObject<{
24
24
  name: z.ZodString;
25
25
  versionConstraint: z.ZodOptional<z.ZodString>;
26
26
  }, z.core.$strip>>;
27
- email: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
28
- includes: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
29
- license: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
27
+ email: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
28
+ includes: z.ZodDefault<z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>>;
29
+ license: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
30
30
  maintainer: z.ZodOptional<z.ZodObject<{
31
31
  email: z.ZodOptional<z.ZodString>;
32
32
  name: z.ZodString;
33
33
  }, z.core.$strip>>;
34
- name: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
35
- paragraph: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
34
+ name: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
35
+ paragraph: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
36
36
  raw: z.ZodRecord<z.ZodString, z.ZodString>;
37
- repository: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
38
- sentence: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
39
- url: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
40
- version: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
37
+ repository: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
38
+ sentence: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
39
+ url: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
40
+ version: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
41
41
  }, z.core.$strip>;
42
42
  type ArduinoLibraryProperties = z.infer<typeof arduinoLibraryPropertiesSchema>;
43
43
  type ArduinoLibraryPropertiesData = OneOrMany<SourceRecord<ArduinoLibraryProperties>> | undefined;