@agntn/registries 0.2.0 → 0.3.1

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 (113) hide show
  1. package/README.md +26 -3
  2. package/dist/THIRD-PARTY-LICENSES.md +36 -0
  3. package/dist/_chunks/cache.mjs +15 -0
  4. package/dist/{cache/index.mjs.map → _chunks/cache.mjs.map} +1 -1
  5. package/dist/{commands/cache.mjs → _chunks/cache2.mjs} +6 -8
  6. package/dist/_chunks/cache2.mjs.map +1 -0
  7. package/dist/{cache → _chunks}/cached-registry.mjs +12 -8
  8. package/dist/_chunks/cached-registry.mjs.map +1 -0
  9. package/dist/{commands → _chunks}/deps.mjs +20 -14
  10. package/dist/_chunks/deps.mjs.map +1 -0
  11. package/dist/_chunks/helpers.mjs +53 -19
  12. package/dist/_chunks/helpers.mjs.map +1 -1
  13. package/dist/_chunks/index.d.mts +9 -23
  14. package/dist/_chunks/index.d.mts.map +1 -1
  15. package/dist/_chunks/index2.d.mts +156 -25
  16. package/dist/_chunks/index2.d.mts.map +1 -1
  17. package/dist/_chunks/index3.d.mts +173 -3
  18. package/dist/_chunks/index3.d.mts.map +1 -1
  19. package/dist/_chunks/info.mjs +105 -0
  20. package/dist/_chunks/info.mjs.map +1 -0
  21. package/dist/_chunks/libs/typebox.mjs +278 -0
  22. package/dist/_chunks/libs/typebox.mjs.map +1 -0
  23. package/dist/_chunks/lockfile.mjs +183 -0
  24. package/dist/_chunks/lockfile.mjs.map +1 -0
  25. package/dist/_chunks/maintainers.mjs +53 -0
  26. package/dist/_chunks/maintainers.mjs.map +1 -0
  27. package/dist/_chunks/mcp.mjs +15 -0
  28. package/dist/_chunks/mcp.mjs.map +1 -0
  29. package/dist/_chunks/registries.mjs +514 -245
  30. package/dist/_chunks/registries.mjs.map +1 -1
  31. package/dist/_chunks/registry.d.mts +121 -10
  32. package/dist/_chunks/registry.d.mts.map +1 -1
  33. package/dist/_chunks/registry.mjs +121 -31
  34. package/dist/_chunks/registry.mjs.map +1 -1
  35. package/dist/{commands → _chunks}/shared.mjs +15 -8
  36. package/dist/_chunks/shared.mjs.map +1 -0
  37. package/dist/_chunks/tool-operations.mjs +63 -0
  38. package/dist/_chunks/tool-operations.mjs.map +1 -0
  39. package/dist/_chunks/version.mjs +4 -0
  40. package/dist/_chunks/version.mjs.map +1 -0
  41. package/dist/{commands → _chunks}/versions.mjs +10 -9
  42. package/dist/_chunks/versions.mjs.map +1 -0
  43. package/dist/ai.d.mts +2 -8
  44. package/dist/ai.d.mts.map +1 -1
  45. package/dist/ai.mjs +0 -1
  46. package/dist/ai.mjs.map +1 -1
  47. package/dist/cache/index.d.mts +1 -6
  48. package/dist/cache/index.mjs +4 -11
  49. package/dist/cli.mjs +9 -7
  50. package/dist/cli.mjs.map +1 -1
  51. package/dist/index.d.mts +3 -9
  52. package/dist/index.mjs +4 -7
  53. package/dist/mcp.d.mts +7 -0
  54. package/dist/mcp.d.mts.map +1 -0
  55. package/dist/mcp.mjs +155 -0
  56. package/dist/mcp.mjs.map +1 -0
  57. package/dist/registries/index.d.mts +0 -1
  58. package/dist/registries/index.mjs +0 -1
  59. package/dist/tool-operations.d.mts +36 -0
  60. package/dist/tool-operations.d.mts.map +1 -0
  61. package/dist/tool-operations.mjs +5 -0
  62. package/package.json +55 -9
  63. package/packages/omp/extensions/registries.ts +112 -0
  64. package/packages/pi/extensions/registries.ts +125 -0
  65. package/dist/_chunks/cached-registry.d.mts +0 -35
  66. package/dist/_chunks/cached-registry.d.mts.map +0 -1
  67. package/dist/_chunks/errors.d.mts +0 -90
  68. package/dist/_chunks/errors.d.mts.map +0 -1
  69. package/dist/_chunks/lockfile.d.mts +0 -50
  70. package/dist/_chunks/lockfile.d.mts.map +0 -1
  71. package/dist/_chunks/paths.d.mts +0 -11
  72. package/dist/_chunks/paths.d.mts.map +0 -1
  73. package/dist/_chunks/purl.mjs +0 -192
  74. package/dist/_chunks/purl.mjs.map +0 -1
  75. package/dist/_chunks/storage.d.mts +0 -22
  76. package/dist/_chunks/storage.d.mts.map +0 -1
  77. package/dist/_chunks/types.d.mts +0 -73
  78. package/dist/_chunks/types.d.mts.map +0 -1
  79. package/dist/cache/cached-registry.d.mts +0 -4
  80. package/dist/cache/cached-registry.mjs.map +0 -1
  81. package/dist/cache/lockfile.d.mts +0 -2
  82. package/dist/cache/lockfile.mjs +0 -68
  83. package/dist/cache/lockfile.mjs.map +0 -1
  84. package/dist/cache/paths.d.mts +0 -2
  85. package/dist/cache/paths.mjs +0 -26
  86. package/dist/cache/paths.mjs.map +0 -1
  87. package/dist/cache/storage.d.mts +0 -2
  88. package/dist/cache/storage.mjs +0 -40
  89. package/dist/cache/storage.mjs.map +0 -1
  90. package/dist/commands/cache.d.mts +0 -7
  91. package/dist/commands/cache.d.mts.map +0 -1
  92. package/dist/commands/cache.mjs.map +0 -1
  93. package/dist/commands/deps.d.mts +0 -23
  94. package/dist/commands/deps.d.mts.map +0 -1
  95. package/dist/commands/deps.mjs.map +0 -1
  96. package/dist/commands/info.d.mts +0 -26
  97. package/dist/commands/info.d.mts.map +0 -1
  98. package/dist/commands/info.mjs +0 -54
  99. package/dist/commands/info.mjs.map +0 -1
  100. package/dist/commands/maintainers.d.mts +0 -23
  101. package/dist/commands/maintainers.d.mts.map +0 -1
  102. package/dist/commands/maintainers.mjs +0 -46
  103. package/dist/commands/maintainers.mjs.map +0 -1
  104. package/dist/commands/shared.d.mts +0 -27
  105. package/dist/commands/shared.d.mts.map +0 -1
  106. package/dist/commands/shared.mjs.map +0 -1
  107. package/dist/commands/versions.d.mts +0 -31
  108. package/dist/commands/versions.d.mts.map +0 -1
  109. package/dist/commands/versions.mjs.map +0 -1
  110. package/dist/core/index.d.mts +0 -4
  111. package/dist/core/index.mjs +0 -3
  112. package/dist/types.d.mts +0 -3
  113. package/dist/types.mjs +0 -1
