Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions lib/services/install/npm-resolve.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,16 @@ const SEARCH_RESULT_LIMIT = 250;
* 保证「配置了镜像」时反查和安装走同一个源(镜像节点同步完整时结果一致)。
* 慢网络下失败不阻塞安装。
*/
export function resolveNpmPackage(repo, registry = '') {
export async function resolveNpmPackage(repo, registry = '') {
const key = repo.toLowerCase();
if (cache.has(key))
return Promise.resolve(cache.get(key) ?? null);
const name = searchRepo(repo, registry);
const name = searchRepo(repo, registry).then(async (found) => {
if (found !== null)
return found;
const canonical = await canonicalRepo(repo);
return canonical.toLowerCase() === key ? found : searchRepo(canonical, registry);
});
void name.then((found) => {
if (found !== undefined)
cache.set(key, found);
Expand Down Expand Up @@ -65,7 +70,7 @@ export function isDshPackageMetadataForRepo(pkg, repo) {
const manifestMarked = pkg.dsh !== null && typeof pkg.dsh === 'object';
return keywordMarked || manifestMarked;
}
export function isDshNpmPackageForRepo(packageName, repo, registry = '') {
export async function isDshNpmPackageForRepo(packageName, repo, registry = '') {
if (packageName === '' || repo === '')
return Promise.resolve(false);
const base = registry === '' ? 'https://registry.npmjs.org' : registry.replace(/\/+$/, '');
Expand All @@ -79,9 +84,11 @@ export function isDshNpmPackageForRepo(packageName, repo, registry = '') {
}
let body = '';
res.on('data', (chunk) => { body += chunk.toString(); });
res.on('end', () => {
res.on('end', async () => {
try {
resolve(isDshPackageMetadataForRepo(JSON.parse(body), repo));
const pkg = JSON.parse(body);
resolve(isDshPackageMetadataForRepo(pkg, repo)
|| isDshPackageMetadataForRepo(pkg, await canonicalRepo(repo)));
}
catch {
resolve(false);
Expand All @@ -92,6 +99,20 @@ export function isDshNpmPackageForRepo(packageName, repo, registry = '') {
req.on('error', () => resolve(false));
});
}
async function canonicalRepo(repo) {
if (githubRepoOf(repo) === null)
return repo;
try {
const response = await fetch(`https://github.com/${repo}`, {
method: 'HEAD',
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
});
return response.ok ? githubRepoOf(response.url) ?? repo : repo;
}
catch {
return repo;
}
}
function matchingPackagesForRepo(objects, repo) {
const matches = [];
for (const obj of objects) {
Expand Down
4 changes: 3 additions & 1 deletion lib/services/install/preflight.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ export async function preflightTarget(target) {
return { ok: true, missing: null, name: null };
const entry = resolvePackageEntry(meta);
const inTar = await hasTarEntry(tar, `${rootPrefix}${entry}`);
return { ok: inTar, missing: inTar ? null : entry, name: typeof meta.name === 'string' ? meta.name : null };
const prepare = meta.scripts?.prepare;
const ok = inTar || (typeof prepare === 'string' && prepare.trim() !== '');
return { ok, missing: ok ? null : entry, name: typeof meta.name === 'string' ? meta.name : null };
}
catch {
return { ok: true, missing: null, name: null };
Expand Down
29 changes: 24 additions & 5 deletions src/server/services/install/npm-resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,14 @@ const SEARCH_RESULT_LIMIT = 250
* 保证「配置了镜像」时反查和安装走同一个源(镜像节点同步完整时结果一致)。
* 慢网络下失败不阻塞安装。
*/
export function resolveNpmPackage(repo: string, registry = ''): Promise<string | null> {
export async function resolveNpmPackage(repo: string, registry = ''): Promise<string | null> {
const key = repo.toLowerCase()
if (cache.has(key)) return Promise.resolve(cache.get(key) ?? null)
const name = searchRepo(repo, registry)
const name = searchRepo(repo, registry).then(async (found) => {
if (found !== null) return found
const canonical = await canonicalRepo(repo)
return canonical.toLowerCase() === key ? found : searchRepo(canonical, registry)
})
void name.then((found) => {
if (found !== undefined) cache.set(key, found)
})
Expand Down Expand Up @@ -77,7 +81,7 @@ export function isDshPackageMetadataForRepo(pkg: NpmSearchPackage, repo: string)
return keywordMarked || manifestMarked
}

export function isDshNpmPackageForRepo(packageName: string, repo: string, registry = ''): Promise<boolean> {
export async function isDshNpmPackageForRepo(packageName: string, repo: string, registry = ''): Promise<boolean> {
if (packageName === '' || repo === '') return Promise.resolve(false)
const base = registry === '' ? 'https://registry.npmjs.org' : registry.replace(/\/+$/, '')
const url = `${base}/${encodeURIComponent(packageName)}/latest`
Expand All @@ -90,9 +94,11 @@ export function isDshNpmPackageForRepo(packageName: string, repo: string, regist
}
let body = ''
res.on('data', (chunk: Buffer) => { body += chunk.toString() })
res.on('end', () => {
res.on('end', async () => {
try {
resolve(isDshPackageMetadataForRepo(JSON.parse(body) as NpmSearchPackage, repo))
const pkg = JSON.parse(body) as NpmSearchPackage
resolve(isDshPackageMetadataForRepo(pkg, repo)
|| isDshPackageMetadataForRepo(pkg, await canonicalRepo(repo)))
} catch {
resolve(false)
}
Expand All @@ -103,6 +109,19 @@ export function isDshNpmPackageForRepo(packageName: string, repo: string, regist
})
}

async function canonicalRepo(repo: string): Promise<string> {
if (githubRepoOf(repo) === null) return repo
try {
const response = await fetch(`https://github.com/${repo}`, {
method: 'HEAD',
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
})
return response.ok ? githubRepoOf(response.url) ?? repo : repo
} catch {
return repo
}
}

function matchingPackagesForRepo(objects: NpmSearchObject[], repo: string): Array<{ name: string; isDshPlugin: boolean }> {
const matches: Array<{ name: string; isDshPlugin: boolean }> = []

Expand Down
4 changes: 3 additions & 1 deletion src/server/services/install/preflight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ export async function preflightTarget(target: string): Promise<PreflightResult>
if (meta === null) return { ok: true, missing: null, name: null }
const entry = resolvePackageEntry(meta)
const inTar = await hasTarEntry(tar, `${rootPrefix}${entry}`)
return { ok: inTar, missing: inTar ? null : entry, name: typeof meta.name === 'string' ? meta.name : null }
const prepare = (meta.scripts as { prepare?: unknown } | undefined)?.prepare
const ok = inTar || (typeof prepare === 'string' && prepare.trim() !== '')
return { ok, missing: ok ? null : entry, name: typeof meta.name === 'string' ? meta.name : null }
} catch {
return { ok: true, missing: null, name: null }
} finally {
Expand Down