@agntn/registries 0.3.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.
- package/README.md +26 -3
- package/dist/THIRD-PARTY-LICENSES.md +36 -0
- package/dist/_chunks/cache.mjs +15 -0
- package/dist/{cache/index.mjs.map → _chunks/cache.mjs.map} +1 -1
- package/dist/{commands/cache.mjs → _chunks/cache2.mjs} +6 -8
- package/dist/_chunks/cache2.mjs.map +1 -0
- package/dist/{cache → _chunks}/cached-registry.mjs +12 -8
- package/dist/_chunks/cached-registry.mjs.map +1 -0
- package/dist/{commands → _chunks}/deps.mjs +19 -13
- package/dist/_chunks/deps.mjs.map +1 -0
- package/dist/_chunks/helpers.mjs +53 -19
- package/dist/_chunks/helpers.mjs.map +1 -1
- package/dist/_chunks/index.d.mts +9 -23
- package/dist/_chunks/index.d.mts.map +1 -1
- package/dist/_chunks/index2.d.mts +181 -0
- package/dist/_chunks/index2.d.mts.map +1 -0
- package/dist/_chunks/index3.d.mts +188 -0
- package/dist/_chunks/index3.d.mts.map +1 -0
- package/dist/_chunks/info.mjs +105 -0
- package/dist/_chunks/info.mjs.map +1 -0
- package/dist/_chunks/libs/typebox.mjs +278 -0
- package/dist/_chunks/libs/typebox.mjs.map +1 -0
- package/dist/_chunks/lockfile.mjs +183 -0
- package/dist/_chunks/lockfile.mjs.map +1 -0
- package/dist/_chunks/maintainers.mjs +53 -0
- package/dist/_chunks/maintainers.mjs.map +1 -0
- package/dist/_chunks/mcp.mjs +15 -0
- package/dist/_chunks/mcp.mjs.map +1 -0
- package/dist/_chunks/registries.mjs +514 -245
- package/dist/_chunks/registries.mjs.map +1 -1
- package/dist/_chunks/registry.d.mts +121 -10
- package/dist/_chunks/registry.d.mts.map +1 -1
- package/dist/_chunks/registry.mjs +121 -31
- package/dist/_chunks/registry.mjs.map +1 -1
- package/dist/{commands → _chunks}/shared.mjs +15 -8
- package/dist/_chunks/shared.mjs.map +1 -0
- package/dist/_chunks/tool-operations.mjs +63 -0
- package/dist/_chunks/tool-operations.mjs.map +1 -0
- package/dist/_chunks/version.mjs +4 -0
- package/dist/_chunks/version.mjs.map +1 -0
- package/dist/{commands → _chunks}/versions.mjs +10 -9
- package/dist/_chunks/versions.mjs.map +1 -0
- package/dist/ai.d.mts +4 -4
- package/dist/ai.mjs +0 -1
- package/dist/ai.mjs.map +1 -1
- package/dist/cache/index.d.mts +3 -23
- package/dist/cache/index.mjs +4 -11
- package/dist/cli.mjs +9 -7
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +4 -56
- package/dist/index.mjs +4 -7
- package/dist/mcp.d.mts +7 -0
- package/dist/mcp.d.mts.map +1 -0
- package/dist/mcp.mjs +155 -0
- package/dist/mcp.mjs.map +1 -0
- package/dist/registries/index.d.mts +0 -1
- package/dist/registries/index.mjs +0 -1
- package/dist/tool-operations.d.mts +36 -0
- package/dist/tool-operations.d.mts.map +1 -0
- package/dist/tool-operations.mjs +5 -0
- package/package.json +55 -9
- package/packages/omp/extensions/registries.ts +112 -0
- package/packages/pi/extensions/registries.ts +125 -0
- package/dist/_chunks/errors.d.mts +0 -90
- package/dist/_chunks/errors.d.mts.map +0 -1
- package/dist/_chunks/purl.mjs +0 -200
- package/dist/_chunks/purl.mjs.map +0 -1
- package/dist/_chunks/types.d.mts +0 -73
- package/dist/_chunks/types.d.mts.map +0 -1
- package/dist/cache/cached-registry.d.mts +0 -35
- package/dist/cache/cached-registry.d.mts.map +0 -1
- package/dist/cache/cached-registry.mjs.map +0 -1
- package/dist/cache/index.d.mts.map +0 -1
- package/dist/cache/lockfile.d.mts +0 -50
- package/dist/cache/lockfile.d.mts.map +0 -1
- package/dist/cache/lockfile.mjs +0 -68
- package/dist/cache/lockfile.mjs.map +0 -1
- package/dist/cache/paths.d.mts +0 -11
- package/dist/cache/paths.d.mts.map +0 -1
- package/dist/cache/paths.mjs +0 -26
- package/dist/cache/paths.mjs.map +0 -1
- package/dist/cache/storage.d.mts +0 -22
- package/dist/cache/storage.d.mts.map +0 -1
- package/dist/cache/storage.mjs +0 -40
- package/dist/cache/storage.mjs.map +0 -1
- package/dist/commands/cache.d.mts +0 -7
- package/dist/commands/cache.d.mts.map +0 -1
- package/dist/commands/cache.mjs.map +0 -1
- package/dist/commands/deps.d.mts +0 -23
- package/dist/commands/deps.d.mts.map +0 -1
- package/dist/commands/deps.mjs.map +0 -1
- package/dist/commands/info.d.mts +0 -26
- package/dist/commands/info.d.mts.map +0 -1
- package/dist/commands/info.mjs +0 -54
- package/dist/commands/info.mjs.map +0 -1
- package/dist/commands/maintainers.d.mts +0 -23
- package/dist/commands/maintainers.d.mts.map +0 -1
- package/dist/commands/maintainers.mjs +0 -46
- package/dist/commands/maintainers.mjs.map +0 -1
- package/dist/commands/shared.d.mts +0 -27
- package/dist/commands/shared.d.mts.map +0 -1
- package/dist/commands/shared.mjs.map +0 -1
- package/dist/commands/versions.d.mts +0 -31
- package/dist/commands/versions.d.mts.map +0 -1
- package/dist/commands/versions.mjs.map +0 -1
- package/dist/core/index.d.mts +0 -4
- package/dist/core/index.mjs +0 -3
- package/dist/index.d.mts.map +0 -1
- package/dist/types.d.mts +0 -3
- package/dist/types.mjs +0 -1
package/README.md
CHANGED
|
@@ -15,12 +15,14 @@ There is no embeddable TypeScript library that normalizes across registries. The
|
|
|
15
15
|
|
|
16
16
|
@agntn/registries fills that gap. One `fetchPackage` call, same response shape, regardless of whether the package lives on npm or Packagist. Uses [PURL (ECMA-427)](https://github.com/package-url/purl-spec) for addressing, so `pkg:npm/lodash` and `pkg:cargo/serde` resolve through the same code path. Storage-backed caching with a lockfile keeps things fast on repeated lookups.
|
|
17
17
|
|
|
18
|
+
Docs and the live lookup explorer: [registries.agntn.dev](https://registries.agntn.dev). The source lives in [`docs/`](./docs); run `pnpm docs` after `pnpm build` for a local copy.
|
|
19
|
+
|
|
18
20
|
## Features
|
|
19
21
|
|
|
20
22
|
- 🔍 **Single API, six registries** - npm, PyPI, crates.io, RubyGems, Packagist, Arch Linux (official + AUR)
|
|
21
23
|
- 📦 **PURL-native** - [ECMA-427](https://github.com/package-url/purl-spec) identifiers as first-class input
|
|
22
24
|
- 🏷️ **Normalized data model** - same `Package`, `Version`, `Dependency`, `Maintainer` types everywhere
|
|
23
|
-
- 💾 **
|
|
25
|
+
- 💾 **Cache on unstorage with a lockfile** - sha256 integrity checks, configurable TTL
|
|
24
26
|
- ⌨️ **CLI included** - `registries info npm/lodash`, `registries versions cargo/serde`, `registries deps pypi/flask@3.1.1`
|
|
25
27
|
- 🔁 **Retry + backoff** - exponential backoff with jitter, rate limiter interface
|
|
26
28
|
- 🪶 **ESM-only, zero CJS** - built with [obuild](https://github.com/unjs/obuild)
|
|
@@ -78,7 +80,7 @@ Add `--json` for machine-readable output, `--no-cache` to skip the cache.
|
|
|
78
80
|
|
|
79
81
|
### AI SDK tool
|
|
80
82
|
|
|
81
|
-
`@agntn/registries/ai` exports a
|
|
83
|
+
`@agntn/registries/ai` exports a tool for AI SDK apps that needs no wiring:
|
|
82
84
|
|
|
83
85
|
```ts
|
|
84
86
|
import { generateText } from "ai";
|
|
@@ -101,6 +103,26 @@ The tool supports these operations through one input schema:
|
|
|
101
103
|
// { operation: 'bulk-packages', purls: ['pkg:npm/lodash', 'pkg:cargo/serde'], concurrency?: number }
|
|
102
104
|
```
|
|
103
105
|
|
|
106
|
+
### MCP
|
|
107
|
+
|
|
108
|
+
The package ships an MCP server with six read-only tools for metadata, versions, dependencies, maintainers, bulk lookups, and ecosystem discovery:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
claude mcp add registries --scope user -- npx @agntn/registries mcp
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Hosts with their own transport can import `createMcpServer` from `@agntn/registries/mcp`.
|
|
115
|
+
|
|
116
|
+
### Pi and OMP extensions
|
|
117
|
+
|
|
118
|
+
Install the published package in OMP:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
omp install @agntn/registries
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
From a source checkout, use `omp install .`. The package manifests point OMP and Pi at their matching extension entrypoints, and both expose the same six read-only tools as MCP.
|
|
125
|
+
|
|
104
126
|
## Registries
|
|
105
127
|
|
|
106
128
|
| Ecosystem | PURL type | Registry |
|
|
@@ -229,6 +251,7 @@ registries <command> [options]
|
|
|
229
251
|
| `registries versions <purl>` | List all published versions |
|
|
230
252
|
| `registries deps <purl>` | Dependencies for a specific version |
|
|
231
253
|
| `registries maintainers <purl>` | Package maintainers / authors |
|
|
254
|
+
| `registries mcp` | Start the MCP server over stdio |
|
|
232
255
|
| `registries cache status` | Show cache stats (entries, freshness) |
|
|
233
256
|
| `registries cache path` | Print cache directory path |
|
|
234
257
|
| `registries cache clear` | Remove all cached data |
|
|
@@ -265,7 +288,7 @@ interface Package {
|
|
|
265
288
|
homepage: string;
|
|
266
289
|
documentation: string; // docs URL (docs.rs, readthedocs, rubydoc, etc.)
|
|
267
290
|
repository: string;
|
|
268
|
-
licenses: string; // SPDX
|
|
291
|
+
licenses: string; // normalized to SPDX
|
|
269
292
|
keywords: string[];
|
|
270
293
|
namespace: string; // e.g. "@vue" for npm scoped packages
|
|
271
294
|
latestVersion: string;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Licenses of Bundled Dependencies
|
|
2
|
+
|
|
3
|
+
The published artifact additionally contains code with the following licenses:
|
|
4
|
+
MIT
|
|
5
|
+
|
|
6
|
+
# Bundled Dependencies
|
|
7
|
+
|
|
8
|
+
## typebox
|
|
9
|
+
|
|
10
|
+
License: MIT
|
|
11
|
+
By: sinclairzx81
|
|
12
|
+
Repository: https://github.com/sinclairzx81/typebox
|
|
13
|
+
|
|
14
|
+
> TypeBox
|
|
15
|
+
>
|
|
16
|
+
> The MIT License (MIT)
|
|
17
|
+
>
|
|
18
|
+
> Copyright (c) 2017-2026 Haydn Paterson
|
|
19
|
+
>
|
|
20
|
+
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
21
|
+
> of this software and associated documentation files (the "Software"), to deal
|
|
22
|
+
> in the Software without restriction, including without limitation the rights
|
|
23
|
+
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
24
|
+
> copies of the Software, and to permit persons to whom the Software is
|
|
25
|
+
> furnished to do so, subject to the following conditions:
|
|
26
|
+
>
|
|
27
|
+
> The above copyright notice and this permission notice shall be included in
|
|
28
|
+
> all copies or substantial portions of the Software.
|
|
29
|
+
>
|
|
30
|
+
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
31
|
+
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
32
|
+
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
33
|
+
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
34
|
+
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
35
|
+
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
36
|
+
> THE SOFTWARE.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { n as create } from "./registry.mjs";
|
|
2
|
+
import { t as CachedRegistry } from "./cached-registry.mjs";
|
|
3
|
+
/**
|
|
4
|
+
* Create a registry with cache and lockfile tracking.
|
|
5
|
+
*
|
|
6
|
+
* @param ecosystem - Registry ecosystem key.
|
|
7
|
+
* @param options - Optional registry, client, and storage overrides.
|
|
8
|
+
* @returns {Registry} A cached registry instance.
|
|
9
|
+
*/
|
|
10
|
+
function createCached(ecosystem, options) {
|
|
11
|
+
return new CachedRegistry(create(ecosystem, options?.baseURL, options?.client), options?.storage);
|
|
12
|
+
}
|
|
13
|
+
export { createCached as t };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=cache.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"
|
|
1
|
+
{"version":3,"file":"cache.mjs","names":[],"sources":["../../src/cache/index.ts"],"sourcesContent":["// Cache\nexport { getCacheDir } from \"./paths.ts\";\nexport {\n getStorage,\n getEcosystemStorage,\n computeIntegrity,\n disposeStorage,\n clearStorage,\n configureStorage,\n} from \"./storage.ts\";\nexport { CachedRegistry } from \"./cached-registry.ts\";\nexport {\n readLockfile,\n writeLockfile,\n cacheKey,\n isFresh,\n getFreshEntry,\n setEntry,\n removeEntry,\n pruneStale,\n DEFAULT_TTL,\n} from \"./lockfile.ts\";\nexport type { Lockfile, LockfileEntry, EntryType } from \"./lockfile.ts\";\n\n// Convenience\nimport type { Storage } from \"unstorage\";\nimport type { Client } from \"../core/client.ts\";\nimport { create, type Registry } from \"../core/registry.ts\";\nimport { CachedRegistry } from \"./cached-registry.ts\";\n\n/** Options for creating a cached registry. */\nexport interface CreateCachedOptions {\n /** Custom base URL for the registry API. */\n baseURL?: string;\n /** Custom HTTP client. */\n client?: Client;\n /** Custom unstorage instance. Overrides the globally configured storage. */\n storage?: Storage;\n}\n\n/**\n * Create a registry with cache and lockfile tracking.\n *\n * @param ecosystem - Registry ecosystem key.\n * @param options - Optional registry, client, and storage overrides.\n * @returns {Registry} A cached registry instance.\n */\nexport function createCached(ecosystem: string, options?: CreateCachedOptions): Registry {\n const inner = create(ecosystem, options?.baseURL, options?.client);\n return new CachedRegistry(inner, options?.storage);\n}\n"],"mappings":";;;;;;;;;AA+CA,SAAgB,aAAa,WAAmB,SAAyC;AAEvF,QAAO,IAAI,eADG,OAAO,WAAW,SAAS,SAAS,SAAS,OAAO,EACjC,SAAS,QAAQ"}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { getCacheDir } from "
|
|
2
|
-
import { clearStorage } from "../cache/storage.mjs";
|
|
3
|
-
import { pruneStale, readLockfile, writeLockfile } from "../cache/lockfile.mjs";
|
|
1
|
+
import { a as pruneStale, g as getCacheDir, l as writeLockfile, o as readLockfile, u as clearStorage } from "./lockfile.mjs";
|
|
4
2
|
import { defineCommand } from "citty";
|
|
5
3
|
import consola from "consola";
|
|
6
4
|
var cache_default = defineCommand({
|
|
@@ -46,9 +44,9 @@ var cache_default = defineCommand({
|
|
|
46
44
|
});
|
|
47
45
|
const stale = entries.length - fresh.length;
|
|
48
46
|
consola.log("");
|
|
49
|
-
consola.log(` \
|
|
50
|
-
consola.log(` \
|
|
51
|
-
consola.log(` \
|
|
47
|
+
consola.log(` \x1B[1mCache status\x1B[0m`);
|
|
48
|
+
consola.log(` \x1B[90mDirectory:\x1B[0m ${getCacheDir()}`);
|
|
49
|
+
consola.log(` \x1B[90mEntries:\x1B[0m ${entries.length} total, ${fresh.length} fresh, ${stale} stale`);
|
|
52
50
|
consola.log("");
|
|
53
51
|
if (fresh.length > 0) {
|
|
54
52
|
const byEco = /* @__PURE__ */ new Map();
|
|
@@ -56,7 +54,7 @@ var cache_default = defineCommand({
|
|
|
56
54
|
const eco = e.key.split(":")[0];
|
|
57
55
|
byEco.set(eco, (byEco.get(eco) ?? 0) + 1);
|
|
58
56
|
}
|
|
59
|
-
for (const [eco, count] of byEco) consola.log(` \
|
|
57
|
+
for (const [eco, count] of byEco) consola.log(` \x1B[36m${eco}\x1B[0m: ${count} cached`);
|
|
60
58
|
consola.log("");
|
|
61
59
|
}
|
|
62
60
|
}
|
|
@@ -77,4 +75,4 @@ var cache_default = defineCommand({
|
|
|
77
75
|
});
|
|
78
76
|
export { cache_default as default };
|
|
79
77
|
|
|
80
|
-
//# sourceMappingURL=
|
|
78
|
+
//# sourceMappingURL=cache2.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache2.mjs","names":[],"sources":["../../src/commands/cache.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport consola from \"consola\";\nimport { getCacheDir } from \"../cache/paths.ts\";\nimport { clearStorage } from \"../cache/storage.ts\";\nimport { readLockfile, writeLockfile, pruneStale } from \"../cache/lockfile.ts\";\n\nexport default defineCommand({\n meta: {\n name: \"cache\",\n description: \"Manage the registries cache\",\n },\n subCommands: {\n clear: defineCommand({\n meta: {\n name: \"clear\",\n description: \"Remove all cached data\",\n },\n async run() {\n await clearStorage();\n await writeLockfile({ version: 1, entries: {} });\n consola.success(\"Cache cleared\");\n },\n }),\n path: defineCommand({\n meta: {\n name: \"path\",\n description: \"Show cache directory path\",\n },\n run() {\n console.log(getCacheDir());\n },\n }),\n status: defineCommand({\n meta: {\n name: \"status\",\n description: \"Show cache status and entry count\",\n },\n async run() {\n const lockfile = await readLockfile();\n const entries = Object.values(lockfile.entries);\n const fresh = entries.filter((e) => {\n const expiresAt = e.fetchedAt + e.ttl * 1000;\n return Date.now() < expiresAt;\n });\n const stale = entries.length - fresh.length;\n\n consola.log(\"\");\n consola.log(` \\x1B[1mCache status\\x1B[0m`);\n consola.log(` \\x1B[90mDirectory:\\x1B[0m ${getCacheDir()}`);\n consola.log(\n ` \\x1B[90mEntries:\\x1B[0m ${entries.length} total, ${fresh.length} fresh, ${stale} stale`,\n );\n consola.log(\"\");\n\n if (fresh.length > 0) {\n // Group by ecosystem\n const byEco = new Map<string, number>();\n for (const e of fresh) {\n const eco = e.key.split(\":\")[0]!;\n byEco.set(eco, (byEco.get(eco) ?? 0) + 1);\n }\n for (const [eco, count] of byEco) {\n consola.log(` \\x1B[36m${eco}\\x1B[0m: ${count} cached`);\n }\n consola.log(\"\");\n }\n },\n }),\n prune: defineCommand({\n meta: {\n name: \"prune\",\n description: \"Remove stale cache entries\",\n },\n async run() {\n const lockfile = await readLockfile();\n const removed = pruneStale(lockfile);\n await writeLockfile(lockfile);\n consola.success(`Pruned ${removed} stale entries`);\n },\n }),\n },\n});\n"],"mappings":";;;AAMA,IAAA,gBAAe,cAAc;CAC3B,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,aAAa;EACX,OAAO,cAAc;GACnB,MAAM;IACJ,MAAM;IACN,aAAa;IACd;GACD,MAAM,MAAM;AACV,UAAM,cAAc;AACpB,UAAM,cAAc;KAAE,SAAS;KAAG,SAAS,EAAA;KAAI,CAAC;AAChD,YAAQ,QAAQ,gBAAgB;;GAEnC,CAAC;EACF,MAAM,cAAc;GAClB,MAAM;IACJ,MAAM;IACN,aAAa;IACd;GACD,MAAM;AACJ,YAAQ,IAAI,aAAa,CAAC;;GAE7B,CAAC;EACF,QAAQ,cAAc;GACpB,MAAM;IACJ,MAAM;IACN,aAAa;IACd;GACD,MAAM,MAAM;IACV,MAAM,WAAW,MAAM,cAAc;IACrC,MAAM,UAAU,OAAO,OAAO,SAAS,QAAQ;IAC/C,MAAM,QAAQ,QAAQ,QAAQ,MAAM;KAClC,MAAM,YAAY,EAAE,YAAY,EAAE,MAAM;AACxC,YAAO,KAAK,KAAK,GAAG;MACpB;IACF,MAAM,QAAQ,QAAQ,SAAS,MAAM;AAErC,YAAQ,IAAI,GAAG;AACf,YAAQ,IAAI,+BAA+B;AAC3C,YAAQ,IAAI,gCAAgC,aAAa,GAAG;AAC5D,YAAQ,IACN,gCAAgC,QAAQ,OAAO,UAAU,MAAM,OAAO,UAAU,MAAM,QACvF;AACD,YAAQ,IAAI,GAAG;AAEf,QAAI,MAAM,SAAS,GAAG;KAEpB,MAAM,wBAAQ,IAAI,KAAqB;AACvC,UAAK,MAAM,KAAK,OAAO;MACrB,MAAM,MAAM,EAAE,IAAI,MAAM,IAAI,CAAC;AAC7B,YAAM,IAAI,MAAM,MAAM,IAAI,IAAI,IAAI,KAAK,EAAE;;AAE3C,UAAK,MAAM,CAAC,KAAK,UAAU,MACzB,SAAQ,IAAI,aAAa,IAAI,WAAW,MAAM,SAAS;AAEzD,aAAQ,IAAI,GAAG;;;GAGpB,CAAC;EACF,OAAO,cAAc;GACnB,MAAM;IACJ,MAAM;IACN,aAAa;IACd;GACD,MAAM,MAAM;IACV,MAAM,WAAW,MAAM,cAAc;IACrC,MAAM,UAAU,WAAW,SAAS;AACpC,UAAM,cAAc,SAAS;AAC7B,YAAQ,QAAQ,UAAU,QAAQ,gBAAgB;;GAErD,CAAA;;CAEJ,CAAC"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { t as Registry } from "
|
|
2
|
-
import { computeIntegrity, getStorage } from "./
|
|
3
|
-
import { DEFAULT_TTL, cacheKey, getFreshEntry, readLockfile, setEntry, writeLockfile } from "./lockfile.mjs";
|
|
1
|
+
import { t as Registry } from "./registry.mjs";
|
|
2
|
+
import { c as setEntry, d as computeIntegrity, h as getStorage, l as writeLockfile, n as cacheKey, o as readLockfile, r as getFreshEntry, t as DEFAULT_TTL } from "./lockfile.mjs";
|
|
4
3
|
/**
|
|
5
4
|
* CachedRegistry wraps any Registry and adds caching backed by unstorage
|
|
6
5
|
* with a lockfile for freshness tracking.
|
|
@@ -41,10 +40,15 @@ var CachedRegistry = class extends Registry {
|
|
|
41
40
|
return this.cached(name, "maintainers", void 0, () => this.inner.fetchMaintainers(name, signal), signal);
|
|
42
41
|
}
|
|
43
42
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
43
|
+
* Read a fresh cached value or fetch and persist its replacement.
|
|
44
|
+
*
|
|
45
|
+
* @param name - Package name.
|
|
46
|
+
* @param type - Cached data type.
|
|
47
|
+
* @param version - Package version when the cache entry is versioned.
|
|
48
|
+
* @param fetcher - Upstream operation used after a cache miss.
|
|
49
|
+
* @param signal - Optional cancellation signal.
|
|
50
|
+
* @param extraMeta - Optional lockfile metadata derived from the fetched value.
|
|
51
|
+
* @returns {Promise<T>} The cached or freshly fetched value.
|
|
48
52
|
*/
|
|
49
53
|
async cached(name, type, version, fetcher, signal, extraMeta) {
|
|
50
54
|
const key = cacheKey(this.inner.ecosystem(), name, type, version);
|
|
@@ -87,6 +91,6 @@ var CachedRegistry = class extends Registry {
|
|
|
87
91
|
}
|
|
88
92
|
}
|
|
89
93
|
};
|
|
90
|
-
export { CachedRegistry };
|
|
94
|
+
export { CachedRegistry as t };
|
|
91
95
|
|
|
92
96
|
//# sourceMappingURL=cached-registry.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cached-registry.mjs","names":[],"sources":["../../src/cache/cached-registry.ts"],"sourcesContent":["import type { Dependency, Maintainer, Package, URLBuilder, Version } from \"../core/types.ts\";\nimport { Registry } from \"../core/registry.ts\";\nimport { getStorage, computeIntegrity } from \"./storage.ts\";\nimport {\n readLockfile,\n writeLockfile,\n cacheKey,\n getFreshEntry,\n setEntry,\n DEFAULT_TTL,\n} from \"./lockfile.ts\";\nimport type { EntryType, LockfileEntry } from \"./lockfile.ts\";\nimport type { Storage } from \"unstorage\";\n\n/**\n * CachedRegistry wraps any Registry and adds caching backed by unstorage\n * with a lockfile for freshness tracking.\n *\n * Pass a custom `storage` to use a non-default driver (e.g. Cloudflare KV).\n * If omitted, uses the globally configured storage (see `configureStorage()`).\n */\nexport class CachedRegistry extends Registry {\n readonly inner: Registry;\n readonly storage: Storage;\n private readonly lockfileStorage: Storage;\n private readonly inflight = new Map<string, Promise<unknown>>();\n\n constructor(inner: Registry, storage?: Storage) {\n super();\n this.inner = inner;\n this.storage = storage ?? getStorage();\n this.lockfileStorage = storage ?? getStorage();\n }\n\n ecosystem(): string {\n return this.inner.ecosystem();\n }\n\n urls(): URLBuilder {\n return this.inner.urls();\n }\n\n async fetchPackage(name: string, signal?: AbortSignal): Promise<Package> {\n return this.cached<Package>(\n name,\n \"package\",\n undefined,\n () => this.inner.fetchPackage(name, signal),\n signal,\n (value) => ({ latestVersion: value.latestVersion }),\n );\n }\n\n async fetchVersions(name: string, signal?: AbortSignal): Promise<Version[]> {\n const versions = await this.cached<Version[]>(\n name,\n \"versions\",\n undefined,\n () => this.inner.fetchVersions(name, signal),\n signal,\n );\n // JSON round-trip through storage turns Date objects into ISO strings.\n // Revive them so consumers can safely call .getTime() / .toISOString().\n return versions.map((v) => ({\n ...v,\n publishedAt: v.publishedAt ? new Date(v.publishedAt as unknown as string) : null,\n }));\n }\n\n async fetchDependencies(\n name: string,\n version: string,\n signal?: AbortSignal,\n ): Promise<Dependency[]> {\n return this.cached<Dependency[]>(\n name,\n \"dependencies\",\n version,\n () => this.inner.fetchDependencies(name, version, signal),\n signal,\n );\n }\n\n async fetchMaintainers(name: string, signal?: AbortSignal): Promise<Maintainer[]> {\n return this.cached<Maintainer[]>(\n name,\n \"maintainers\",\n undefined,\n () => this.inner.fetchMaintainers(name, signal),\n signal,\n );\n }\n\n /**\n * Read a fresh cached value or fetch and persist its replacement.\n *\n * @param name - Package name.\n * @param type - Cached data type.\n * @param version - Package version when the cache entry is versioned.\n * @param fetcher - Upstream operation used after a cache miss.\n * @param signal - Optional cancellation signal.\n * @param extraMeta - Optional lockfile metadata derived from the fetched value.\n * @returns {Promise<T>} The cached or freshly fetched value.\n */\n private async cached<T>(\n name: string,\n type: EntryType,\n version: string | undefined,\n fetcher: () => Promise<T>,\n signal: AbortSignal | undefined,\n extraMeta?: (value: T) => Record<string, unknown>,\n ): Promise<T> {\n const eco = this.inner.ecosystem();\n const key = cacheKey(eco, name, type, version);\n const storageKey = key;\n\n // 1. Check lockfile\n const lockfile = await readLockfile(this.lockfileStorage);\n const entry = getFreshEntry(lockfile, key);\n\n if (entry) {\n // 2. Read from storage\n const cached = await this.storage.getItem<T>(storageKey);\n if (cached !== null) {\n // Verify integrity\n const currentHash = computeIntegrity(cached);\n if (currentHash === entry.integrity) {\n return cached;\n }\n // Integrity mismatch - refetch\n }\n }\n\n // 3. Coalesce concurrent fetches for the same key (single-flight).\n // Skip dedup when caller provides an AbortSignal to avoid sharing\n // cancellation context across unrelated callers.\n if (!signal) {\n const pending = this.inflight.get(key);\n if (pending) {\n return pending as Promise<T>;\n }\n }\n\n const flight = (async () => {\n const value = await fetcher();\n\n // Persist to cache (best-effort - storage failures must not discard fetched data)\n const meta = extraMeta ? extraMeta(value) : {};\n const newEntry: LockfileEntry = {\n key,\n type,\n fetchedAt: Date.now(),\n ttl: DEFAULT_TTL[type],\n integrity: computeIntegrity(value),\n ...(\"latestVersion\" in meta ? { latestVersion: meta[\"latestVersion\"] as string } : {}),\n };\n try {\n await this.storage.setItem(storageKey, value as Record<string, unknown>);\n // Re-read lockfile before writing to avoid overwriting entries\n // added by concurrent calls for different keys.\n const freshLockfile = await readLockfile(this.lockfileStorage);\n setEntry(freshLockfile, newEntry);\n await writeLockfile(freshLockfile, this.lockfileStorage);\n } catch {\n // Storage I/O failed (disk full, permissions, remote driver timeout, etc.).\n // The data was already fetched successfully - return it anyway.\n }\n\n return value;\n })();\n\n if (!signal) {\n this.inflight.set(key, flight);\n }\n try {\n return await flight;\n } finally {\n if (!signal) {\n this.inflight.delete(key);\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;AAqBA,IAAa,iBAAb,cAAoC,SAAS;CAC3C;CACA;CACA;CACA,2BAA4B,IAAI,KAA+B;CAE/D,YAAY,OAAiB,SAAmB;AAC9C,SAAO;AACP,OAAK,QAAQ;AACb,OAAK,UAAU,WAAW,YAAY;AACtC,OAAK,kBAAkB,WAAW,YAAY;;CAGhD,YAAoB;AAClB,SAAO,KAAK,MAAM,WAAW;;CAG/B,OAAmB;AACjB,SAAO,KAAK,MAAM,MAAM;;CAG1B,MAAM,aAAa,MAAc,QAAwC;AACvE,SAAO,KAAK,OACV,MACA,WACA,KAAA,SACM,KAAK,MAAM,aAAa,MAAM,OAAO,EAC3C,SACC,WAAW,EAAE,eAAe,MAAM,eAAe,EACnD;;CAGH,MAAM,cAAc,MAAc,QAA0C;AAU1E,UATiB,MAAM,KAAK,OAC1B,MACA,YACA,KAAA,SACM,KAAK,MAAM,cAAc,MAAM,OAAO,EAC5C,OACD,EAGe,KAAK,OAAO;GAC1B,GAAG;GACH,aAAa,EAAE,cAAc,IAAI,KAAK,EAAE,YAAiC,GAAG;GAC7E,EAAE;;CAGL,MAAM,kBACJ,MACA,SACA,QACuB;AACvB,SAAO,KAAK,OACV,MACA,gBACA,eACM,KAAK,MAAM,kBAAkB,MAAM,SAAS,OAAO,EACzD,OACD;;CAGH,MAAM,iBAAiB,MAAc,QAA6C;AAChF,SAAO,KAAK,OACV,MACA,eACA,KAAA,SACM,KAAK,MAAM,iBAAiB,MAAM,OAAO,EAC/C,OACD;;;;;;;;;;;;;CAcH,MAAc,OACZ,MACA,MACA,SACA,SACA,QACA,WACY;EAEZ,MAAM,MAAM,SADA,KAAK,MAAM,WAAW,EACR,MAAM,MAAM,QAAQ;EAC9C,MAAM,aAAa;EAInB,MAAM,QAAQ,cADG,MAAM,aAAa,KAAK,gBAAgB,EACnB,IAAI;AAE1C,MAAI,OAAO;GAET,MAAM,SAAS,MAAM,KAAK,QAAQ,QAAW,WAAW;AACxD,OAAI,WAAW;QAEO,iBAAiB,OAAO,KACxB,MAAM,UACxB,QAAO;;;AASb,MAAI,CAAC,QAAQ;GACX,MAAM,UAAU,KAAK,SAAS,IAAI,IAAI;AACtC,OAAI,QACF,QAAO;;EAIX,MAAM,UAAU,YAAY;GAC1B,MAAM,QAAQ,MAAM,SAAS;GAG7B,MAAM,OAAO,YAAY,UAAU,MAAM,GAAG,EAAE;GAC9C,MAAM,WAA0B;IAC9B;IACA;IACA,WAAW,KAAK,KAAK;IACrB,KAAK,YAAY;IACjB,WAAW,iBAAiB,MAAM;IAClC,GAAI,mBAAmB,OAAO,EAAE,eAAe,KAAK,kBAA4B,GAAG,EAAA;IACpF;AACD,OAAI;AACF,UAAM,KAAK,QAAQ,QAAQ,YAAY,MAAiC;IAGxE,MAAM,gBAAgB,MAAM,aAAa,KAAK,gBAAgB;AAC9D,aAAS,eAAe,SAAS;AACjC,UAAM,cAAc,eAAe,KAAK,gBAAgB;WAClD;AAKR,UAAO;MACL;AAEJ,MAAI,CAAC,OACH,MAAK,SAAS,IAAI,KAAK,OAAO;AAEhC,MAAI;AACF,UAAO,MAAM;YACL;AACR,OAAI,CAAC,OACH,MAAK,SAAS,OAAO,IAAI"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import "
|
|
2
|
-
import "
|
|
3
|
-
import "
|
|
4
|
-
import
|
|
1
|
+
import "./registry.mjs";
|
|
2
|
+
import "./registries.mjs";
|
|
3
|
+
import "./lockfile.mjs";
|
|
4
|
+
import "./cached-registry.mjs";
|
|
5
|
+
import { n as sharedArgs, r as withErrorHandling, t as resolvePURL } from "./shared.mjs";
|
|
5
6
|
import { defineCommand } from "citty";
|
|
6
7
|
import consola from "consola";
|
|
7
8
|
var deps_default = defineCommand({
|
|
@@ -42,14 +43,9 @@ function outputDeps(name, version, deps, json) {
|
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
44
45
|
consola.log("");
|
|
45
|
-
consola.log(` \
|
|
46
|
+
consola.log(` \x1B[1m${name}@${version}\x1B[0m — ${deps.length} dependenc${deps.length === 1 ? "y" : "ies"}`);
|
|
46
47
|
consola.log("");
|
|
47
|
-
const byScope =
|
|
48
|
-
for (const dep of deps) {
|
|
49
|
-
const scope = dep.scope || "runtime";
|
|
50
|
-
if (!byScope.has(scope)) byScope.set(scope, []);
|
|
51
|
-
byScope.get(scope).push(dep);
|
|
52
|
-
}
|
|
48
|
+
const byScope = groupByScope(deps);
|
|
53
49
|
const scopeColors = {
|
|
54
50
|
runtime: "\x1B[32m",
|
|
55
51
|
development: "\x1B[33m",
|
|
@@ -59,14 +55,24 @@ function outputDeps(name, version, deps, json) {
|
|
|
59
55
|
};
|
|
60
56
|
for (const [scope, scopeDeps] of byScope) {
|
|
61
57
|
const color = scopeColors[scope] ?? "\x1B[0m";
|
|
62
|
-
consola.log(` ${color}${scope}\
|
|
58
|
+
consola.log(` ${color}${scope}\x1B[0m (${scopeDeps.length})`);
|
|
63
59
|
for (const dep of scopeDeps) {
|
|
64
60
|
const opt = dep.optional ? " \x1B[90m(optional)\x1B[0m" : "";
|
|
65
|
-
consola.log(` ${dep.name} \
|
|
61
|
+
consola.log(` ${dep.name} \x1B[90m${dep.requirements}\x1B[0m${opt}`);
|
|
66
62
|
}
|
|
67
63
|
consola.log("");
|
|
68
64
|
}
|
|
69
65
|
}
|
|
66
|
+
function groupByScope(deps) {
|
|
67
|
+
const byScope = /* @__PURE__ */ new Map();
|
|
68
|
+
for (const dep of deps) {
|
|
69
|
+
const scope = dep.scope || "runtime";
|
|
70
|
+
const scopeDeps = byScope.get(scope) ?? [];
|
|
71
|
+
scopeDeps.push(dep);
|
|
72
|
+
byScope.set(scope, scopeDeps);
|
|
73
|
+
}
|
|
74
|
+
return byScope;
|
|
75
|
+
}
|
|
70
76
|
export { deps_default as default };
|
|
71
77
|
|
|
72
78
|
//# sourceMappingURL=deps.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deps.mjs","names":[],"sources":["../../src/commands/deps.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport consola from \"consola\";\nimport { sharedArgs, resolvePURL, withErrorHandling } from \"./shared.ts\";\n\nexport default defineCommand({\n meta: {\n name: \"deps\",\n description: \"List package dependencies\",\n },\n args: {\n ...sharedArgs,\n purl: {\n type: \"positional\",\n description: \"Package PURL with version (e.g. pkg:npm/lodash@4.17.21, cargo/serde@1.0)\",\n required: true,\n },\n },\n async run({ args }) {\n await withErrorHandling(async () => {\n const [reg, name, version] = resolvePURL(args.purl, !args[\"no-cache\"]);\n\n if (!version) {\n // Try to resolve latest version\n const pkg = await reg.fetchPackage(name);\n if (!pkg.latestVersion) {\n consola.error(\n \"PURL must include a version for dependency lookup, and no latest version found.\",\n );\n consola.info(\"Example: pkg:npm/lodash@4.17.21\");\n process.exit(1);\n }\n if (!args.json) {\n consola.info(`No version specified, using latest: ${pkg.latestVersion}`);\n }\n const deps = await reg.fetchDependencies(name, pkg.latestVersion);\n outputDeps(name, pkg.latestVersion, deps, args.json);\n return;\n }\n\n const deps = await reg.fetchDependencies(name, version);\n outputDeps(name, version, deps, args.json);\n });\n },\n});\n\nimport type { Dependency } from \"../core/types.ts\";\n\nfunction outputDeps(\n name: string,\n version: string,\n deps: readonly Dependency[],\n json: boolean,\n): void {\n if (json) {\n console.log(JSON.stringify(deps, null, 2));\n return;\n }\n\n consola.log(\"\");\n consola.log(\n ` \\x1B[1m${name}@${version}\\x1B[0m — ${deps.length} dependenc${deps.length === 1 ? \"y\" : \"ies\"}`,\n );\n consola.log(\"\");\n\n const byScope = groupByScope(deps);\n\n const scopeColors: Record<string, string> = {\n runtime: \"\\x1B[32m\",\n development: \"\\x1B[33m\",\n build: \"\\x1B[35m\",\n test: \"\\x1B[36m\",\n optional: \"\\x1B[90m\",\n };\n\n for (const [scope, scopeDeps] of byScope) {\n const color = scopeColors[scope] ?? \"\\x1B[0m\";\n consola.log(` ${color}${scope}\\x1B[0m (${scopeDeps.length})`);\n for (const dep of scopeDeps) {\n const opt = dep.optional ? \" \\x1B[90m(optional)\\x1B[0m\" : \"\";\n consola.log(` ${dep.name} \\x1B[90m${dep.requirements}\\x1B[0m${opt}`);\n }\n consola.log(\"\");\n }\n}\n\nfunction groupByScope(deps: readonly Dependency[]): Map<string, Dependency[]> {\n const byScope = new Map<string, Dependency[]>();\n\n for (const dep of deps) {\n const scope = dep.scope || \"runtime\";\n const scopeDeps = byScope.get(scope) ?? [];\n scopeDeps.push(dep);\n byScope.set(scope, scopeDeps);\n }\n\n return byScope;\n}\n"],"mappings":";;;;;;;AAIA,IAAA,eAAe,cAAc;CAC3B,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAAM;EACJ,GAAG;EACH,MAAM;GACJ,MAAM;GACN,aAAa;GACb,UAAU;;EAEb;CACD,MAAM,IAAI,EAAE,QAAQ;AAClB,QAAM,kBAAkB,YAAY;GAClC,MAAM,CAAC,KAAK,MAAM,WAAW,YAAY,KAAK,MAAM,CAAC,KAAK,YAAY;AAEtE,OAAI,CAAC,SAAS;IAEZ,MAAM,MAAM,MAAM,IAAI,aAAa,KAAK;AACxC,QAAI,CAAC,IAAI,eAAe;AACtB,aAAQ,MACN,kFACD;AACD,aAAQ,KAAK,kCAAkC;AAC/C,aAAQ,KAAK,EAAE;;AAEjB,QAAI,CAAC,KAAK,KACR,SAAQ,KAAK,uCAAuC,IAAI,gBAAgB;IAE1E,MAAM,OAAO,MAAM,IAAI,kBAAkB,MAAM,IAAI,cAAc;AACjE,eAAW,MAAM,IAAI,eAAe,MAAM,KAAK,KAAK;AACpD;;AAIF,cAAW,MAAM,SADJ,MAAM,IAAI,kBAAkB,MAAM,QAAQ,EACvB,KAAK,KAAK;IAC1C;;CAEL,CAAC;AAIF,SAAS,WACP,MACA,SACA,MACA,MACM;AACN,KAAI,MAAM;AACR,UAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;AAC1C;;AAGF,SAAQ,IAAI,GAAG;AACf,SAAQ,IACN,YAAY,KAAK,GAAG,QAAQ,YAAY,KAAK,OAAO,YAAY,KAAK,WAAW,IAAI,MAAM,QAC3F;AACD,SAAQ,IAAI,GAAG;CAEf,MAAM,UAAU,aAAa,KAAK;CAElC,MAAM,cAAsC;EAC1C,SAAS;EACT,aAAa;EACb,OAAO;EACP,MAAM;EACN,UAAU;EACX;AAED,MAAK,MAAM,CAAC,OAAO,cAAc,SAAS;EACxC,MAAM,QAAQ,YAAY,UAAU;AACpC,UAAQ,IAAI,KAAK,QAAQ,MAAM,WAAW,UAAU,OAAO,GAAG;AAC9D,OAAK,MAAM,OAAO,WAAW;GAC3B,MAAM,MAAM,IAAI,WAAW,+BAA+B;AAC1D,WAAQ,IAAI,OAAO,IAAI,KAAK,WAAW,IAAI,aAAa,SAAS,MAAM;;AAEzE,UAAQ,IAAI,GAAG;;;AAInB,SAAS,aAAa,MAAwD;CAC5E,MAAM,0BAAU,IAAI,KAA2B;AAE/C,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,QAAQ,IAAI,SAAS;EAC3B,MAAM,YAAY,QAAQ,IAAI,MAAM,IAAI,EAAE;AAC1C,YAAU,KAAK,IAAI;AACnB,UAAQ,IAAI,OAAO,UAAU;;AAG/B,QAAO"}
|
package/dist/_chunks/helpers.mjs
CHANGED
|
@@ -1,28 +1,62 @@
|
|
|
1
1
|
import { l as InvalidPURLError } from "./registry.mjs";
|
|
2
|
-
import {
|
|
3
|
-
/**
|
|
2
|
+
import { c as createFromPURL } from "./registries.mjs";
|
|
3
|
+
/**
|
|
4
|
+
* Fetch normalized package metadata from a package URL.
|
|
5
|
+
*
|
|
6
|
+
* @param purl - Package URL.
|
|
7
|
+
* @param signal - Optional cancellation signal.
|
|
8
|
+
* @param client - Optional HTTP client.
|
|
9
|
+
* @returns {Promise<Package>} Normalized package metadata.
|
|
10
|
+
*/
|
|
4
11
|
async function fetchPackageFromPURL(purl, signal, client) {
|
|
5
12
|
const [reg, name] = createFromPURL(purl, client);
|
|
6
13
|
return reg.fetchPackage(name, signal);
|
|
7
14
|
}
|
|
8
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Fetch all versions from a package URL.
|
|
17
|
+
*
|
|
18
|
+
* @param purl - Package URL.
|
|
19
|
+
* @param signal - Optional cancellation signal.
|
|
20
|
+
* @param client - Optional HTTP client.
|
|
21
|
+
* @returns {Promise<Version[]>} Normalized versions.
|
|
22
|
+
*/
|
|
9
23
|
async function fetchVersionsFromPURL(purl, signal, client) {
|
|
10
24
|
const [reg, name] = createFromPURL(purl, client);
|
|
11
25
|
return reg.fetchVersions(name, signal);
|
|
12
26
|
}
|
|
13
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Fetch dependencies for a versioned package URL.
|
|
29
|
+
*
|
|
30
|
+
* @param purl - Versioned package URL.
|
|
31
|
+
* @param signal - Optional cancellation signal.
|
|
32
|
+
* @param client - Optional HTTP client.
|
|
33
|
+
* @returns {Promise<Dependency[]>} Normalized dependencies.
|
|
34
|
+
*/
|
|
14
35
|
async function fetchDependenciesFromPURL(purl, signal, client) {
|
|
15
36
|
const [reg, name, version] = createFromPURL(purl, client);
|
|
16
37
|
if (!version) throw new InvalidPURLError(purl, "must include a version for dependency lookup");
|
|
17
38
|
return reg.fetchDependencies(name, version, signal);
|
|
18
39
|
}
|
|
19
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* Fetch maintainers from a package URL.
|
|
42
|
+
*
|
|
43
|
+
* @param purl - Package URL.
|
|
44
|
+
* @param signal - Optional cancellation signal.
|
|
45
|
+
* @param client - Optional HTTP client.
|
|
46
|
+
* @returns {Promise<Maintainer[]>} Normalized maintainers.
|
|
47
|
+
*/
|
|
20
48
|
async function fetchMaintainersFromPURL(purl, signal, client) {
|
|
21
49
|
const [reg, name] = createFromPURL(purl, client);
|
|
22
50
|
return reg.fetchMaintainers(name, signal);
|
|
23
51
|
}
|
|
24
52
|
const DEFAULT_CONCURRENCY = 15;
|
|
25
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* Fetch packages concurrently, skipping failed lookups.
|
|
55
|
+
*
|
|
56
|
+
* @param purls - Package URLs to fetch.
|
|
57
|
+
* @param options - Optional concurrency, cancellation, and client settings.
|
|
58
|
+
* @returns {Promise<Map<string, Package>>} Results keyed by package URL.
|
|
59
|
+
*/
|
|
26
60
|
async function bulkFetchPackages(purls, options) {
|
|
27
61
|
const concurrency = options?.concurrency ?? DEFAULT_CONCURRENCY;
|
|
28
62
|
const results = /* @__PURE__ */ new Map();
|
|
@@ -44,14 +78,11 @@ async function bulkFetchPackages(purls, options) {
|
|
|
44
78
|
return results;
|
|
45
79
|
}
|
|
46
80
|
/**
|
|
47
|
-
* Select
|
|
48
|
-
*
|
|
49
|
-
* Resolution order:
|
|
50
|
-
* 1. Exact match for `requested` (non-yanked/deprecated/retracted)
|
|
51
|
-
* 2. Exact match for `latest` (non-yanked/deprecated/retracted)
|
|
52
|
-
* 3. Newest available version with no negative status (by publishedAt)
|
|
81
|
+
* Select an exact requested or latest version, then the newest usable one.
|
|
53
82
|
*
|
|
54
|
-
*
|
|
83
|
+
* @param versions - Candidate versions.
|
|
84
|
+
* @param options - Optional requested and latest version numbers.
|
|
85
|
+
* @returns {Version | null} The selected version, or null.
|
|
55
86
|
*/
|
|
56
87
|
function selectVersion(versions, options) {
|
|
57
88
|
const { requested, latest } = options ?? {};
|
|
@@ -74,18 +105,21 @@ function selectVersion(versions, options) {
|
|
|
74
105
|
/**
|
|
75
106
|
* Resolve the best documentation URL for a package.
|
|
76
107
|
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
108
|
+
* @param pkg - Package metadata.
|
|
109
|
+
* @param urls - Ecosystem URL builder.
|
|
110
|
+
* @param version - Optional package version.
|
|
111
|
+
* @returns {string} The explicit, homepage, or ecosystem documentation URL.
|
|
81
112
|
*/
|
|
82
113
|
function resolveDocsUrl(pkg, urls, version) {
|
|
83
114
|
return pkg.documentation || pkg.homepage || urls.documentation(pkg.name, version);
|
|
84
115
|
}
|
|
85
116
|
/**
|
|
86
|
-
* Resolve the
|
|
117
|
+
* Resolve the ecosystem README URL for a package.
|
|
87
118
|
*
|
|
88
|
-
*
|
|
119
|
+
* @param pkg - Package metadata.
|
|
120
|
+
* @param urls - Ecosystem URL builder.
|
|
121
|
+
* @param version - Optional package version.
|
|
122
|
+
* @returns {string} The README URL.
|
|
89
123
|
*/
|
|
90
124
|
function resolveReadmeUrl(pkg, urls, version) {
|
|
91
125
|
return urls.readme(pkg.name, version);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.mjs","names":[],"sources":["../../src/helpers.ts"],"sourcesContent":["import type { Package, Version, Dependency, Maintainer, URLBuilder } from \"./core/types.ts\";\nimport type { Client } from \"./core/client.ts\";\nimport { createFromPURL } from \"./core/purl.ts\";\nimport { InvalidPURLError } from \"./core/errors.ts\";\n\n
|
|
1
|
+
{"version":3,"file":"helpers.mjs","names":[],"sources":["../../src/helpers.ts"],"sourcesContent":["import type { Package, Version, Dependency, Maintainer, URLBuilder } from \"./core/types.ts\";\nimport type { Client } from \"./core/client.ts\";\nimport { createFromPURL } from \"./core/purl.ts\";\nimport { InvalidPURLError } from \"./core/errors.ts\";\n\n/**\n * Fetch normalized package metadata from a package URL.\n *\n * @param purl - Package URL.\n * @param signal - Optional cancellation signal.\n * @param client - Optional HTTP client.\n * @returns {Promise<Package>} Normalized package metadata.\n */\nexport async function fetchPackageFromPURL(\n purl: string,\n signal?: AbortSignal,\n client?: Client,\n): Promise<Package> {\n const [reg, name] = createFromPURL(purl, client);\n return reg.fetchPackage(name, signal);\n}\n\n/**\n * Fetch all versions from a package URL.\n *\n * @param purl - Package URL.\n * @param signal - Optional cancellation signal.\n * @param client - Optional HTTP client.\n * @returns {Promise<Version[]>} Normalized versions.\n */\nexport async function fetchVersionsFromPURL(\n purl: string,\n signal?: AbortSignal,\n client?: Client,\n): Promise<Version[]> {\n const [reg, name] = createFromPURL(purl, client);\n return reg.fetchVersions(name, signal);\n}\n\n/**\n * Fetch dependencies for a versioned package URL.\n *\n * @param purl - Versioned package URL.\n * @param signal - Optional cancellation signal.\n * @param client - Optional HTTP client.\n * @returns {Promise<Dependency[]>} Normalized dependencies.\n */\nexport async function fetchDependenciesFromPURL(\n purl: string,\n signal?: AbortSignal,\n client?: Client,\n): Promise<Dependency[]> {\n const [reg, name, version] = createFromPURL(purl, client);\n if (!version) {\n throw new InvalidPURLError(purl, \"must include a version for dependency lookup\");\n }\n return reg.fetchDependencies(name, version, signal);\n}\n\n/**\n * Fetch maintainers from a package URL.\n *\n * @param purl - Package URL.\n * @param signal - Optional cancellation signal.\n * @param client - Optional HTTP client.\n * @returns {Promise<Maintainer[]>} Normalized maintainers.\n */\nexport async function fetchMaintainersFromPURL(\n purl: string,\n signal?: AbortSignal,\n client?: Client,\n): Promise<Maintainer[]> {\n const [reg, name] = createFromPURL(purl, client);\n return reg.fetchMaintainers(name, signal);\n}\n\nconst DEFAULT_CONCURRENCY = 15;\n\n/**\n * Fetch packages concurrently, skipping failed lookups.\n *\n * @param purls - Package URLs to fetch.\n * @param options - Optional concurrency, cancellation, and client settings.\n * @returns {Promise<Map<string, Package>>} Results keyed by package URL.\n */\nexport async function bulkFetchPackages(\n purls: readonly string[],\n options?: Readonly<{ concurrency?: number; signal?: AbortSignal; client?: Client }>,\n): Promise<Map<string, Package>> {\n const concurrency = options?.concurrency ?? DEFAULT_CONCURRENCY;\n const results = new Map<string, Package>();\n const queue = [...purls];\n\n const signal = options?.signal;\n\n const workers = Array.from({ length: Math.min(concurrency, queue.length) }, async () => {\n while (queue.length > 0) {\n if (signal?.aborted) break;\n\n const purl = queue.shift()!;\n try {\n const pkg = await fetchPackageFromPURL(purl, signal, options?.client);\n results.set(purl, pkg);\n } catch {\n if (signal?.aborted) break;\n // Silently skip failed lookups — absent from results map\n }\n }\n });\n\n await Promise.all(workers);\n return results;\n}\n\n/**\n * Select an exact requested or latest version, then the newest usable one.\n *\n * @param versions - Candidate versions.\n * @param options - Optional requested and latest version numbers.\n * @returns {Version | null} The selected version, or null.\n */\nexport function selectVersion(\n versions: readonly Version[],\n options?: Readonly<{\n requested?: string;\n latest?: string;\n }>,\n): Version | null {\n const { requested, latest } = options ?? {};\n\n if (requested) {\n const exact = versions.find((v) => v.number === requested && v.status === \"\");\n if (exact) return exact;\n }\n\n if (latest) {\n const latestV = versions.find((v) => v.number === latest && v.status === \"\");\n if (latestV) return latestV;\n }\n\n const usable = versions.filter((v) => v.status === \"\");\n if (usable.length === 0) return null;\n\n usable.sort((a, b) => {\n const at = a.publishedAt?.getTime() ?? 0;\n const bt = b.publishedAt?.getTime() ?? 0;\n return bt - at;\n });\n\n return usable[0] ?? null;\n}\n\n/**\n * Resolve the best documentation URL for a package.\n *\n * @param pkg - Package metadata.\n * @param urls - Ecosystem URL builder.\n * @param version - Optional package version.\n * @returns {string} The explicit, homepage, or ecosystem documentation URL.\n */\nexport function resolveDocsUrl(pkg: Package, urls: URLBuilder, version?: string): string {\n return pkg.documentation || pkg.homepage || urls.documentation(pkg.name, version);\n}\n\n/**\n * Resolve the ecosystem README URL for a package.\n *\n * @param pkg - Package metadata.\n * @param urls - Ecosystem URL builder.\n * @param version - Optional package version.\n * @returns {string} The README URL.\n */\nexport function resolveReadmeUrl(pkg: Package, urls: URLBuilder, version?: string): string {\n return urls.readme(pkg.name, version);\n}\n"],"mappings":";;;;;;;;;;AAaA,eAAsB,qBACpB,MACA,QACA,QACkB;CAClB,MAAM,CAAC,KAAK,QAAQ,eAAe,MAAM,OAAO;AAChD,QAAO,IAAI,aAAa,MAAM,OAAO;;;;;;;;;;AAWvC,eAAsB,sBACpB,MACA,QACA,QACoB;CACpB,MAAM,CAAC,KAAK,QAAQ,eAAe,MAAM,OAAO;AAChD,QAAO,IAAI,cAAc,MAAM,OAAO;;;;;;;;;;AAWxC,eAAsB,0BACpB,MACA,QACA,QACuB;CACvB,MAAM,CAAC,KAAK,MAAM,WAAW,eAAe,MAAM,OAAO;AACzD,KAAI,CAAC,QACH,OAAM,IAAI,iBAAiB,MAAM,+CAA+C;AAElF,QAAO,IAAI,kBAAkB,MAAM,SAAS,OAAO;;;;;;;;;;AAWrD,eAAsB,yBACpB,MACA,QACA,QACuB;CACvB,MAAM,CAAC,KAAK,QAAQ,eAAe,MAAM,OAAO;AAChD,QAAO,IAAI,iBAAiB,MAAM,OAAO;;AAG3C,MAAM,sBAAsB;;;;;;;;AAS5B,eAAsB,kBACpB,OACA,SAC+B;CAC/B,MAAM,cAAc,SAAS,eAAe;CAC5C,MAAM,0BAAU,IAAI,KAAsB;CAC1C,MAAM,QAAQ,CAAC,GAAG,MAAM;CAExB,MAAM,SAAS,SAAS;CAExB,MAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,aAAa,MAAM,OAAO,EAAE,EAAE,YAAY;AACtF,SAAO,MAAM,SAAS,GAAG;AACvB,OAAI,QAAQ,QAAS;GAErB,MAAM,OAAO,MAAM,OAAO;AAC1B,OAAI;IACF,MAAM,MAAM,MAAM,qBAAqB,MAAM,QAAQ,SAAS,OAAO;AACrE,YAAQ,IAAI,MAAM,IAAI;WAChB;AACN,QAAI,QAAQ,QAAS;;;GAIzB;AAEF,OAAM,QAAQ,IAAI,QAAQ;AAC1B,QAAO;;;;;;;;;AAUT,SAAgB,cACd,UACA,SAIgB;CAChB,MAAM,EAAE,WAAW,WAAW,WAAW,EAAE;AAE3C,KAAI,WAAW;EACb,MAAM,QAAQ,SAAS,MAAM,MAAM,EAAE,WAAW,aAAa,EAAE,WAAW,GAAG;AAC7E,MAAI,MAAO,QAAO;;AAGpB,KAAI,QAAQ;EACV,MAAM,UAAU,SAAS,MAAM,MAAM,EAAE,WAAW,UAAU,EAAE,WAAW,GAAG;AAC5E,MAAI,QAAS,QAAO;;CAGtB,MAAM,SAAS,SAAS,QAAQ,MAAM,EAAE,WAAW,GAAG;AACtD,KAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,QAAO,MAAM,GAAG,MAAM;EACpB,MAAM,KAAK,EAAE,aAAa,SAAS,IAAI;AAEvC,UADW,EAAE,aAAa,SAAS,IAAI,KAC3B;GACZ;AAEF,QAAO,OAAO,MAAM;;;;;;;;;;AAWtB,SAAgB,eAAe,KAAc,MAAkB,SAA0B;AACvF,QAAO,IAAI,iBAAiB,IAAI,YAAY,KAAK,cAAc,IAAI,MAAM,QAAQ;;;;;;;;;;AAWnF,SAAgB,iBAAiB,KAAc,MAAkB,SAA0B;AACzF,QAAO,KAAK,OAAO,IAAI,MAAM,QAAQ"}
|
package/dist/_chunks/index.d.mts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { o as Client, t as Registry } from "./registry.mjs";
|
|
1
|
+
import { d as Package, g as Version, h as URLBuilder, l as Dependency, o as Client, t as Registry, u as Maintainer } from "./registry.mjs";
|
|
3
2
|
|
|
4
3
|
//#region src/registries/npm.d.ts
|
|
5
4
|
/** npm registry client. */
|
|
@@ -13,13 +12,12 @@ declare class NpmRegistry extends Registry {
|
|
|
13
12
|
fetchDependencies(name: string, version: string, signal?: AbortSignal): Promise<Dependency[]>;
|
|
14
13
|
fetchMaintainers(name: string, signal?: AbortSignal): Promise<Maintainer[]>;
|
|
15
14
|
urls(): URLBuilder;
|
|
16
|
-
|
|
15
|
+
private mapDependencies;
|
|
16
|
+
private collectMaintainers;
|
|
17
|
+
private toMaintainer;
|
|
17
18
|
private maintainerKey;
|
|
18
|
-
/** Encode package name for URL (handle scoped packages). */
|
|
19
19
|
private encodeName;
|
|
20
|
-
/** Extract namespace from scoped package name. */
|
|
21
20
|
private extractNamespace;
|
|
22
|
-
/** Extract and normalize license. */
|
|
23
21
|
private extractLicense;
|
|
24
22
|
}
|
|
25
23
|
//#endregion
|
|
@@ -50,17 +48,14 @@ declare class PyPIRegistry extends Registry {
|
|
|
50
48
|
fetchDependencies(name: string, version: string, signal?: AbortSignal): Promise<Dependency[]>;
|
|
51
49
|
fetchMaintainers(name: string, signal?: AbortSignal): Promise<Maintainer[]>;
|
|
52
50
|
urls(): URLBuilder;
|
|
53
|
-
|
|
51
|
+
private indexFilesByVersion;
|
|
52
|
+
private toVersion;
|
|
54
53
|
private matchFileVersion;
|
|
55
|
-
/** Normalize package name per PEP 503. */
|
|
56
54
|
private normalizeName;
|
|
57
|
-
/** Extract repository URL from project_urls. */
|
|
58
55
|
private extractRepository;
|
|
59
|
-
/** Find a project URL by key, case-insensitive. */
|
|
60
56
|
private findProjectUrl;
|
|
61
|
-
/** Parse comma-separated keywords. */
|
|
62
57
|
private parseKeywords;
|
|
63
|
-
|
|
58
|
+
private parseExtraMarker;
|
|
64
59
|
private parsePEP508;
|
|
65
60
|
}
|
|
66
61
|
//#endregion
|
|
@@ -90,13 +85,11 @@ declare class PackagistRegistry extends Registry {
|
|
|
90
85
|
fetchDependencies(name: string, version: string, signal?: AbortSignal): Promise<Dependency[]>;
|
|
91
86
|
fetchMaintainers(name: string, signal?: AbortSignal): Promise<Maintainer[]>;
|
|
92
87
|
urls(): URLBuilder;
|
|
93
|
-
|
|
88
|
+
private collectMaintainers;
|
|
89
|
+
private toMaintainer;
|
|
94
90
|
private parseName;
|
|
95
|
-
/** Find the highest non-dev version. */
|
|
96
91
|
private findLatestVersion;
|
|
97
|
-
/** Extract and normalize licenses. */
|
|
98
92
|
private extractLicenses;
|
|
99
|
-
/** Skip PHP and extension dependencies. */
|
|
100
93
|
private shouldSkipDependency;
|
|
101
94
|
}
|
|
102
95
|
//#endregion
|
|
@@ -116,25 +109,18 @@ declare class AlpmRegistry extends Registry {
|
|
|
116
109
|
private fetchOfficialVersions;
|
|
117
110
|
private fetchOfficialDependencies;
|
|
118
111
|
private fetchOfficialMaintainers;
|
|
119
|
-
/** Search official repos by exact package name. Prefers x86_64 results. */
|
|
120
112
|
private searchOfficial;
|
|
121
113
|
private fetchAurPackage;
|
|
122
114
|
private fetchAurVersions;
|
|
123
115
|
private fetchAurDependencies;
|
|
124
116
|
private fetchAurMaintainers;
|
|
125
|
-
/** Fetch package info from AUR RPC v5. */
|
|
126
117
|
private fetchAurInfo;
|
|
127
|
-
/** Parse "namespace/name" into components. Defaults to "arch" namespace. */
|
|
128
118
|
private parseName;
|
|
129
119
|
private assertSupportedNamespace;
|
|
130
120
|
private assertVersionMatches;
|
|
131
|
-
/** Format ALPM version: epoch:pkgver-pkgrel (epoch omitted when 0). */
|
|
132
121
|
private formatVersion;
|
|
133
|
-
/** Build normalized dependency list from ALPM dependency arrays. */
|
|
134
122
|
private buildDependencies;
|
|
135
|
-
/** Parse a dependency string like "glibc>=2.33" or "bash". */
|
|
136
123
|
private parseDep;
|
|
137
|
-
/** Parse optional dependency like "perl-locale-gettext: translation support". */
|
|
138
124
|
private parseOptDep;
|
|
139
125
|
}
|
|
140
126
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/registries/npm.ts","../../src/registries/cargo.ts","../../src/registries/pypi.ts","../../src/registries/rubygems.ts","../../src/registries/packagist.ts","../../src/registries/alpm.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/registries/npm.ts","../../src/registries/cargo.ts","../../src/registries/pypi.ts","../../src/registries/rubygems.ts","../../src/registries/packagist.ts","../../src/registries/alpm.ts"],"mappings":"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"}
|