@@ -0,0 +1,112 @@
1
+ import { existsSync } from "node:fs";
2
+ import { fileURLToPath } from "node:url";
3
+
4
+ import type { AgentToolResult, ExtensionAPI } from "@oh-my-pi/pi-coding-agent";
5
+
6
+ import type * as RegistryTools from "../../../dist/tool-operations.d.mts";
7
+
8
+ const sourceModulePath = fileURLToPath(new URL("../../../src/tool-operations.ts", import.meta.url));
9
+ let toolOperationsPromise: Promise<typeof RegistryTools> | undefined;
10
+
11
+ function loadToolOperations(): Promise<typeof RegistryTools> {
12
+ toolOperationsPromise ??= (
13
+ existsSync(sourceModulePath)
14
+ ? import("../../../src/tool-operations.ts")
15
+ : import("../../../dist/tool-operations.mjs")
16
+ ) as Promise<typeof RegistryTools>;
17
+ return toolOperationsPromise;
18
+ }
19
+
20
+ type RegistryToolResult = AgentToolResult<unknown>;
21
+
22
+ export default function registriesExtension(pi: ExtensionAPI): void {
23
+ const { Type } = pi.typebox;
24
+ const PURL = Type.String({
25
+ minLength: 1,
26
+ maxLength: 2_048,
27
+ description: "Package URL, for example pkg:npm/lodash or pkg:pypi/requests@2.32.3",
28
+ });
29
+ const PURLParams = Type.Object({ purl: PURL }, { additionalProperties: false });
30
+ const BulkPackagesParams = Type.Object(
31
+ {
32
+ purls: Type.Array(PURL, { minItems: 1, maxItems: 50 }),
33
+ concurrency: Type.Optional(Type.Integer({ minimum: 1, maximum: 50 })),
34
+ },
35
+ { additionalProperties: false },
36
+ );
37
+ const EmptyParams = Type.Object({}, { additionalProperties: false });
38
+
39
+ pi.setLabel("Registries");
40
+
41
+ pi.registerTool({
42
+ name: "registries_package",
43
+ label: "Registry Package",
44
+ description: "Fetch normalized metadata for one package URL",
45
+ parameters: PURLParams,
46
+ approval: "read",
47
+ async execute(_toolCallId, params, signal): Promise<RegistryToolResult> {
48
+ const { packageOperation } = await loadToolOperations();
49
+ return packageOperation(params, signal);
50
+ },
51
+ });
52
+
53
+ pi.registerTool({
54
+ name: "registries_versions",
55
+ label: "Registry Versions",
56
+ description: "List normalized versions for one package URL",
57
+ parameters: PURLParams,
58
+ approval: "read",
59
+ async execute(_toolCallId, params, signal): Promise<RegistryToolResult> {
60
+ const { versionsOperation } = await loadToolOperations();
61
+ return versionsOperation(params, signal);
62
+ },
63
+ });
64
+
65
+ pi.registerTool({
66
+ name: "registries_dependencies",
67
+ label: "Registry Dependencies",
68
+ description: "List dependencies for a versioned package URL",
69
+ parameters: PURLParams,
70
+ approval: "read",
71
+ async execute(_toolCallId, params, signal): Promise<RegistryToolResult> {
72
+ const { dependenciesOperation } = await loadToolOperations();
73
+ return dependenciesOperation(params, signal);
74
+ },
75
+ });
76
+
77
+ pi.registerTool({
78
+ name: "registries_maintainers",
79
+ label: "Registry Maintainers",
80
+ description: "List normalized maintainers for one package URL",
81
+ parameters: PURLParams,
82
+ approval: "read",
83
+ async execute(_toolCallId, params, signal): Promise<RegistryToolResult> {
84
+ const { maintainersOperation } = await loadToolOperations();
85
+ return maintainersOperation(params, signal);
86
+ },
87
+ });
88
+
89
+ pi.registerTool({
90
+ name: "registries_bulk_packages",
91
+ label: "Registry Bulk Packages",
92
+ description: "Fetch normalized metadata for up to 50 package URLs",
93
+ parameters: BulkPackagesParams,
94
+ approval: "read",
95
+ async execute(_toolCallId, params, signal): Promise<RegistryToolResult> {
96
+ const { bulkPackagesOperation } = await loadToolOperations();
97
+ return bulkPackagesOperation(params, signal);
98
+ },
99
+ });
100
+
101
+ pi.registerTool({
102
+ name: "registries_ecosystems",
103
+ label: "Registry Ecosystems",
104
+ description: "List package ecosystems registered by this package",
105
+ parameters: EmptyParams,
106
+ approval: "read",
107
+ async execute(): Promise<RegistryToolResult> {
108
+ const { ecosystemsOperation } = await loadToolOperations();
109
+ return ecosystemsOperation();
110
+ },
111
+ });
112
+ }
@@ -0,0 +1,125 @@
1
+ import { existsSync } from "node:fs";
2
+ import { fileURLToPath } from "node:url";
3
+
4
+ import type { AgentToolResult, ExtensionAPI } from "@earendil-works/pi-coding-agent";
5
+ import { Type } from "typebox";
6
+
7
+ import type * as RegistryTools from "../../../dist/tool-operations.d.mts";
8
+
9
+ const sourceModuleUrl = new URL("../../../src/tool-operations.ts", import.meta.url);
10
+ const distributionModuleUrl = new URL("../../../dist/tool-operations.mjs", import.meta.url);
11
+ let toolOperationsPromise: Promise<typeof RegistryTools> | undefined;
12
+
13
+ function loadToolOperations(): Promise<typeof RegistryTools> {
14
+ toolOperationsPromise ??= import(
15
+ existsSync(fileURLToPath(sourceModuleUrl)) ? sourceModuleUrl.href : distributionModuleUrl.href
16
+ ) as Promise<typeof RegistryTools>;
17
+ return toolOperationsPromise;
18
+ }
19
+
20
+ const PURL = Type.String({
21
+ minLength: 1,
22
+ maxLength: 2_048,
23
+ description: "Package URL, for example pkg:npm/lodash or pkg:pypi/requests@2.32.3",
24
+ });
25
+ const PURLParams = Type.Object({ purl: PURL }, { additionalProperties: false });
26
+ const BulkPackagesParams = Type.Object(
27
+ {
28
+ purls: Type.Array(PURL, { minItems: 1, maxItems: 50 }),
29
+ concurrency: Type.Optional(Type.Integer({ minimum: 1, maximum: 50 })),
30
+ },
31
+ { additionalProperties: false },
32
+ );
33
+ const EmptyParams = Type.Object({}, { additionalProperties: false });
34
+
35
+ type RegistryToolResult = AgentToolResult<unknown>;
36
+
37
+ export default function registriesExtension(pi: ExtensionAPI): void {
38
+ pi.registerTool({
39
+ name: "registries_package",
40
+ label: "Registry Package",
41
+ description: "Fetch normalized metadata for one package URL",
42
+ promptSnippet: "Use registries_package to inspect normalized package metadata.",
43
+ promptGuidelines: [
44
+ "Use registries_package with a PURL such as pkg:npm/lodash or pkg:pypi/requests.",
45
+ ],
46
+ parameters: PURLParams,
47
+ async execute(_toolCallId, params, signal): Promise<RegistryToolResult> {
48
+ const { packageOperation } = await loadToolOperations();
49
+ return packageOperation(params, signal);
50
+ },
51
+ });
52
+
53
+ pi.registerTool({
54
+ name: "registries_versions",
55
+ label: "Registry Versions",
56
+ description: "List normalized versions for one package URL",
57
+ promptSnippet: "Use registries_versions to inspect package releases.",
58
+ promptGuidelines: ["Use registries_versions when release dates, integrity, or status matter."],
59
+ parameters: PURLParams,
60
+ async execute(_toolCallId, params, signal): Promise<RegistryToolResult> {
61
+ const { versionsOperation } = await loadToolOperations();
62
+ return versionsOperation(params, signal);
63
+ },
64
+ });
65
+
66
+ pi.registerTool({
67
+ name: "registries_dependencies",
68
+ label: "Registry Dependencies",
69
+ description: "List dependencies for a versioned package URL",
70
+ promptSnippet: "Use registries_dependencies to inspect one package release.",
71
+ promptGuidelines: [
72
+ "Use registries_dependencies with a versioned PURL such as pkg:npm/lodash@4.17.21.",
73
+ ],
74
+ parameters: PURLParams,
75
+ async execute(_toolCallId, params, signal): Promise<RegistryToolResult> {
76
+ const { dependenciesOperation } = await loadToolOperations();
77
+ return dependenciesOperation(params, signal);
78
+ },
79
+ });
80
+
81
+ pi.registerTool({
82
+ name: "registries_maintainers",
83
+ label: "Registry Maintainers",
84
+ description: "List normalized maintainers for one package URL",
85
+ promptSnippet: "Use registries_maintainers to inspect package ownership.",
86
+ promptGuidelines: [
87
+ "Use registries_maintainers to retrieve the identities published by the package registry.",
88
+ ],
89
+ parameters: PURLParams,
90
+ async execute(_toolCallId, params, signal): Promise<RegistryToolResult> {
91
+ const { maintainersOperation } = await loadToolOperations();
92
+ return maintainersOperation(params, signal);
93
+ },
94
+ });
95
+
96
+ pi.registerTool({
97
+ name: "registries_bulk_packages",
98
+ label: "Registry Bulk Packages",
99
+ description: "Fetch normalized metadata for up to 50 package URLs",
100
+ promptSnippet: "Use registries_bulk_packages to inspect several packages concurrently.",
101
+ promptGuidelines: [
102
+ "Use registries_bulk_packages for independent package lookups; failed packages are absent from the result.",
103
+ ],
104
+ parameters: BulkPackagesParams,
105
+ async execute(_toolCallId, params, signal): Promise<RegistryToolResult> {
106
+ const { bulkPackagesOperation } = await loadToolOperations();
107
+ return bulkPackagesOperation(params, signal);
108
+ },
109
+ });
110
+
111
+ pi.registerTool({
112
+ name: "registries_ecosystems",
113
+ label: "Registry Ecosystems",
114
+ description: "List package ecosystems registered by this package",
115
+ promptSnippet: "Use registries_ecosystems to discover supported package URL types.",
116
+ promptGuidelines: [
117
+ "Use registries_ecosystems before choosing a PURL type when ecosystem support is uncertain.",
118
+ ],
119
+ parameters: EmptyParams,
120
+ async execute(): Promise<RegistryToolResult> {
121
+ const { ecosystemsOperation } = await loadToolOperations();
122
+ return ecosystemsOperation();
123
+ },
124
+ });
125
+ }
@@ -1,35 +0,0 @@
1
- import { c as URLBuilder, i as Package, l as Version, n as Dependency, r as Maintainer } from "./types.mjs";
2
- import { t as Registry } from "./registry.mjs";
3
- import { Storage } from "unstorage";
4
-
5
- //#region src/cache/cached-registry.d.ts
6
- /**
7
- * CachedRegistry wraps any Registry and adds caching backed by unstorage
8
- * with a lockfile for freshness tracking.
9
- *
10
- * Pass a custom `storage` to use a non-default driver (e.g. Cloudflare KV).
11
- * If omitted, uses the globally configured storage (see `configureStorage()`).
12
- */
13
- declare class CachedRegistry extends Registry {
14
- readonly inner: Registry;
15
- readonly storage: Storage;
16
- private readonly lockfileStorage;
17
- private readonly inflight;
18
- constructor(inner: Registry, storage?: Storage);
19
- ecosystem(): string;
20
- urls(): URLBuilder;
21
- fetchPackage(name: string, signal?: AbortSignal): Promise<Package>;
22
- fetchVersions(name: string, signal?: AbortSignal): Promise<Version[]>;
23
- fetchDependencies(name: string, version: string, signal?: AbortSignal): Promise<Dependency[]>;
24
- fetchMaintainers(name: string, signal?: AbortSignal): Promise<Maintainer[]>;
25
- /**
26
- * Generic cache-through method:
27
- * 1. Check lockfile for fresh entry
28
- * 2. If fresh -> read from storage
29
- * 3. If stale/missing -> fetch, store, update lockfile
30
- */
31
- private cached;
32
- }
33
- //#endregion
34
- export { CachedRegistry as t };
35
- //# sourceMappingURL=cached-registry.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cached-registry.d.mts","names":[],"sources":["../../src/cache/cached-registry.ts"],"mappings":";;;;;;;AAqBA;;;;;cAAa,cAAA,SAAuB,QAAA;EAAA,SACzB,KAAA,EAAO,QAAA;EAAA,SACP,OAAA,EAAS,OAAA;EAAA,iBACD,eAAA;EAAA,iBACA,QAAA;cAEL,KAAA,EAAO,QAAA,EAAU,OAAA,GAAU,OAAA;EAOvC,SAAA,CAAA;EAIA,IAAA,CAAA,GAAQ,UAAA;EAIF,YAAA,CAAa,IAAA,UAAc,MAAA,GAAS,WAAA,GAAc,OAAA,CAAQ,OAAA;EAW1D,aAAA,CAAc,IAAA,UAAc,MAAA,GAAS,WAAA,GAAc,OAAA,CAAQ,OAAA;EAgB3D,iBAAA,CACJ,IAAA,UACA,OAAA,UACA,MAAA,GAAS,WAAA,GACR,OAAA,CAAQ,UAAA;EAUL,gBAAA,CAAiB,IAAA,UAAc,MAAA,GAAS,WAAA,GAAc,OAAA,CAAQ,UAAA;EAAtB;;;;;;EAAA,QAgBhC,MAAA;AAAA"}
@@ -1,90 +0,0 @@
1
- import { a as ParsedPURL } from "./types.mjs";
2
- import { o as Client, t as Registry } from "./registry.mjs";
3
-
4
- //#region src/core/purl.d.ts
5
- /**
6
- * Parse a PURL string into its components.
7
- *
8
- * Format: `pkg:<type>/<namespace>/<name>@<version>?<qualifiers>#<subpath>`
9
- *
10
- * @see https://github.com/package-url/purl-spec (ECMA-427)
11
- */
12
- declare function parsePURL(purlStr: string): ParsedPURL;
13
- /** Build the full name from namespace + name (e.g., "@scope/pkg" for npm). */
14
- declare function fullName(parsed: ParsedPURL): string;
15
- /** Create a registry instance from a PURL, returning [registry, name, version]. */
16
- declare function createFromPURL(purlStr: string, client?: Client): [Registry, string, string];
17
- /** Build a PURL string from components. Inverse of `parsePURL`. */
18
- declare function buildPURL(parts: {
19
- type: string;
20
- name: string;
21
- version?: string;
22
- namespace?: string;
23
- qualifiers?: Record<string, string>;
24
- subpath?: string;
25
- }): string;
26
- //#endregion
27
- //#region src/core/license.d.ts
28
- /**
29
- * Normalize a license string to SPDX expression.
30
- *
31
- * Handles common variations: "MIT License" → "MIT", "Apache 2.0" → "Apache-2.0".
32
- * Passes through already-valid SPDX identifiers unchanged.
33
- */
34
- declare function normalizeLicense(raw: string | null | undefined): string;
35
- /**
36
- * Combine multiple license strings into a single SPDX expression.
37
- *
38
- * Default operator is OR (disjunctive, user picks one).
39
- * Pass "AND" for ecosystems where multiple licenses mean all apply (e.g. Arch Linux).
40
- */
41
- declare function combineLicenses(licenses: (string | null | undefined)[], operator?: "OR" | "AND"): string;
42
- //#endregion
43
- //#region src/core/repository.d.ts
44
- /**
45
- * Normalize a repository URL to a clean HTTPS git URL.
46
- *
47
- * Handles various formats:
48
- * - "git+https://github.com/foo/bar.git" → "https://github.com/foo/bar"
49
- * - "git://github.com/foo/bar" → "https://github.com/foo/bar"
50
- * - "ssh://git@github.com/foo/bar.git" → "https://github.com/foo/bar"
51
- * - "github:foo/bar" → "https://github.com/foo/bar"
52
- * - { url: "..." } → extracted and normalized
53
- */
54
- declare function normalizeRepositoryURL(raw: unknown): string;
55
- //#endregion
56
- //#region src/core/errors.d.ts
57
- /** Custom error types for registry operations. */
58
- declare class PkioError extends Error {
59
- constructor(message: string, options?: ErrorOptions);
60
- }
61
- declare class HTTPError extends PkioError {
62
- readonly statusCode: number;
63
- readonly url: string;
64
- readonly body: string;
65
- constructor(statusCode: number, url: string, body: string);
66
- isNotFound(): boolean;
67
- isRateLimit(): boolean;
68
- isServerError(): boolean;
69
- }
70
- declare class NotFoundError extends PkioError {
71
- readonly ecosystem: string;
72
- readonly packageName: string;
73
- readonly version: string;
74
- constructor(ecosystem: string, packageName: string, version?: string);
75
- }
76
- declare class RateLimitError extends PkioError {
77
- readonly retryAfter: number;
78
- constructor(retryAfter: number);
79
- }
80
- declare class UnknownEcosystemError extends PkioError {
81
- readonly ecosystem: string;
82
- constructor(ecosystem: string);
83
- }
84
- declare class InvalidPURLError extends PkioError {
85
- readonly purl: string;
86
- constructor(purl: string, reason: string);
87
- }
88
- //#endregion
89
- export { RateLimitError as a, combineLicenses as c, createFromPURL as d, fullName as f, PkioError as i, normalizeLicense as l, InvalidPURLError as n, UnknownEcosystemError as o, parsePURL as p, NotFoundError as r, normalizeRepositoryURL as s, HTTPError as t, buildPURL as u };
90
- //# sourceMappingURL=errors.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors.d.mts","names":[],"sources":["../../src/core/purl.ts","../../src/core/license.ts","../../src/core/repository.ts","../../src/core/errors.ts"],"mappings":";;;;;AAqBA;;;;;AA4FA;iBA5FgB,SAAA,CAAU,OAAA,WAAkB,UAAA;;iBA4F5B,QAAA,CAAS,MAAA,EAAQ,UAAA;;iBAQjB,cAAA,CAAe,OAAA,UAAiB,MAAA,GAAS,MAAA,IAAU,QAAA;;iBAQnD,SAAA,CAAU,KAAA;EACxB,IAAA;EACA,IAAA;EACA,OAAA;EACA,SAAA;EACA,UAAA,GAAa,MAAA;EACb,OAAA;AAAA;;;;;;;AAlHF;;iBCfgB,gBAAA,CAAiB,GAAA;;;AD2GjC;;;;iBClDgB,eAAA,CACd,QAAA,iCACA,QAAA;;;;;;;AD5CF;;;;;AA4FA;iBEvGgB,sBAAA,CAAuB,GAAA;;;;cCR1B,SAAA,SAAkB,KAAA;cACjB,OAAA,UAAiB,OAAA,GAAU,YAAA;AAAA;AAAA,cAM5B,SAAA,SAAkB,SAAA;EAAA,SACpB,UAAA;EAAA,SACA,GAAA;EAAA,SACA,IAAA;cAEG,UAAA,UAAoB,GAAA,UAAa,IAAA;EAQ7C,UAAA,CAAA;EAIA,WAAA,CAAA;EAIA,aAAA,CAAA;AAAA;AAAA,cAKW,aAAA,SAAsB,SAAA;EAAA,SACxB,SAAA;EAAA,SACA,WAAA;EAAA,SACA,OAAA;cAEG,SAAA,UAAmB,WAAA,UAAqB,OAAA;AAAA;AAAA,cAUzC,cAAA,SAAuB,SAAA;EAAA,SACzB,UAAA;cAEG,UAAA;AAAA;AAAA,cAOD,qBAAA,SAA8B,SAAA;EAAA,SAChC,SAAA;cAEG,SAAA;AAAA;AAAA,cAOD,gBAAA,SAAyB,SAAA;EAAA,SAC3B,IAAA;cAEG,IAAA,UAAc,MAAA;AAAA"}
@@ -1,50 +0,0 @@
1
- import { Storage } from "unstorage";
2
-
3
- //#region src/cache/lockfile.d.ts
4
- /** Default TTL per data type (seconds). */
5
- declare const DEFAULT_TTL: {
6
- readonly package: 3600;
7
- readonly versions: 1800;
8
- readonly dependencies: 86400;
9
- readonly maintainers: 86400;
10
- };
11
- type EntryType = keyof typeof DEFAULT_TTL;
12
- /** A single cached entry tracked in the lockfile. */
13
- interface LockfileEntry {
14
- /** PURL-style key: 'npm:lodash', 'cargo:serde' */
15
- key: string;
16
- /** What kind of data: package, versions, dependencies, maintainers */
17
- type: EntryType;
18
- /** Unix timestamp (ms) when fetched */
19
- fetchedAt: number;
20
- /** TTL in seconds */
21
- ttl: number;
22
- /** Latest version at time of caching (for package entries) */
23
- latestVersion?: string;
24
- /** Content hash (sha256 of JSON-serialized value) for integrity */
25
- integrity: string;
26
- }
27
- /** The full lockfile structure. */
28
- interface Lockfile {
29
- version: number;
30
- entries: Record<string, LockfileEntry>;
31
- }
32
- /** Read the lockfile from storage. Returns empty lockfile if not found or invalid. */
33
- declare function readLockfile(storage?: Storage): Promise<Lockfile>;
34
- /** Write the lockfile to storage. */
35
- declare function writeLockfile(lockfile: Lockfile, storage?: Storage): Promise<void>;
36
- /** Build a cache key from ecosystem + name + type + optional version. */
37
- declare function cacheKey(ecosystem: string, name: string, type: EntryType, version?: string): string;
38
- /** Check if a lockfile entry is still fresh. */
39
- declare function isFresh(entry: LockfileEntry): boolean;
40
- /** Get a lockfile entry if it exists and is fresh. Returns null otherwise. */
41
- declare function getFreshEntry(lockfile: Lockfile, key: string): LockfileEntry | null;
42
- /** Upsert an entry in the lockfile. Does NOT persist — call writeLockfile() after. */
43
- declare function setEntry(lockfile: Lockfile, entry: LockfileEntry): void;
44
- /** Remove an entry from the lockfile. */
45
- declare function removeEntry(lockfile: Lockfile, key: string): void;
46
- /** Remove all stale entries from the lockfile. Returns count of removed entries. */
47
- declare function pruneStale(lockfile: Lockfile): number;
48
- //#endregion
49
- export { cacheKey as a, pruneStale as c, setEntry as d, writeLockfile as f, LockfileEntry as i, readLockfile as l, EntryType as n, getFreshEntry as o, Lockfile as r, isFresh as s, DEFAULT_TTL as t, removeEntry as u };
50
- //# sourceMappingURL=lockfile.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"lockfile.d.mts","names":[],"sources":["../../src/cache/lockfile.ts"],"mappings":";;;;cAOa,WAAA;EAAA;;;;;KAOD,SAAA,gBAAyB,WAAA;;UAGpB,aAAA;;EAEf,GAAA;EALU;EAOV,IAAA,EAAM,SAAA;;EAEN,SAAA;EAT8C;EAW9C,GAAA;EAR4B;EAU5B,aAAA;EANe;EAQf,SAAA;AAAA;;UAIe,QAAA;EACf,OAAA;EACA,OAAA,EAAS,MAAA,SAAe,aAAA;AAAA;;iBAQJ,YAAA,CAAa,OAAA,GAAU,OAAA,GAAU,OAAA,CAAQ,QAAA;AAV/D;AAAA,iBAsBsB,aAAA,CAAc,QAAA,EAAU,QAAA,EAAU,OAAA,GAAU,OAAA,GAAU,OAAA;;iBAM5D,QAAA,CACd,SAAA,UACA,IAAA,UACA,IAAA,EAAM,SAAA,EACN,OAAA;;iBAOc,OAAA,CAAQ,KAAA,EAAO,aAAA;;iBAMf,aAAA,CAAc,QAAA,EAAU,QAAA,EAAU,GAAA,WAAc,aAAA;;iBAQhD,QAAA,CAAS,QAAA,EAAU,QAAA,EAAU,KAAA,EAAO,aAAA;AA3CpD;AAAA,iBAgDgB,WAAA,CAAY,QAAA,EAAU,QAAA,EAAU,GAAA;;iBAKhC,UAAA,CAAW,QAAA,EAAU,QAAA"}
@@ -1,11 +0,0 @@
1
- //#region src/cache/paths.d.ts
2
- /**
3
- * Resolve the cache directory following platform conventions:
4
- * - Linux: $XDG_CACHE_HOME/registries or ~/.cache/registries
5
- * - macOS: ~/Library/Caches/registries
6
- * - Windows: %LOCALAPPDATA%/registries/cache
7
- */
8
- declare function getCacheDir(): string;
9
- //#endregion
10
- export { getCacheDir as t };
11
- //# sourceMappingURL=paths.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"paths.d.mts","names":[],"sources":["../../src/cache/paths.ts"],"mappings":";;AAWA;;;;;iBAAgB,WAAA,CAAA"}
@@ -1,192 +0,0 @@
1
- import { l as InvalidPURLError, n as create } from "./registry.mjs";
2
- /**
3
- * Normalize a license string to SPDX expression.
4
- *
5
- * Handles common variations: "MIT License" → "MIT", "Apache 2.0" → "Apache-2.0".
6
- * Passes through already-valid SPDX identifiers unchanged.
7
- */
8
- function normalizeLicense(raw) {
9
- if (!raw) return "";
10
- const trimmed = raw.trim();
11
- if (!trimmed) return "";
12
- const lower = trimmed.toLowerCase();
13
- const known = LICENSE_MAP.get(lower);
14
- if (known) return known;
15
- return trimmed;
16
- }
17
- const LICENSE_MAP = new Map([
18
- ["mit license", "MIT"],
19
- ["mit", "MIT"],
20
- ["apache license 2.0", "Apache-2.0"],
21
- ["apache 2.0", "Apache-2.0"],
22
- ["apache-2.0", "Apache-2.0"],
23
- ["apache license, version 2.0", "Apache-2.0"],
24
- ["apache2", "Apache-2.0"],
25
- ["bsd-2-clause", "BSD-2-Clause"],
26
- ["bsd-3-clause", "BSD-3-Clause"],
27
- ["bsd 2-clause", "BSD-2-Clause"],
28
- ["bsd 3-clause", "BSD-3-Clause"],
29
- ["simplified bsd license", "BSD-2-Clause"],
30
- ["new bsd license", "BSD-3-Clause"],
31
- ["isc license", "ISC"],
32
- ["isc", "ISC"],
33
- ["gpl-2.0", "GPL-2.0-only"],
34
- ["gpl-3.0", "GPL-3.0-only"],
35
- ["gpl-2.0-only", "GPL-2.0-only"],
36
- ["gpl-3.0-only", "GPL-3.0-only"],
37
- ["lgpl-2.1", "LGPL-2.1-only"],
38
- ["lgpl-3.0", "LGPL-3.0-only"],
39
- ["mpl-2.0", "MPL-2.0"],
40
- ["mozilla public license 2.0", "MPL-2.0"],
41
- ["unlicense", "Unlicense"],
42
- ["the unlicense", "Unlicense"],
43
- ["cc0-1.0", "CC0-1.0"],
44
- ["cc0", "CC0-1.0"],
45
- ["public domain", "Unlicense"],
46
- ["zlib", "Zlib"],
47
- ["wtfpl", "WTFPL"],
48
- ["artistic-2.0", "Artistic-2.0"],
49
- ["boost software license 1.0", "BSL-1.0"],
50
- ["bsl-1.0", "BSL-1.0"]
51
- ]);
52
- /**
53
- * Combine multiple license strings into a single SPDX expression.
54
- *
55
- * Default operator is OR (disjunctive, user picks one).
56
- * Pass "AND" for ecosystems where multiple licenses mean all apply (e.g. Arch Linux).
57
- */
58
- function combineLicenses(licenses, operator = "OR") {
59
- const normalized = licenses.map((l) => normalizeLicense(l)).filter(Boolean);
60
- if (normalized.length === 0) return "";
61
- if (normalized.length === 1) return normalized[0];
62
- return normalized.join(` ${operator} `);
63
- }
64
- /**
65
- * Normalize a repository URL to a clean HTTPS git URL.
66
- *
67
- * Handles various formats:
68
- * - "git+https://github.com/foo/bar.git" → "https://github.com/foo/bar"
69
- * - "git://github.com/foo/bar" → "https://github.com/foo/bar"
70
- * - "ssh://git@github.com/foo/bar.git" → "https://github.com/foo/bar"
71
- * - "github:foo/bar" → "https://github.com/foo/bar"
72
- * - { url: "..." } → extracted and normalized
73
- */
74
- function normalizeRepositoryURL(raw) {
75
- if (!raw) return "";
76
- let url;
77
- if (typeof raw === "string") url = raw;
78
- else if (typeof raw === "object" && raw !== null) {
79
- const obj = raw;
80
- if (typeof obj["url"] === "string") url = obj["url"];
81
- else return "";
82
- } else return "";
83
- url = url.trim();
84
- if (!url) return "";
85
- if (url.startsWith("github:")) url = `https://github.com/${url.slice(7)}`;
86
- if (url.startsWith("gitlab:")) url = `https://gitlab.com/${url.slice(7)}`;
87
- if (url.startsWith("bitbucket:")) url = `https://bitbucket.org/${url.slice(10)}`;
88
- if (url.startsWith("git+")) url = url.slice(4);
89
- if (url.startsWith("git://")) url = "https://" + url.slice(6);
90
- if (url.startsWith("ssh://git@")) url = "https://" + url.slice(10);
91
- const sshMatch = url.match(/^git@([^:]+):(.+)$/);
92
- if (sshMatch) url = `https://${sshMatch[1]}/${sshMatch[2]}`;
93
- if (url.endsWith("/")) url = url.slice(0, -1);
94
- if (url.endsWith(".git")) url = url.slice(0, -4);
95
- return url;
96
- }
97
- /** Decode a percent-encoded PURL component, throwing InvalidPURLError on malformed sequences. */
98
- function decodePURLComponent(purlStr, value) {
99
- try {
100
- return decodeURIComponent(value);
101
- } catch {
102
- throw new InvalidPURLError(purlStr, "malformed percent-encoding");
103
- }
104
- }
105
- /**
106
- * Parse a PURL string into its components.
107
- *
108
- * Format: `pkg:<type>/<namespace>/<name>@<version>?<qualifiers>#<subpath>`
109
- *
110
- * @see https://github.com/package-url/purl-spec (ECMA-427)
111
- */
112
- function parsePURL(purlStr) {
113
- if (!purlStr.startsWith("pkg:")) throw new InvalidPURLError(purlStr, "must start with \"pkg:\"");
114
- let remainder = purlStr.slice(4);
115
- let subpath = "";
116
- const hashIdx = remainder.indexOf("#");
117
- if (hashIdx !== -1) {
118
- subpath = remainder.slice(hashIdx + 1).split("/").map((s) => decodePURLComponent(purlStr, s)).join("/");
119
- remainder = remainder.slice(0, hashIdx);
120
- }
121
- const qualifiers = {};
122
- const queryIdx = remainder.indexOf("?");
123
- if (queryIdx !== -1) {
124
- const queryStr = remainder.slice(queryIdx + 1);
125
- remainder = remainder.slice(0, queryIdx);
126
- for (const pair of queryStr.split("&")) {
127
- const eqIdx = pair.indexOf("=");
128
- if (eqIdx !== -1) qualifiers[decodePURLComponent(purlStr, pair.slice(0, eqIdx))] = decodePURLComponent(purlStr, pair.slice(eqIdx + 1));
129
- }
130
- }
131
- let version = "";
132
- const lastSlashBeforeVersion = remainder.lastIndexOf("/");
133
- const lastAtIdx = remainder.lastIndexOf("@");
134
- if (lastAtIdx !== -1 && lastAtIdx > lastSlashBeforeVersion) {
135
- version = decodePURLComponent(purlStr, remainder.slice(lastAtIdx + 1));
136
- remainder = remainder.slice(0, lastAtIdx);
137
- }
138
- const slashIdx = remainder.indexOf("/");
139
- if (slashIdx === -1) throw new InvalidPURLError(purlStr, "missing type/name separator");
140
- const type = remainder.slice(0, slashIdx).toLowerCase();
141
- if (!type) throw new InvalidPURLError(purlStr, "empty type");
142
- const rest = remainder.slice(slashIdx + 1);
143
- if (!rest) throw new InvalidPURLError(purlStr, "empty name");
144
- const lastSlashIdx = rest.lastIndexOf("/");
145
- let namespace = "";
146
- let name;
147
- if (lastSlashIdx !== -1) {
148
- namespace = rest.slice(0, lastSlashIdx).split("/").map((s) => decodePURLComponent(purlStr, s)).join("/");
149
- name = decodePURLComponent(purlStr, rest.slice(lastSlashIdx + 1));
150
- } else name = decodePURLComponent(purlStr, rest);
151
- if (type === "pypi") name = name.toLowerCase().replace(/[-_.]+/g, "-");
152
- if (type === "alpm") name = name.toLowerCase();
153
- return {
154
- type,
155
- namespace,
156
- name,
157
- version,
158
- qualifiers,
159
- subpath
160
- };
161
- }
162
- /** Build the full name from namespace + name (e.g., "@scope/pkg" for npm). */
163
- function fullName(parsed) {
164
- if (parsed.namespace) return `${parsed.namespace}/${parsed.name}`;
165
- return parsed.name;
166
- }
167
- /** Create a registry instance from a PURL, returning [registry, name, version]. */
168
- function createFromPURL(purlStr, client) {
169
- const parsed = parsePURL(purlStr);
170
- const baseURL = parsed.qualifiers["repository_url"] ?? "";
171
- return [
172
- create(parsed.type, baseURL || void 0, client),
173
- fullName(parsed),
174
- parsed.version
175
- ];
176
- }
177
- /** Build a PURL string from components. Inverse of `parsePURL`. */
178
- function buildPURL(parts) {
179
- let purl = `pkg:${parts.type}/`;
180
- if (parts.namespace) purl += `${parts.namespace.split("/").map((s) => encodeURIComponent(s)).join("/")}/`;
181
- purl += encodeURIComponent(parts.name);
182
- if (parts.version) purl += `@${encodeURIComponent(parts.version)}`;
183
- if (parts.qualifiers && Object.keys(parts.qualifiers).length > 0) {
184
- const qs = Object.entries(parts.qualifiers).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join("&");
185
- purl += `?${qs}`;
186
- }
187
- if (parts.subpath) purl += `#${parts.subpath.split("/").map((s) => encodeURIComponent(s)).join("/")}`;
188
- return purl;
189
- }
190
- export { normalizeRepositoryURL as a, parsePURL as i, createFromPURL as n, combineLicenses as o, fullName as r, normalizeLicense as s, buildPURL as t };
191
-
192
- //# sourceMappingURL=purl.mjs.map