@pleaseai/ask 0.1.0 → 0.1.3

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 (101) hide show
  1. package/dist/agents.d.ts +2 -0
  2. package/dist/agents.d.ts.map +1 -0
  3. package/dist/agents.js +73 -0
  4. package/dist/agents.js.map +1 -0
  5. package/dist/concurrency.d.ts +12 -0
  6. package/dist/concurrency.d.ts.map +1 -0
  7. package/dist/concurrency.js +33 -0
  8. package/dist/concurrency.js.map +1 -0
  9. package/dist/config.d.ts +8 -0
  10. package/dist/config.d.ts.map +1 -0
  11. package/dist/config.js +28 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/ignore-files.d.ts +59 -0
  14. package/dist/ignore-files.d.ts.map +1 -0
  15. package/dist/ignore-files.js +205 -0
  16. package/dist/ignore-files.js.map +1 -0
  17. package/dist/index.d.ts +76 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +485 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/io.d.ts +55 -0
  22. package/dist/io.d.ts.map +1 -0
  23. package/dist/io.js +159 -0
  24. package/dist/io.js.map +1 -0
  25. package/dist/manifest/index.d.ts +26 -0
  26. package/dist/manifest/index.d.ts.map +1 -0
  27. package/dist/manifest/index.js +25 -0
  28. package/dist/manifest/index.js.map +1 -0
  29. package/dist/manifest/npm.d.ts +18 -0
  30. package/dist/manifest/npm.d.ts.map +1 -0
  31. package/dist/manifest/npm.js +155 -0
  32. package/dist/manifest/npm.js.map +1 -0
  33. package/dist/markers.d.ts +34 -0
  34. package/dist/markers.d.ts.map +1 -0
  35. package/dist/markers.js +82 -0
  36. package/dist/markers.js.map +1 -0
  37. package/dist/migrate-legacy.d.ts +24 -0
  38. package/dist/migrate-legacy.d.ts.map +1 -0
  39. package/dist/migrate-legacy.js +85 -0
  40. package/dist/migrate-legacy.js.map +1 -0
  41. package/dist/registry.d.ts +71 -0
  42. package/dist/registry.d.ts.map +1 -0
  43. package/dist/registry.js +201 -0
  44. package/dist/registry.js.map +1 -0
  45. package/dist/resolvers/index.d.ts +32 -0
  46. package/dist/resolvers/index.d.ts.map +1 -0
  47. package/dist/resolvers/index.js +17 -0
  48. package/dist/resolvers/index.js.map +1 -0
  49. package/dist/resolvers/maven.d.ts +33 -0
  50. package/dist/resolvers/maven.d.ts.map +1 -0
  51. package/dist/resolvers/maven.js +187 -0
  52. package/dist/resolvers/maven.js.map +1 -0
  53. package/dist/resolvers/npm.d.ts +13 -0
  54. package/dist/resolvers/npm.d.ts.map +1 -0
  55. package/dist/resolvers/npm.js +67 -0
  56. package/dist/resolvers/npm.js.map +1 -0
  57. package/dist/resolvers/pub.d.ts +13 -0
  58. package/dist/resolvers/pub.d.ts.map +1 -0
  59. package/dist/resolvers/pub.js +50 -0
  60. package/dist/resolvers/pub.js.map +1 -0
  61. package/dist/resolvers/pypi.d.ts +12 -0
  62. package/dist/resolvers/pypi.d.ts.map +1 -0
  63. package/dist/resolvers/pypi.js +60 -0
  64. package/dist/resolvers/pypi.js.map +1 -0
  65. package/dist/resolvers/utils.d.ts +15 -0
  66. package/dist/resolvers/utils.d.ts.map +1 -0
  67. package/dist/resolvers/utils.js +26 -0
  68. package/dist/resolvers/utils.js.map +1 -0
  69. package/dist/schemas.d.ts +490 -0
  70. package/dist/schemas.d.ts.map +1 -0
  71. package/dist/schemas.js +91 -0
  72. package/dist/schemas.js.map +1 -0
  73. package/dist/skill.d.ts +4 -0
  74. package/dist/skill.d.ts.map +1 -0
  75. package/dist/skill.js +53 -0
  76. package/dist/skill.js.map +1 -0
  77. package/dist/sources/github.d.ts +14 -0
  78. package/dist/sources/github.d.ts.map +1 -0
  79. package/dist/sources/github.js +114 -0
  80. package/dist/sources/github.js.map +1 -0
  81. package/dist/sources/index.d.ts +41 -0
  82. package/dist/sources/index.d.ts.map +1 -0
  83. package/dist/sources/index.js +14 -0
  84. package/dist/sources/index.js.map +1 -0
  85. package/dist/sources/llms-txt.d.ts +5 -0
  86. package/dist/sources/llms-txt.d.ts.map +1 -0
  87. package/dist/sources/llms-txt.js +33 -0
  88. package/dist/sources/llms-txt.js.map +1 -0
  89. package/dist/sources/npm.d.ts +14 -0
  90. package/dist/sources/npm.d.ts.map +1 -0
  91. package/dist/sources/npm.js +113 -0
  92. package/dist/sources/npm.js.map +1 -0
  93. package/dist/sources/web.d.ts +13 -0
  94. package/dist/sources/web.d.ts.map +1 -0
  95. package/dist/sources/web.js +143 -0
  96. package/dist/sources/web.js.map +1 -0
  97. package/dist/storage.d.ts +11 -0
  98. package/dist/storage.d.ts.map +1 -0
  99. package/dist/storage.js +76 -0
  100. package/dist/storage.js.map +1 -0
  101. package/package.json +9 -8
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-legacy.js","sourceRoot":"","sources":["../src/migrate-legacy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ import type { RegistryEntry, RegistryStrategy } from '@pleaseai/registry-schema';
2
+ export type { ExpandInput, RegistryAlias, RegistryEntry, RegistryStrategy } from '@pleaseai/registry-schema';
3
+ export { expandStrategies } from '@pleaseai/registry-schema';
4
+ /**
5
+ * Parse ecosystem prefix from spec.
6
+ * "npm:next@canary" -> { ecosystem: "npm", spec: "next@canary" }
7
+ * "next@canary" -> { ecosystem: undefined, spec: "next@canary" }
8
+ */
9
+ export declare function parseEcosystem(input: string): {
10
+ ecosystem: string | undefined;
11
+ spec: string;
12
+ };
13
+ /**
14
+ * Parsed identifier passed to `ask docs add`.
15
+ *
16
+ * Three shapes are supported:
17
+ * - `owner/repo[@ref]` → github fast-path (no registry lookup)
18
+ * - `ecosystem:name[@version]` → registry lookup with explicit ecosystem
19
+ * - `name[@version]` → registry lookup with auto-detected ecosystem
20
+ */
21
+ export type ParsedDocSpec = {
22
+ kind: 'github';
23
+ owner: string;
24
+ repo: string;
25
+ ref?: string;
26
+ } | {
27
+ kind: 'ecosystem';
28
+ ecosystem: string;
29
+ name: string;
30
+ version: string;
31
+ } | {
32
+ kind: 'name';
33
+ name: string;
34
+ version: string;
35
+ };
36
+ /**
37
+ * Parse a `docs add` identifier into a discriminated union.
38
+ *
39
+ * Disambiguation rules (checked in order):
40
+ * 1. Contains `/` and no `:` → github (`owner/repo[@ref]`).
41
+ * Exactly one slash is required; more is an error. Empty owner or repo
42
+ * is also an error.
43
+ * 2. Contains `:` (with non-empty prefix) → ecosystem (`prefix:name[@version]`).
44
+ * 3. Otherwise → bare name (`name[@version]`).
45
+ *
46
+ * @throws Error when input is empty or has malformed `owner/repo` shape.
47
+ */
48
+ export declare function parseDocSpec(input: string): ParsedDocSpec;
49
+ /**
50
+ * Fetch registry entry from the registry API.
51
+ *
52
+ * Accepts either `(owner, repo)` for direct lookup or `(ecosystem, name)`
53
+ * for alias-based lookup — the API handles both patterns via catch-all slug.
54
+ */
55
+ export declare function fetchRegistryEntry(first: string, second: string): Promise<RegistryEntry | null>;
56
+ /**
57
+ * Pick the highest-priority strategy from a list, preserving the original
58
+ * order for ties (stable sort).
59
+ */
60
+ export declare function selectBestStrategy(strategies: RegistryStrategy[]): RegistryStrategy;
61
+ /**
62
+ * Resolve source config from registry.
63
+ * Returns the highest-priority strategy from the registry entry.
64
+ */
65
+ export declare function resolveFromRegistry(input: string, projectDir: string): Promise<{
66
+ ecosystem: string;
67
+ name: string;
68
+ version: string;
69
+ strategy: RegistryStrategy;
70
+ } | null>;
71
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAMhF,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAC5G,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAI5D;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAS7F;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACvE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAarD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAgDzD;AA4BD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAe/B;AAgBD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,gBAAgB,EAAE,GAAG,gBAAgB,CAcnF;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,gBAAgB,CAAA;CAAE,GAAG,IAAI,CAAC,CAwClG"}
@@ -0,0 +1,201 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { expandStrategies } from '@pleaseai/registry-schema';
4
+ import { consola } from 'consola';
5
+ export { expandStrategies } from '@pleaseai/registry-schema';
6
+ const REGISTRY_BASE_URL = 'https://ask-registry.pages.dev';
7
+ /**
8
+ * Parse ecosystem prefix from spec.
9
+ * "npm:next@canary" -> { ecosystem: "npm", spec: "next@canary" }
10
+ * "next@canary" -> { ecosystem: undefined, spec: "next@canary" }
11
+ */
12
+ export function parseEcosystem(input) {
13
+ const colonIdx = input.indexOf(':');
14
+ if (colonIdx > 0 && !input.includes('/')) {
15
+ return {
16
+ ecosystem: input.substring(0, colonIdx),
17
+ spec: input.substring(colonIdx + 1),
18
+ };
19
+ }
20
+ return { ecosystem: undefined, spec: input };
21
+ }
22
+ function splitNameVersion(spec) {
23
+ const lastAt = spec.lastIndexOf('@');
24
+ if (lastAt > 0) {
25
+ return {
26
+ name: spec.substring(0, lastAt),
27
+ version: spec.substring(lastAt + 1),
28
+ };
29
+ }
30
+ return { name: spec, version: 'latest' };
31
+ }
32
+ /**
33
+ * Parse a `docs add` identifier into a discriminated union.
34
+ *
35
+ * Disambiguation rules (checked in order):
36
+ * 1. Contains `/` and no `:` → github (`owner/repo[@ref]`).
37
+ * Exactly one slash is required; more is an error. Empty owner or repo
38
+ * is also an error.
39
+ * 2. Contains `:` (with non-empty prefix) → ecosystem (`prefix:name[@version]`).
40
+ * 3. Otherwise → bare name (`name[@version]`).
41
+ *
42
+ * @throws Error when input is empty or has malformed `owner/repo` shape.
43
+ */
44
+ export function parseDocSpec(input) {
45
+ if (!input) {
46
+ throw new Error('docs spec is empty — expected `owner/repo`, `ecosystem:name`, or `name`');
47
+ }
48
+ // 1. github shape: owner/repo[@ref]
49
+ // Strict: must contain `/` AND no `:`. The `:` exclusion prevents
50
+ // scoped ecosystem specs (e.g. `npm:@scope/pkg@1.0`) from being
51
+ // mis-parsed as github — they contain a slash but the colon prefix
52
+ // means they belong to the ecosystem branch.
53
+ if (input.includes('/') && !input.includes(':')) {
54
+ const parts = input.split('/');
55
+ if (parts.length !== 2) {
56
+ throw new Error(`invalid docs spec '${input}': github shorthand must contain exactly one slash (owner/repo)`);
57
+ }
58
+ const [owner, repoAndRef] = parts;
59
+ if (!owner) {
60
+ throw new Error(`invalid docs spec '${input}': owner segment is empty`);
61
+ }
62
+ if (!repoAndRef) {
63
+ throw new Error(`invalid docs spec '${input}': repo segment is empty`);
64
+ }
65
+ const atIdx = repoAndRef.indexOf('@');
66
+ if (atIdx >= 0) {
67
+ const repo = repoAndRef.substring(0, atIdx);
68
+ const ref = repoAndRef.substring(atIdx + 1);
69
+ if (!repo) {
70
+ throw new Error(`invalid docs spec '${input}': repo segment is empty`);
71
+ }
72
+ return ref ? { kind: 'github', owner, repo, ref } : { kind: 'github', owner, repo };
73
+ }
74
+ return { kind: 'github', owner, repo: repoAndRef };
75
+ }
76
+ // 2. ecosystem shape: prefix:name[@version]
77
+ const colonIdx = input.indexOf(':');
78
+ if (colonIdx > 0) {
79
+ const ecosystem = input.substring(0, colonIdx);
80
+ const rest = input.substring(colonIdx + 1);
81
+ const { name, version } = splitNameVersion(rest);
82
+ return { kind: 'ecosystem', ecosystem, name, version };
83
+ }
84
+ // 3. bare name: name[@version]
85
+ const { name, version } = splitNameVersion(input);
86
+ return { kind: 'name', name, version };
87
+ }
88
+ /**
89
+ * Detect ecosystem from project files in cwd.
90
+ */
91
+ function detectEcosystem(projectDir) {
92
+ const checks = [
93
+ ['package.json', 'npm'],
94
+ ['pubspec.yaml', 'pub'],
95
+ ['pyproject.toml', 'pypi'],
96
+ ['requirements.txt', 'pypi'],
97
+ ['go.mod', 'go'],
98
+ ['Cargo.toml', 'crates'],
99
+ ['mix.exs', 'hex'],
100
+ ['pom.xml', 'maven'],
101
+ ['build.gradle', 'maven'],
102
+ ['build.gradle.kts', 'maven'],
103
+ ];
104
+ for (const [file, ecosystem] of checks) {
105
+ if (fs.existsSync(path.join(projectDir, file))) {
106
+ return ecosystem;
107
+ }
108
+ }
109
+ return 'npm';
110
+ }
111
+ /**
112
+ * Fetch registry entry from the registry API.
113
+ *
114
+ * Accepts either `(owner, repo)` for direct lookup or `(ecosystem, name)`
115
+ * for alias-based lookup — the API handles both patterns via catch-all slug.
116
+ */
117
+ export async function fetchRegistryEntry(first, second) {
118
+ const url = `${REGISTRY_BASE_URL}/api/registry/${first}/${second}`;
119
+ try {
120
+ const response = await fetch(url);
121
+ if (!response.ok) {
122
+ return null;
123
+ }
124
+ const data = await response.json();
125
+ return data;
126
+ }
127
+ catch (error) {
128
+ consola.debug(`Registry lookup failed for ${first}/${second}:`, error);
129
+ return null;
130
+ }
131
+ }
132
+ /**
133
+ * Source type priority for selecting the best strategy from a registry entry.
134
+ *
135
+ * Lower number = higher priority. Based on Nuxt UI eval results (2026-04-07):
136
+ * GitHub docs achieved 100% pass rate at lowest cost, while llms.txt scored
137
+ * below baseline. See evals/nuxt-ui/README.md for full methodology.
138
+ */
139
+ const SOURCE_PRIORITY = {
140
+ 'github': 0,
141
+ 'npm': 1,
142
+ 'web': 2,
143
+ 'llms-txt': 3,
144
+ };
145
+ /**
146
+ * Pick the highest-priority strategy from a list, preserving the original
147
+ * order for ties (stable sort).
148
+ */
149
+ export function selectBestStrategy(strategies) {
150
+ if (strategies.length === 0) {
151
+ throw new Error('selectBestStrategy requires at least one strategy');
152
+ }
153
+ // Stable sort by priority — lower priority value wins
154
+ const indexed = Array.from(strategies, (s, i) => ({ s, i }));
155
+ indexed.sort((a, b) => {
156
+ const pa = SOURCE_PRIORITY[a.s.source] ?? 99;
157
+ const pb = SOURCE_PRIORITY[b.s.source] ?? 99;
158
+ if (pa !== pb)
159
+ return pa - pb;
160
+ return a.i - b.i;
161
+ });
162
+ return indexed[0].s;
163
+ }
164
+ /**
165
+ * Resolve source config from registry.
166
+ * Returns the highest-priority strategy from the registry entry.
167
+ */
168
+ export async function resolveFromRegistry(input, projectDir) {
169
+ const { ecosystem: explicitEcosystem, spec } = parseEcosystem(input);
170
+ const lastAt = spec.lastIndexOf('@');
171
+ const name = lastAt > 0 ? spec.substring(0, lastAt) : spec;
172
+ const version = lastAt > 0 ? spec.substring(lastAt + 1) : 'latest';
173
+ const ecosystem = explicitEcosystem ?? detectEcosystem(projectDir);
174
+ consola.info(`Looking up ${ecosystem}:${name} in registry...`);
175
+ const entry = await fetchRegistryEntry(ecosystem, name);
176
+ if (!entry) {
177
+ return null;
178
+ }
179
+ let strategies;
180
+ try {
181
+ strategies = expandStrategies({
182
+ repo: entry.repo,
183
+ docsPath: entry.docsPath,
184
+ strategies: entry.strategies,
185
+ });
186
+ }
187
+ catch (error) {
188
+ consola.warn(`Registry entry for ${name} is misconfigured: ${error.message}`);
189
+ return null;
190
+ }
191
+ consola.success(`Found ${entry.name} in registry: ${entry.description}`);
192
+ const strategy = selectBestStrategy(strategies);
193
+ consola.info(`Using source: ${strategy.source}`);
194
+ return {
195
+ ecosystem,
196
+ name: entry.name,
197
+ version,
198
+ strategy,
199
+ };
200
+ }
201
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Result of resolving an ecosystem package to a GitHub repository.
3
+ * Always handed off to the github source for download.
4
+ */
5
+ export interface ResolveResult {
6
+ /** GitHub `owner/repo` */
7
+ repo: string;
8
+ /** Primary git ref to try first (tag or branch) */
9
+ ref: string;
10
+ /**
11
+ * Fallback refs to try if the primary ref doesn't exist.
12
+ * Implements FR-5: try `v{version}`, then `{version}`, then default branch.
13
+ */
14
+ fallbackRefs?: string[];
15
+ /** Resolved version string (e.g. `4.17.21`) */
16
+ resolvedVersion: string;
17
+ }
18
+ /**
19
+ * Ecosystem resolver: maps a package name + version to a GitHub repository.
20
+ *
21
+ * Resolvers are orthogonal to sources — they only perform metadata lookups
22
+ * and never download documentation themselves. The resolved `repo` + `ref`
23
+ * are handed to the `github` source for the actual download.
24
+ */
25
+ export interface EcosystemResolver {
26
+ resolve: (name: string, version: string) => Promise<ResolveResult>;
27
+ }
28
+ /**
29
+ * Return the resolver for the given ecosystem, or `null` if unsupported.
30
+ */
31
+ export declare function getResolver(ecosystem: string): EcosystemResolver | null;
32
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resolvers/index.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAA;IACX;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,+CAA+C;IAC/C,eAAe,EAAE,MAAM,CAAA;CACxB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,CAAC,CAAA;CACnE;AAWD;;GAEG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAEvE"}
@@ -0,0 +1,17 @@
1
+ import { MavenResolver } from './maven.js';
2
+ import { NpmResolver } from './npm.js';
3
+ import { PubResolver } from './pub.js';
4
+ import { PypiResolver } from './pypi.js';
5
+ const resolvers = {
6
+ maven: new MavenResolver(),
7
+ npm: new NpmResolver(),
8
+ pypi: new PypiResolver(),
9
+ pub: new PubResolver(),
10
+ };
11
+ /**
12
+ * Return the resolver for the given ecosystem, or `null` if unsupported.
13
+ */
14
+ export function getResolver(ecosystem) {
15
+ return resolvers[ecosystem] ?? null;
16
+ }
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resolvers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAiCxC,MAAM,SAAS,GAAkD;IAC/D,KAAK,EAAE,IAAI,aAAa,EAAE;IAC1B,GAAG,EAAE,IAAI,WAAW,EAAE;IACtB,IAAI,EAAE,IAAI,YAAY,EAAE;IACxB,GAAG,EAAE,IAAI,WAAW,EAAE;CACvB,CAAA;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,SAAiB;IAC3C,OAAQ,SAA+C,CAAC,SAAS,CAAC,IAAI,IAAI,CAAA;AAC5E,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { EcosystemResolver, ResolveResult } from './index.js';
2
+ /**
3
+ * Resolve a Maven Central package to a GitHub repo + git tag.
4
+ *
5
+ * 1. Fetch latest version from Maven Central Search API
6
+ * 2. For explicit versions, use the version directly
7
+ * 3. Extract GitHub repo from Search API scmUrl, or fallback to POM XML
8
+ * 4. Return `v{version}` as the git ref with `{version}` fallback
9
+ */
10
+ export declare class MavenResolver implements EcosystemResolver {
11
+ resolve(name: string, version: string): Promise<ResolveResult>;
12
+ /**
13
+ * Resolve version via Search API. Falls back to POM-based resolution
14
+ * when the Search API is unavailable.
15
+ *
16
+ * For explicit versions, the version is used as-is (no Search API needed
17
+ * for validation — the POM fetch will fail if it doesn't exist).
18
+ */
19
+ private resolveVersion;
20
+ /**
21
+ * Fetch version and optional scmUrl from Maven Central Search API.
22
+ */
23
+ private fetchSearchApi;
24
+ /**
25
+ * Resolve latest version from maven-metadata.xml when Search API is unavailable.
26
+ */
27
+ private resolveVersionFromMetadata;
28
+ /**
29
+ * Find GitHub repo URL from POM XML. Priority: <scm><url> → <url>
30
+ */
31
+ private findRepoFromPom;
32
+ }
33
+ //# sourceMappingURL=maven.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maven.d.ts","sourceRoot":"","sources":["../../src/resolvers/maven.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAqFlE;;;;;;;GAOG;AACH,qBAAa,aAAc,YAAW,iBAAiB;IAC/C,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAsCpE;;;;;;OAMG;YACW,cAAc;IAuB5B;;OAEG;YACW,cAAc;IA0C5B;;OAEG;YACW,0BAA0B;IAyBxC;;OAEG;YACW,eAAe;CAgB9B"}
@@ -0,0 +1,187 @@
1
+ import { consola } from 'consola';
2
+ import { parseRepoUrl } from './utils.js';
3
+ const RE_SCM_URL = /<scm>[\s\S]*?<url>([^<]+)<\/url>/;
4
+ const RE_PROJECT_URL = /<project[^>]*>[\s\S]*?<url>([^<]+)<\/url>/;
5
+ /**
6
+ * Parse `groupId:artifactId` from the combined name string.
7
+ * Splits at the last colon — groupId may contain dots but never colons,
8
+ * while artifactId never contains colons.
9
+ */
10
+ function parseMavenCoordinate(name) {
11
+ const lastColon = name.lastIndexOf(':');
12
+ if (lastColon <= 0 || lastColon === name.length - 1) {
13
+ throw new Error(`Invalid Maven coordinate '${name}': expected 'groupId:artifactId' format (e.g. 'com.google.guava:guava')`);
14
+ }
15
+ return {
16
+ groupId: name.substring(0, lastColon),
17
+ artifactId: name.substring(lastColon + 1),
18
+ };
19
+ }
20
+ const RE_DOT = /\./g;
21
+ const RE_RELEASE = /<release>([^<]+)<\/release>/;
22
+ const RE_LATEST = /<latest>([^<]+)<\/latest>/;
23
+ /**
24
+ * Build the Maven Central Repository POM URL.
25
+ * Converts groupId dots to path separators.
26
+ */
27
+ function buildPomUrl(groupId, artifactId, version) {
28
+ const groupPath = groupId.replace(RE_DOT, '/');
29
+ return `https://repo1.maven.org/maven2/${groupPath}/${artifactId}/${version}/${artifactId}-${version}.pom`;
30
+ }
31
+ /**
32
+ * Extract a GitHub repository URL from POM XML content.
33
+ * Priority: <scm><url> → top-level <url>
34
+ */
35
+ function extractRepoFromPom(pomXml) {
36
+ // Try <scm><url> first
37
+ const scmMatch = RE_SCM_URL.exec(pomXml);
38
+ if (scmMatch) {
39
+ const repo = parseRepoUrl(scmMatch[1].trim());
40
+ if (repo)
41
+ return repo;
42
+ }
43
+ // Fall back to top-level <url>
44
+ const urlMatch = RE_PROJECT_URL.exec(pomXml);
45
+ if (urlMatch) {
46
+ const repo = parseRepoUrl(urlMatch[1].trim());
47
+ if (repo)
48
+ return repo;
49
+ }
50
+ return null;
51
+ }
52
+ /**
53
+ * Resolve a Maven Central package to a GitHub repo + git tag.
54
+ *
55
+ * 1. Fetch latest version from Maven Central Search API
56
+ * 2. For explicit versions, use the version directly
57
+ * 3. Extract GitHub repo from Search API scmUrl, or fallback to POM XML
58
+ * 4. Return `v{version}` as the git ref with `{version}` fallback
59
+ */
60
+ export class MavenResolver {
61
+ async resolve(name, version) {
62
+ const { groupId, artifactId } = parseMavenCoordinate(name);
63
+ // Step 1: Resolve version + optional scmUrl via Search API
64
+ const versionResult = await this.resolveVersion(groupId, artifactId, version);
65
+ const resolvedVersion = versionResult.version;
66
+ // Step 2: Find GitHub repo — priority: (1) Search API scmUrl, (2) POM <scm><url>, (3) POM <url>
67
+ let repo = null;
68
+ // (1) Check Search API scmUrl first
69
+ if (versionResult.scmUrl) {
70
+ repo = parseRepoUrl(versionResult.scmUrl);
71
+ }
72
+ // (2, 3) Fall back to POM XML
73
+ if (!repo) {
74
+ repo = await this.findRepoFromPom(groupId, artifactId, resolvedVersion);
75
+ }
76
+ if (!repo) {
77
+ throw new Error(`Cannot resolve GitHub repository for Maven package '${groupId}:${artifactId}'. `
78
+ + `Neither the Search API nor the POM contains a GitHub URL. `
79
+ + `Use 'owner/repo' format instead: ask docs add owner/repo`);
80
+ }
81
+ consola.debug(`maven: ${groupId}:${artifactId}@${version} → ${repo}@${resolvedVersion}`);
82
+ return {
83
+ repo,
84
+ ref: `v${resolvedVersion}`,
85
+ fallbackRefs: [resolvedVersion],
86
+ resolvedVersion,
87
+ };
88
+ }
89
+ /**
90
+ * Resolve version via Search API. Falls back to POM-based resolution
91
+ * when the Search API is unavailable.
92
+ *
93
+ * For explicit versions, the version is used as-is (no Search API needed
94
+ * for validation — the POM fetch will fail if it doesn't exist).
95
+ */
96
+ async resolveVersion(groupId, artifactId, version) {
97
+ // Explicit versions can skip Search API for version resolution
98
+ if (version !== 'latest') {
99
+ // Still try Search API for scmUrl, but don't fail if unavailable
100
+ try {
101
+ return await this.fetchSearchApi(groupId, artifactId, version);
102
+ }
103
+ catch {
104
+ return { version };
105
+ }
106
+ }
107
+ // For 'latest', try Search API first
108
+ try {
109
+ return await this.fetchSearchApi(groupId, artifactId, version);
110
+ }
111
+ catch {
112
+ // Search API unavailable — try maven-metadata.xml for latest version
113
+ consola.debug(`maven: Search API unavailable, trying maven-metadata.xml`);
114
+ return this.resolveVersionFromMetadata(groupId, artifactId);
115
+ }
116
+ }
117
+ /**
118
+ * Fetch version and optional scmUrl from Maven Central Search API.
119
+ */
120
+ async fetchSearchApi(groupId, artifactId, version) {
121
+ const isLatest = version === 'latest';
122
+ const query = isLatest
123
+ ? `q=g:${encodeURIComponent(groupId)}+AND+a:${encodeURIComponent(artifactId)}&rows=1&wt=json`
124
+ : `q=g:${encodeURIComponent(groupId)}+AND+a:${encodeURIComponent(artifactId)}+AND+v:${encodeURIComponent(version)}&rows=1&wt=json&core=gav`;
125
+ const url = `https://search.maven.org/solrsearch/select?${query}`;
126
+ const response = await fetch(url);
127
+ if (!response.ok) {
128
+ throw new Error(`Maven Central Search API returned ${response.status} for ${groupId}:${artifactId}`);
129
+ }
130
+ const data = await response.json();
131
+ if (data.response.numFound === 0) {
132
+ throw new Error(`Maven package '${groupId}:${artifactId}'${isLatest ? '' : `@${version}`} not found on Maven Central`);
133
+ }
134
+ const doc = data.response.docs[0];
135
+ // Try to get scmUrl from artifact-level search (default core, not GAV)
136
+ let scmUrl;
137
+ try {
138
+ const extUrl = `https://search.maven.org/solrsearch/select?q=g:${encodeURIComponent(groupId)}+AND+a:${encodeURIComponent(artifactId)}&rows=1&wt=json`;
139
+ const extResponse = await fetch(extUrl);
140
+ if (extResponse.ok) {
141
+ const extData = await extResponse.json();
142
+ scmUrl = extData.response.docs[0]?.['scm.url'];
143
+ }
144
+ }
145
+ catch {
146
+ // Non-critical — will fall back to POM
147
+ }
148
+ return { version: doc.v, scmUrl };
149
+ }
150
+ /**
151
+ * Resolve latest version from maven-metadata.xml when Search API is unavailable.
152
+ */
153
+ async resolveVersionFromMetadata(groupId, artifactId) {
154
+ const groupPath = groupId.replace(RE_DOT, '/');
155
+ const url = `https://repo1.maven.org/maven2/${groupPath}/${artifactId}/maven-metadata.xml`;
156
+ const response = await fetch(url);
157
+ if (!response.ok) {
158
+ throw new Error(`Cannot resolve Maven package '${groupId}:${artifactId}': `
159
+ + `Search API unavailable and maven-metadata.xml returned ${response.status}`);
160
+ }
161
+ const xml = await response.text();
162
+ const versionMatch = RE_RELEASE.exec(xml) ?? RE_LATEST.exec(xml);
163
+ if (!versionMatch) {
164
+ throw new Error(`Cannot resolve latest version for Maven package '${groupId}:${artifactId}': `
165
+ + `no <release> or <latest> tag in maven-metadata.xml`);
166
+ }
167
+ return { version: versionMatch[1] };
168
+ }
169
+ /**
170
+ * Find GitHub repo URL from POM XML. Priority: <scm><url> → <url>
171
+ */
172
+ async findRepoFromPom(groupId, artifactId, version) {
173
+ const pomUrl = buildPomUrl(groupId, artifactId, version);
174
+ try {
175
+ const response = await fetch(pomUrl);
176
+ if (response.ok) {
177
+ const pomXml = await response.text();
178
+ return extractRepoFromPom(pomXml);
179
+ }
180
+ }
181
+ catch {
182
+ consola.debug(`maven: POM fetch failed for ${groupId}:${artifactId}@${version}`);
183
+ }
184
+ return null;
185
+ }
186
+ }
187
+ //# sourceMappingURL=maven.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maven.js","sourceRoot":"","sources":["../../src/resolvers/maven.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAyBzC,MAAM,UAAU,GAAG,kCAAkC,CAAA;AACrD,MAAM,cAAc,GAAG,2CAA2C,CAAA;AAElE;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,IAAY;IACxC,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IACvC,IAAI,SAAS,IAAI,CAAC,IAAI,SAAS,KAAK,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CACb,6BAA6B,IAAI,yEAAyE,CAC3G,CAAA;IACH,CAAC;IACD,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC;QACrC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,GAAG,CAAC,CAAC;KAC1C,CAAA;AACH,CAAC;AAED,MAAM,MAAM,GAAG,KAAK,CAAA;AACpB,MAAM,UAAU,GAAG,6BAA6B,CAAA;AAChD,MAAM,SAAS,GAAG,2BAA2B,CAAA;AAE7C;;;GAGG;AACH,SAAS,WAAW,CAAC,OAAe,EAAE,UAAkB,EAAE,OAAe;IACvE,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC9C,OAAO,kCAAkC,SAAS,IAAI,UAAU,IAAI,OAAO,IAAI,UAAU,IAAI,OAAO,MAAM,CAAA;AAC5G,CAAC;AAED;;;GAGG;AACH,SAAS,kBAAkB,CAAC,MAAc;IACxC,uBAAuB;IACvB,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACxC,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;QAC7C,IAAI,IAAI;YACN,OAAO,IAAI,CAAA;IACf,CAAC;IAED,+BAA+B;IAC/B,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC5C,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;QAC7C,IAAI,IAAI;YACN,OAAO,IAAI,CAAA;IACf,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,aAAa;IACxB,KAAK,CAAC,OAAO,CAAC,IAAY,EAAE,OAAe;QACzC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAA;QAE1D,2DAA2D;QAC3D,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;QAC7E,MAAM,eAAe,GAAG,aAAa,CAAC,OAAO,CAAA;QAE7C,gGAAgG;QAChG,IAAI,IAAI,GAAkB,IAAI,CAAA;QAE9B,oCAAoC;QACpC,IAAI,aAAa,CAAC,MAAM,EAAE,CAAC;YACzB,IAAI,GAAG,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;QAC3C,CAAC;QAED,8BAA8B;QAC9B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,eAAe,CAAC,CAAA;QACzE,CAAC;QAED,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CACb,uDAAuD,OAAO,IAAI,UAAU,KAAK;kBAC/E,4DAA4D;kBAC5D,0DAA0D,CAC7D,CAAA;QACH,CAAC;QAED,OAAO,CAAC,KAAK,CAAC,UAAU,OAAO,IAAI,UAAU,IAAI,OAAO,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC,CAAA;QAExF,OAAO;YACL,IAAI;YACJ,GAAG,EAAE,IAAI,eAAe,EAAE;YAC1B,YAAY,EAAE,CAAC,eAAe,CAAC;YAC/B,eAAe;SAChB,CAAA;IACH,CAAC;IAED;;;;;;OAMG;IACK,KAAK,CAAC,cAAc,CAAC,OAAe,EAAE,UAAkB,EAAE,OAAe;QAC/E,+DAA+D;QAC/D,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;YACzB,iEAAiE;YACjE,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;YAChE,CAAC;YACD,MAAM,CAAC;gBACL,OAAO,EAAE,OAAO,EAAE,CAAA;YACpB,CAAC;QACH,CAAC;QAED,qCAAqC;QACrC,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;QAChE,CAAC;QACD,MAAM,CAAC;YACL,qEAAqE;YACrE,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAA;YACzE,OAAO,IAAI,CAAC,0BAA0B,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;QAC7D,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,cAAc,CAAC,OAAe,EAAE,UAAkB,EAAE,OAAe;QAC/E,MAAM,QAAQ,GAAG,OAAO,KAAK,QAAQ,CAAA;QACrC,MAAM,KAAK,GAAG,QAAQ;YACpB,CAAC,CAAC,OAAO,kBAAkB,CAAC,OAAO,CAAC,UAAU,kBAAkB,CAAC,UAAU,CAAC,iBAAiB;YAC7F,CAAC,CAAC,OAAO,kBAAkB,CAAC,OAAO,CAAC,UAAU,kBAAkB,CAAC,UAAU,CAAC,UAAU,kBAAkB,CAAC,OAAO,CAAC,0BAA0B,CAAA;QAE7I,MAAM,GAAG,GAAG,8CAA8C,KAAK,EAAE,CAAA;QACjE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;QAEjC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,qCAAqC,QAAQ,CAAC,MAAM,QAAQ,OAAO,IAAI,UAAU,EAAE,CACpF,CAAA;QACH,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAyB,CAAA;QAEzD,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CACb,kBAAkB,OAAO,IAAI,UAAU,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,6BAA6B,CACtG,CAAA;QACH,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAEjC,uEAAuE;QACvE,IAAI,MAA0B,CAAA;QAC9B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,kDAAkD,kBAAkB,CAAC,OAAO,CAAC,UAAU,kBAAkB,CAAC,UAAU,CAAC,iBAAiB,CAAA;YACrJ,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,CAAA;YACvC,IAAI,WAAW,CAAC,EAAE,EAAE,CAAC;gBACnB,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,EAA2D,CAAA;gBACjG,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,CAAA;YAChD,CAAC;QACH,CAAC;QACD,MAAM,CAAC;YACL,uCAAuC;QACzC,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAA;IACnC,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,0BAA0B,CAAC,OAAe,EAAE,UAAkB;QAC1E,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QAC9C,MAAM,GAAG,GAAG,kCAAkC,SAAS,IAAI,UAAU,qBAAqB,CAAA;QAE1F,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;QACjC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,iCAAiC,OAAO,IAAI,UAAU,KAAK;kBACzD,0DAA0D,QAAQ,CAAC,MAAM,EAAE,CAC9E,CAAA;QACH,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QACjC,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAEhE,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CACb,oDAAoD,OAAO,IAAI,UAAU,KAAK;kBAC5E,oDAAoD,CACvD,CAAA;QACH,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAA;IACrC,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,eAAe,CAAC,OAAe,EAAE,UAAkB,EAAE,OAAe;QAChF,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;QAExD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,CAAA;YACpC,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAChB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;gBACpC,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAA;YACnC,CAAC;QACH,CAAC;QACD,MAAM,CAAC;YACL,OAAO,CAAC,KAAK,CAAC,+BAA+B,OAAO,IAAI,UAAU,IAAI,OAAO,EAAE,CAAC,CAAA;QAClF,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ import type { EcosystemResolver, ResolveResult } from './index.js';
2
+ /**
3
+ * Resolve an npm package to a GitHub repo + git tag.
4
+ *
5
+ * 1. Fetch `https://registry.npmjs.org/<name>`
6
+ * 2. Resolve version: dist-tag → exact, semver range → best match, exact → passthrough
7
+ * 3. Extract `repository.url` → `owner/repo`
8
+ * 4. Return `v{version}` as the git ref
9
+ */
10
+ export declare class NpmResolver implements EcosystemResolver {
11
+ resolve(name: string, version: string): Promise<ResolveResult>;
12
+ }
13
+ //# sourceMappingURL=npm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"npm.d.ts","sourceRoot":"","sources":["../../src/resolvers/npm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAgBlE;;;;;;;GAOG;AACH,qBAAa,WAAY,YAAW,iBAAiB;IAC7C,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;CAkErE"}