feat(registry): modernize npm registry file handling and package extraction APIs

This commit is contained in:
2026-05-01 15:39:02 +00:00
parent 3bb68776fb
commit 0dedf79fa7
14 changed files with 3712 additions and 4592 deletions
+31 -18
View File
@@ -13,12 +13,14 @@ export interface INpmRegistryConstructorOptions {
}
export class NpmRegistry {
public options: INpmRegistryConstructorOptions;
public options: Required<INpmRegistryConstructorOptions>;
public registryCache: RegistryCache;
public smartFs = new plugins.smartfs.SmartFs(new plugins.smartfs.SmartFsProviderNode());
public smartFileFactory = plugins.smartfile.SmartFileFactory.nodeFs();
private searchDomain = 'https://api.npms.io/v2/search?q=';
constructor(optionsArg: INpmRegistryConstructorOptions = {}) {
const defaultOptions: INpmRegistryConstructorOptions = {
const defaultOptions: Required<INpmRegistryConstructorOptions> = {
npmRegistryUrl: 'https://registry.npmjs.org',
};
this.options = {
@@ -46,10 +48,17 @@ export class NpmRegistry {
registryUrl: this.options.npmRegistryUrl,
allVersions: true,
});
if (!fullMetadata) {
throw new Error(`Could not retrieve metadata for package ${packageName}.`);
}
const npmPackage = await NpmPackage.createFromFullMetadataAndVersionData(
this,
fullMetadata,
versionData as any
versionData as {
name: string;
'dist-tags': { [key: string]: string };
versions: { [key: string]: import('./smartnpm.classes.packageversion.js').IVersionData };
}
);
return npmPackage;
}
@@ -60,7 +69,7 @@ export class NpmRegistry {
* @param targetDir
*/
public async savePackageToDisk(packageName: string, targetDir: string): Promise<void> {
plugins.smartfile.fs.ensureDirSync(paths.nogitDir);
await this.smartFs.directory(paths.nogitDir).create();
const npmPackage = await this.getPackageInfo(packageName);
await npmPackage.saveToDisk(targetDir);
}
@@ -75,7 +84,7 @@ export class NpmRegistry {
distTag?: string;
version?: string;
}
): Promise<plugins.smartfile.SmartFile> {
): Promise<plugins.smartfile.SmartFile | null> {
// lets create a cache descriptor
const cacheDescriptor: ICacheDescriptor = {
registryUrl: this.options.npmRegistryUrl,
@@ -86,7 +95,7 @@ export class NpmRegistry {
};
// lets see if we have something cached
const cachedFile: plugins.smartfile.SmartFile = await this.registryCache.getCachedFile(
const cachedFile = await this.registryCache.getCachedFile(
cacheDescriptor
);
@@ -98,9 +107,8 @@ export class NpmRegistry {
(packageArg) => packageArg.name === 'latest'
);
if (!latestAvailable) {
optionsArg = {
version: npmPackage.getBestMatchingVersion('*'),
};
const version = npmPackage.getBestMatchingVersion('*');
optionsArg = version ? { version } : undefined;
}
}
const fileResult = await npmPackage.getFileFromPackage(filePathArg, optionsArg);
@@ -120,16 +128,15 @@ export class NpmRegistry {
distTag?: string;
version?: string;
}
): Promise<plugins.smartfile.SmartFile[]> {
): Promise<plugins.smartfile.SmartFile[] | null> {
const npmPackage = await this.getPackageInfo(packageNameArg);
if (!optionsArg?.version && !optionsArg?.distTag) {
const latestAvailable = npmPackage.allDistTags.find(
(packageDistTagArg) => packageDistTagArg.name === 'latest'
);
if (!latestAvailable) {
optionsArg = {
version: npmPackage.getBestMatchingVersion('*'),
};
const version = npmPackage.getBestMatchingVersion('*');
optionsArg = version ? { version } : undefined;
}
}
return npmPackage.getFilesFromPackage(filePath, optionsArg);
@@ -142,10 +149,10 @@ export class NpmRegistry {
* TODO: rewrite as memory only
*/
const baseDir = plugins.path.join(paths.nogitDir, packageNameArg.replace('/', '__'));
await plugins.smartfile.fs.ensureDir(baseDir);
await this.smartFs.directory(baseDir).create();
await this.savePackageToDisk(packageNameArg, baseDir);
const virtualDir = await plugins.smartfile.VirtualDirectory.fromFsDirPath(baseDir);
await plugins.smartfile.fs.remove(baseDir);
const virtualDir = await this.smartFileFactory.virtualDirectoryFromPath(baseDir);
await this.smartFs.directory(baseDir).recursive().delete();
return virtualDir;
}
@@ -224,7 +231,13 @@ export class NpmRegistry {
`info: Search on npm for ${plugins.consolecolor.coloredString(searchString, 'pink')}`
);
let body: any;
let body: {
results?: Array<{
package: {
name: string;
};
}>;
} | string | undefined;
try {
const response = await plugins.smartrequest.SmartRequest.create()
.url(this.searchDomain + searchString)
@@ -238,7 +251,7 @@ export class NpmRegistry {
const packageArray: NpmPackage[] = [];
// if request failed just return it empty
if (!body || typeof body === 'string') {
if (!body || typeof body === 'string' || !Array.isArray(body.results)) {
return packageArray;
}