feat(registry): add declarative protocol routing and request-scoped storage hook context across registries
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
export type TNpmRequestRoute =
|
||||
| { type: 'root' }
|
||||
| { type: 'search' }
|
||||
| { type: 'userAuth'; username: string }
|
||||
| { type: 'tokens'; path: string }
|
||||
| { type: 'distTags'; packageName: string; tag?: string }
|
||||
| { type: 'tarball'; packageName: string; filename: string }
|
||||
| { type: 'unpublishVersion'; packageName: string; version: string }
|
||||
| { type: 'unpublishPackage'; packageName: string; rev: string }
|
||||
| { type: 'packageVersion'; packageName: string; version: string }
|
||||
| { type: 'package'; packageName: string };
|
||||
|
||||
function decodePackageName(rawPackageName: string): string {
|
||||
return decodeURIComponent(rawPackageName);
|
||||
}
|
||||
|
||||
export function parseNpmRequestRoute(path: string, method: string): TNpmRequestRoute | null {
|
||||
if (path === '/' || path === '') {
|
||||
return { type: 'root' };
|
||||
}
|
||||
|
||||
if (path.startsWith('/-/v1/search')) {
|
||||
return { type: 'search' };
|
||||
}
|
||||
|
||||
const userMatch = path.match(/^\/-\/user\/org\.couchdb\.user:(.+)$/);
|
||||
if (userMatch) {
|
||||
return {
|
||||
type: 'userAuth',
|
||||
username: userMatch[1],
|
||||
};
|
||||
}
|
||||
|
||||
if (path.startsWith('/-/npm/v1/tokens')) {
|
||||
return {
|
||||
type: 'tokens',
|
||||
path,
|
||||
};
|
||||
}
|
||||
|
||||
const distTagsMatch = path.match(/^\/-\/package\/(@?[^\/]+(?:\/[^\/]+)?)\/dist-tags(?:\/(.+))?$/);
|
||||
if (distTagsMatch) {
|
||||
const [, rawPackageName, tag] = distTagsMatch;
|
||||
return {
|
||||
type: 'distTags',
|
||||
packageName: decodePackageName(rawPackageName),
|
||||
tag,
|
||||
};
|
||||
}
|
||||
|
||||
const tarballMatch = path.match(/^\/(@?[^\/]+(?:\/[^\/]+)?)\/-\/(.+\.tgz)$/);
|
||||
if (tarballMatch) {
|
||||
const [, rawPackageName, filename] = tarballMatch;
|
||||
return {
|
||||
type: 'tarball',
|
||||
packageName: decodePackageName(rawPackageName),
|
||||
filename,
|
||||
};
|
||||
}
|
||||
|
||||
if (method === 'DELETE') {
|
||||
const unpublishVersionMatch = path.match(/^\/(@?[^\/]+(?:\/[^\/]+)?)\/-\/([^\/]+)$/);
|
||||
if (unpublishVersionMatch) {
|
||||
const [, rawPackageName, version] = unpublishVersionMatch;
|
||||
return {
|
||||
type: 'unpublishVersion',
|
||||
packageName: decodePackageName(rawPackageName),
|
||||
version,
|
||||
};
|
||||
}
|
||||
|
||||
const unpublishPackageMatch = path.match(/^\/(@?[^\/]+(?:\/[^\/]+)?)\/-rev\/([^\/]+)$/);
|
||||
if (unpublishPackageMatch) {
|
||||
const [, rawPackageName, rev] = unpublishPackageMatch;
|
||||
return {
|
||||
type: 'unpublishPackage',
|
||||
packageName: decodePackageName(rawPackageName),
|
||||
rev,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const unencodedScopedPackageMatch = path.match(/^\/@[^\/]+\/[^\/]+$/);
|
||||
if (unencodedScopedPackageMatch) {
|
||||
return {
|
||||
type: 'package',
|
||||
packageName: decodePackageName(path.substring(1)),
|
||||
};
|
||||
}
|
||||
|
||||
const versionMatch = path.match(/^\/(@?[^\/]+(?:\/[^\/]+)?)\/([^\/]+)$/);
|
||||
if (versionMatch) {
|
||||
const [, rawPackageName, version] = versionMatch;
|
||||
return {
|
||||
type: 'packageVersion',
|
||||
packageName: decodePackageName(rawPackageName),
|
||||
version,
|
||||
};
|
||||
}
|
||||
|
||||
const packageMatch = path.match(/^\/(@?[^\/]+(?:\/[^\/]+)?)$/);
|
||||
if (packageMatch) {
|
||||
return {
|
||||
type: 'package',
|
||||
packageName: decodePackageName(packageMatch[1]),
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user