187 lines
5.5 KiB
TypeScript
187 lines
5.5 KiB
TypeScript
import * as plugins from './smartnpm.plugins';
|
|
import { NpmRegistry } from './smartnpm.classes.npmregistry';
|
|
import { PackageDisttag } from './smartnpm.classes.packagedisttag';
|
|
import { PackageVersion, IVersionData } from './smartnpm.classes.packageversion';
|
|
|
|
export class NpmPackage {
|
|
public static async createFromFullMetadataAndVersionData(
|
|
npmRegistryArg: NpmRegistry,
|
|
fullMetadataArg: plugins.packageJson.FullMetadata,
|
|
versionsDataArg: {
|
|
name: string;
|
|
'dist-tags': { [key: string]: string };
|
|
versions: { [key: string]: IVersionData };
|
|
}
|
|
) {
|
|
const npmPackage = new NpmPackage(npmRegistryArg);
|
|
Object.assign(npmPackage, fullMetadataArg);
|
|
npmPackage.allVersions = [];
|
|
npmPackage.allDistTags = [];
|
|
for (const versionArg of Object.keys(versionsDataArg.versions)) {
|
|
const packageVersion = PackageVersion.createFromVersionData(
|
|
versionsDataArg.versions[versionArg]
|
|
);
|
|
npmPackage.allVersions.push(packageVersion);
|
|
}
|
|
for (const distTagArg of Object.keys(versionsDataArg['dist-tags'])) {
|
|
const packageDistTag = new PackageDisttag(
|
|
distTagArg,
|
|
versionsDataArg['dist-tags'][distTagArg]
|
|
);
|
|
npmPackage.allDistTags.push(packageDistTag);
|
|
}
|
|
return npmPackage;
|
|
}
|
|
|
|
// INSTANCE
|
|
public name: string = null;
|
|
public scope: string = null;
|
|
public version: string = null;
|
|
public allVersions: PackageVersion[];
|
|
public allDistTags: PackageDisttag[];
|
|
public description: string = null;
|
|
public keywords: string[] = null;
|
|
public date: string;
|
|
public license: string;
|
|
public links: {
|
|
npm: string;
|
|
homepage: string;
|
|
repository: string;
|
|
bugs: string;
|
|
};
|
|
public author: {
|
|
name: 'Lossless GmbH';
|
|
};
|
|
public publisher: {
|
|
username: 'gitzone';
|
|
email: 'npm@git.zone';
|
|
};
|
|
public maintainers: any = null;
|
|
public dist: {
|
|
integrity: string;
|
|
shasum: string;
|
|
tarball: string;
|
|
};
|
|
public score: {
|
|
final: number;
|
|
detail: {
|
|
quality: number;
|
|
popularity: number;
|
|
maintenance: number;
|
|
};
|
|
} = null;
|
|
public searchScore: number = null;
|
|
|
|
public npmRegistryRef: NpmRegistry;
|
|
constructor(npmRegistryArg: NpmRegistry) {
|
|
this.npmRegistryRef = npmRegistryArg;
|
|
}
|
|
|
|
/**
|
|
* saves the package to disk
|
|
*/
|
|
public async saveToDisk(targetDir: string) {
|
|
const smartarchiveInstance = new plugins.smartarchive.SmartArchive();
|
|
await smartarchiveInstance.extractArchiveFromUrlToFs(this.dist.tarball, targetDir);
|
|
}
|
|
|
|
/**
|
|
* saves the complete package to cache
|
|
*/
|
|
public async saveToCache() {}
|
|
|
|
/**
|
|
* get files from package
|
|
*/
|
|
public async getFilesFromPackage(
|
|
filePath: string,
|
|
optionsArg: {
|
|
distTag?: string;
|
|
version?: string;
|
|
},
|
|
returnOnFirstArg = false
|
|
): Promise<plugins.smartfile.Smartfile[]> {
|
|
const done = plugins.smartpromise.defer<plugins.smartfile.Smartfile[]>();
|
|
const smartarchiveInstance = new plugins.smartarchive.SmartArchive();
|
|
let tarballUrl = this.dist?.tarball;
|
|
if (optionsArg?.version || optionsArg?.distTag) {
|
|
if (optionsArg.distTag && optionsArg.version) {
|
|
throw new Error('Please either specify version OR disttag, not both.');
|
|
}
|
|
let targetVersionString: string;
|
|
if (optionsArg.distTag) {
|
|
const targetDistTag = this.allDistTags.find((distTag) => {
|
|
return distTag.name === optionsArg.distTag;
|
|
});
|
|
if (targetDistTag) {
|
|
targetVersionString = targetDistTag.targetVersion;
|
|
}
|
|
} else {
|
|
targetVersionString = optionsArg.version;
|
|
}
|
|
|
|
// lets find the best matching release
|
|
const bestMatchingVersion = this.getBestMatchingVersion(targetVersionString);
|
|
if (!bestMatchingVersion) {
|
|
return null;
|
|
}
|
|
tarballUrl = this.allVersions.find(
|
|
(packageVersion) => packageVersion.version === bestMatchingVersion
|
|
).dist.tarball;
|
|
}
|
|
const fileObservable = await smartarchiveInstance.extractArchiveFromUrlToObservable(tarballUrl);
|
|
const wantedFilePath = plugins.path.join('package', filePath);
|
|
const allMatchingFiles: plugins.smartfile.Smartfile[] = [];
|
|
const subscription = fileObservable.subscribe(
|
|
(fileArg) => {
|
|
// returnOnFirstArg requires exact match
|
|
if (returnOnFirstArg && fileArg.path === wantedFilePath) {
|
|
// lets resolve with the wanted file
|
|
done.resolve([fileArg]);
|
|
subscription.unsubscribe();
|
|
} else if(!returnOnFirstArg && fileArg.path.startsWith(wantedFilePath)) {
|
|
allMatchingFiles.push(fileArg);
|
|
}
|
|
},
|
|
(err) => {
|
|
console.log(err);
|
|
},
|
|
() => {
|
|
done.resolve(allMatchingFiles);
|
|
subscription.unsubscribe();
|
|
}
|
|
);
|
|
return done.promise;
|
|
}
|
|
|
|
/**
|
|
* get files from package
|
|
*/
|
|
public async getFileFromPackage(
|
|
filePath: string,
|
|
optionsArg?: {
|
|
distTag?: string;
|
|
version?: string;
|
|
}
|
|
): Promise<plugins.smartfile.Smartfile> {
|
|
const result = await this.getFilesFromPackage(filePath, optionsArg, true);
|
|
return result[0];
|
|
}
|
|
|
|
/**
|
|
* updates the package with information from the registry
|
|
*/
|
|
update() {}
|
|
|
|
/** */
|
|
public getBestMatchingVersion(versionArg: string): string {
|
|
// lets find the best matching release
|
|
const targetVersion = plugins.smartversion.SmartVersion.fromFuzzyString(versionArg);
|
|
const versionStrings = this.allVersions.map((packageVersion) => packageVersion.version);
|
|
const bestMatchingVersion = targetVersion.getBestMatch(versionStrings);
|
|
if (!bestMatchingVersion) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|