Skip to content

Commit

Permalink
Merge branch 'master' into feat/proxy-mode
Browse files Browse the repository at this point in the history
  • Loading branch information
hezhengxu2018 committed Aug 12, 2023
2 parents 7d64259 + 3f9c91c commit e151c3f
Show file tree
Hide file tree
Showing 36 changed files with 267 additions and 93 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## [3.40.0](https://github.com/cnpm/cnpmcore/compare/v3.39.5...v3.40.0) (2023-08-08)


### Features

* signup on auth ([#567](https://github.com/cnpm/cnpmcore/issues/567)) ([c710600](https://github.com/cnpm/cnpmcore/commit/c7106008d9e5da1760919010899f7a0e24acd051))

## [3.39.5](https://github.com/cnpm/cnpmcore/compare/v3.39.4...v3.39.5) (2023-08-08)


### Bug Fixes

* noImplicitAny ts ([#568](https://github.com/cnpm/cnpmcore/issues/568)) ([1932bb9](https://github.com/cnpm/cnpmcore/commit/1932bb9713187bcd4d7e0b0dde410cb0118ab607))

## [3.39.4](https://github.com/cnpm/cnpmcore/compare/v3.39.3...v3.39.4) (2023-08-04)


Expand Down
4 changes: 2 additions & 2 deletions app/common/FileUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,13 @@ const WHITE_FILENAME_CONTENT_TYPES = {
'.eslintignore': PLAIN_TEXT,
'.jshintrc': 'application/json',
'.eslintrc': 'application/json',
};
} as const;

export function mimeLookup(filepath: string) {
const filename = path.basename(filepath).toLowerCase();
if (filename.endsWith('.ts')) return PLAIN_TEXT;
if (filename.endsWith('.lock')) return PLAIN_TEXT;
return mime.lookup(filename) ||
WHITE_FILENAME_CONTENT_TYPES[filename] ||
WHITE_FILENAME_CONTENT_TYPES[filename as keyof typeof WHITE_FILENAME_CONTENT_TYPES] ||
DEFAULT_CONTENT_TYPE;
}
2 changes: 1 addition & 1 deletion app/common/UserUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function integrity(plain: string): string {
}

export function checkIntegrity(plain: string, expectedIntegrity: string): boolean {
return ssri.checkData(plain, expectedIntegrity);
return !!ssri.checkData(plain, expectedIntegrity);
}

export function sha512(plain: string): string {
Expand Down
3 changes: 2 additions & 1 deletion app/common/adapter/NPMRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
HttpClientRequestOptions,
HttpClientResponse,
} from 'egg';
import { PackageManifestType } from '../../repository/PackageRepository';

type HttpMethod = HttpClientRequestOptions['method'];

Expand Down Expand Up @@ -40,7 +41,7 @@ export class NPMRegistry {
this.registryHost = registryHost;
}

public async getFullManifests(fullname: string, optionalConfig?: {retries?:number, remoteAuthToken?:string}): Promise<RegistryResponse> {
public async getFullManifests(fullname: string, optionalConfig?: { retries?: number, remoteAuthToken?: string }): Promise<{ method: HttpMethod } & HttpClientResponse<PackageManifestType>> {
// set query t=timestamp, make sure CDN cache disable
// cache=0 is sync worker request flag
const url = `${this.registry}/${encodeURIComponent(fullname)}?t=${Date.now()}&cache=0`;
Expand Down
8 changes: 5 additions & 3 deletions app/common/adapter/binary/AbstractBinary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export type FetchResult = {
nextParams?: any;
};

const platforms = [ 'darwin', 'linux', 'win32' ] as const;

export const BINARY_ADAPTER_ATTRIBUTE = Symbol('BINARY_ADAPTER_ATTRIBUTE');

export abstract class AbstractBinary {
Expand Down Expand Up @@ -74,7 +76,7 @@ export abstract class AbstractBinary {

protected listNodePlatforms() {
// https://nodejs.org/api/os.html#osplatform
return [ 'darwin', 'linux', 'win32' ];
return platforms;
}

protected listNodeArchs(binaryConfig?: BinaryTaskConfig) {
Expand All @@ -87,11 +89,11 @@ export abstract class AbstractBinary {
};
}

protected listNodeLibcs() {
protected listNodeLibcs(): Record<typeof platforms[number], string[]> {
// https://github.com/lovell/detect-libc/blob/master/lib/detect-libc.js#L42
return {
linux: [ 'glibc', 'musl' ],
darwin: [ 'unknown' ],
linux: [ 'glibc', 'musl' ],
win32: [ 'unknown' ],
};
}
Expand Down
4 changes: 2 additions & 2 deletions app/common/adapter/binary/PlaywrightBinary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ const DOWNLOAD_PATHS = {
'android': {
'<unknown>': 'builds/android/%s/android.zip',
},
};
} as const;

@SingletonProto()
@BinaryAdapter(BinaryType.Playwright)
Expand All @@ -215,7 +215,7 @@ export class PlaywrightBinary extends AbstractBinary {
.filter(version => version.match(/^(?:\d+\.\d+\.\d+)(?:-beta-\d+)?$/))
// select recently update 20 items
.slice(-20);
const browsers: { name: string; revision: string; browserVersion: string; revisionOverrides?: Record<string, string> }[] = [];
const browsers: { name: keyof typeof DOWNLOAD_PATHS; revision: string; browserVersion: string; revisionOverrides?: Record<string, string> }[] = [];
await Promise.all(
packageVersions.map(version =>
this.requestJSON(
Expand Down
14 changes: 12 additions & 2 deletions app/common/adapter/changesStream/CnpmjsorgChangesStream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ import { AbstractChangeStream, RegistryChangesStream } from './AbstractChangesSt

const MAX_LIMIT = 10000;

type FetchResults = {
results: {
seq: number;
type: string;
id: string;
changes: Record<string, string>[];
gmt_modified: Date,
}[];
};

@SingletonProto()
@RegistryChangesStream(RegistryType.Cnpmjsorg)
export class CnpmjsorgChangesStream extends AbstractChangeStream {
Expand All @@ -18,13 +28,13 @@ export class CnpmjsorgChangesStream extends AbstractChangeStream {
return since;
}

private async tryFetch(registry: Registry, since: string, limit = 1000) {
private async tryFetch(registry: Registry, since: string, limit = 1000): Promise<{ data: FetchResults }> {
if (limit > MAX_LIMIT) {
throw new E500(`limit too large, current since: ${since}, limit: ${limit}`);
}
const db = this.getChangesStreamUrl(registry, since, limit);
// json mode
const res = await this.httpclient.request(db, {
const res = await this.httpclient.request<FetchResults>(db, {
followRedirect: true,
timeout: 30000,
dataType: 'json',
Expand Down
2 changes: 1 addition & 1 deletion app/core/entity/BugVersion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export type BugVersionPackages = Record<string, BugVersionPackage>;
export class BugVersion {
private readonly data: BugVersionPackages;

constructor(data) {
constructor(data: BugVersionPackages) {
this.data = data;
}

Expand Down
2 changes: 1 addition & 1 deletion app/core/entity/Hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class Hook extends Entity {
}

// payload 可能会特别大,如果做多次 stringify 浪费太多 cpu
signPayload(payload: object): { digest, payloadStr } {
signPayload(payload: object) {
const payloadStr = JSON.stringify(payload);
const digest = crypto.createHmac('sha256', this.secret)
.update(JSON.stringify(payload))
Expand Down
2 changes: 1 addition & 1 deletion app/core/entity/SqlRange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class SqlRange {
};
}
const paddingSemver = new PaddingSemVer(comparator.semver);
const operator = OPERATOR_MAP[comparator.operator];
const operator = OPERATOR_MAP[comparator.operator as keyof typeof OPERATOR_MAP];
if (!operator) {
throw new Error(`unknown operator ${comparator.operator}`);
}
Expand Down
2 changes: 1 addition & 1 deletion app/core/service/BugVersionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class BugVersionService {
const packageVersionJson = (await this.distRepository.findPackageVersionManifest(pkg!.packageId, tag!.version)) as PackageJSONType;
if (!packageVersionJson) return;
const data = packageVersionJson.config?.['bug-versions'];
bugVersion = new BugVersion(data);
bugVersion = new BugVersion(data || {});
this.bugVersionStore.setBugVersion(bugVersion, tag!.version);
}
return bugVersion;
Expand Down
11 changes: 7 additions & 4 deletions app/core/service/PackageManagerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ export class PackageManagerService extends AbstractService {

public plusPackageVersionCounter(fullname: string, version: string) {
// set counter + 1, schedule will store them into database
const counters = PackageManagerService.downloadCounters;
const counters: Record<string, Record<string, number>> = PackageManagerService.downloadCounters;
if (!counters[fullname]) counters[fullname] = {};
counters[fullname][version] = (counters[fullname][version] || 0) + 1;
// Total
Expand All @@ -444,7 +444,7 @@ export class PackageManagerService extends AbstractService {
// will be call by schedule/SavePackageVersionDownloadCounter.ts
async savePackageVersionCounters() {
// { [fullname]: { [version]: number } }
const counters = PackageManagerService.downloadCounters;
const counters: Record<string, Record<string, number>> = PackageManagerService.downloadCounters;
const fullnames = Object.keys(counters);
if (fullnames.length === 0) return;

Expand Down Expand Up @@ -724,13 +724,16 @@ export class PackageManagerService extends AbstractService {
const fieldsFromLatestManifest = [
'author', 'bugs', 'contributors', 'description', 'homepage', 'keywords', 'license',
'readmeFilename', 'repository',
];
] as const;
// the latest version metas
for (const field of fieldsFromLatestManifest) {
fullManifests[field] = latestManifest[field];
if (latestManifest[field]) {
(fullManifests as Record<string, unknown>)[field] = latestManifest[field];
}
}
}


private async _setPackageDistTagsAndLatestInfos(pkg: Package, fullManifests: PackageManifestType, abbreviatedManifests: AbbreviatedPackageManifestType) {
const distTags = await this._listPackageDistTags(pkg);
if (distTags.latest) {
Expand Down
6 changes: 3 additions & 3 deletions app/core/service/PackageSyncerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { downloadToTempfile } from '../../common/FileUtil';
import { TaskState, TaskType } from '../../common/enum/Task';
import { AbstractService } from '../../common/AbstractService';
import { TaskRepository } from '../../repository/TaskRepository';
import { PackageJSONType, PackageRepository } from '../../repository/PackageRepository';
import { PackageJSONType, PackageManifestType, PackageRepository } from '../../repository/PackageRepository';
import { PackageVersionDownloadRepository } from '../../repository/PackageVersionDownloadRepository';
import { UserRepository } from '../../repository/UserRepository';
import { Task, SyncPackageTaskOptions, CreateSyncPackageTask } from '../entity/Task';
Expand Down Expand Up @@ -484,7 +484,7 @@ export class PackageSyncerService extends AbstractService {
// { name: 'jasonlaster11', email: '[email protected]' }
// ],
let maintainers = data.maintainers;
const maintainersMap = {};
const maintainersMap: Record<string, PackageManifestType['maintainers']> = {};
const users: User[] = [];
let changedUserCount = 0;
if (!Array.isArray(maintainers) || maintainers.length === 0) {
Expand Down Expand Up @@ -619,7 +619,7 @@ export class PackageSyncerService extends AbstractService {
}
if (!isEqual(remoteItemValue, existsItem[key])) {
diffMeta[key] = remoteItemValue;
} else if (!ignoreInAbbreviated.includes(key) && existsAbbreviatedItem && !isEqual(remoteItemValue, existsAbbreviatedItem[key])) {
} else if (!ignoreInAbbreviated.includes(key) && existsAbbreviatedItem && !isEqual(remoteItemValue, (existsAbbreviatedItem as Record<string, unknown>)[key])) {
// should diff exists abbreviated item too
diffMeta[key] = remoteItemValue;
}
Expand Down
2 changes: 1 addition & 1 deletion app/core/service/PackageVersionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export class PackageVersionService {
if (isFullManifests) {
manifest = await this.distRepository.findPackageVersionManifest(pkgId, version);
} else {
manifest = this.distRepository.findPackageAbbreviatedManifest(pkgId, version);
manifest = await this.distRepository.findPackageAbbreviatedManifest(pkgId, version);
}
if (manifest && bugVersionAdvice) {
manifest.deprecated = `[WARNING] Use ${bugVersionAdvice.advice.version} instead of ${bugVersionAdvice.version}, reason: ${bugVersionAdvice.advice.reason}`;
Expand Down
18 changes: 11 additions & 7 deletions app/core/service/UserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,19 +106,23 @@ export class UserService extends AbstractService {
return { code: LoginResultCode.Success, user, token };
}

async ensureTokenByUser({ name, email, password = crypto.randomUUID(), ip }: Optional<CreateUser, 'password'>) {
async findOrCreateUser({ name, email, ip, password = crypto.randomUUID() }: Optional<CreateUser, 'password'>) {
let user = await this.userRepository.findUserByName(name);
if (!user) {
const createRes = await this.create({
name,
email,
// Authentication via sso
// should use token instead of password
password,
ip,
});
user = createRes.user;
}

return user;
}

async ensureTokenByUser(opts: Optional<CreateUser, 'password'>) {
const user = await this.findOrCreateUser(opts);
const token = await this.createToken(user.userId);
return { user, token };
}
Expand Down Expand Up @@ -199,14 +203,14 @@ export class UserService extends AbstractService {
await this.userRepository.removeToken(token.tokenId);
}

async findWebauthnCredential(userId: string, browserType?: string) {
async findWebauthnCredential(userId: string, browserType: string | undefined | null) {
const credential = await this.userRepository.findCredentialByUserIdAndBrowserType(userId, browserType || null);
return credential;
}

async createWebauthnCredential(userId: string, options: CreateWebauthnCredentialOptions) {
async createWebauthnCredential(userId: string | undefined, options: CreateWebauthnCredentialOptions) {
const credentialEntity = WebauthnCredentialEntity.create({
userId,
userId: userId as string,
credentialId: options.credentialId,
publicKey: options.publicKey,
browserType: options.browserType,
Expand All @@ -215,7 +219,7 @@ export class UserService extends AbstractService {
return credentialEntity;
}

async removeWebauthnCredential(userId: string, browserType?: string) {
async removeWebauthnCredential(userId?: string, browserType?: string) {
const credential = await this.userRepository.findCredentialByUserIdAndBrowserType(userId, browserType || null);
if (credential) {
await this.userRepository.removeCredential(credential.wancId);
Expand Down
15 changes: 7 additions & 8 deletions app/port/controller/DownloadController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ export class DownloadController extends AbstractController {
const pkg = await this.packageRepository.findPackage(scope, name);
if (!pkg) throw new NotFoundError(`${fullname} not found`);
const entities = await this.packageVersionDownloadRepository.query(pkg.packageId, startDate.toDate(), endDate.toDate());
const days = {};
const versions = {};
const days: Record<string, number> = {};
const versions: Record<string, { day: string, downloads: number }[]> = {};
for (const entity of entities) {
const yearMonth = String(entity.yearMonth);
const prefix = yearMonth.substring(0, 4) + '-' + yearMonth.substring(4, 6);
for (let i = 1; i <= 31; i++) {
const day = String(i).padStart(2, '0');
const field = `d${day}`;
const counter = entity[field];
const field = `d${day}` as keyof typeof entity;
const counter = entity[field] as number;
if (!counter) continue;
const date = `${prefix}-${day}`;
days[date] = (days[date] || 0) + counter;
Expand Down Expand Up @@ -66,14 +66,14 @@ export class DownloadController extends AbstractController {
async showTotalDownloads(@HTTPParam() scope: string, @HTTPParam() range: string) {
const [ startDate, endDate ] = this.checkAndGetRange(range);
const entities = await this.packageVersionDownloadRepository.query(scope, startDate.toDate(), endDate.toDate());
const days = {};
const days: Record<string, number> = {};
for (const entity of entities) {
const yearMonth = String(entity.yearMonth);
const prefix = yearMonth.substring(0, 4) + '-' + yearMonth.substring(4, 6);
for (let i = 1; i <= 31; i++) {
const day = String(i).padStart(2, '0');
const field = `d${day}`;
const counter = entity[field];
const field = `d${day}` as keyof typeof entity;
const counter = entity[field] as number;
if (!counter) continue;
const date = `${prefix}-${day}`;
days[date] = (days[date] || 0) + counter;
Expand Down Expand Up @@ -115,4 +115,3 @@ export class DownloadController extends AbstractController {
return [ startDate, endDate ];
}
}

2 changes: 1 addition & 1 deletion app/port/controller/PackageTagController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class PackageTagController extends AbstractController {
async showTags(@HTTPParam() fullname: string) {
const packageEntity = await this.getPackageEntityByFullname(fullname);
const tagEntities = await this.packageRepository.listPackageTags(packageEntity.packageId);
const tags = {};
const tags: Record<string, string> = {};
for (const entity of tagEntities) {
tags[entity.tag] = entity.version;
}
Expand Down
9 changes: 3 additions & 6 deletions app/port/controller/TokenController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,12 @@ export class TokenController extends AbstractController {
return { objects, total: objects.length, urls: {} };
}

private async ensureWebUser() {
private async ensureWebUser(ip = '') {
const userRes = await this.authAdapter.ensureCurrentUser();
if (!userRes?.name || !userRes?.email) {
throw new ForbiddenError('need login first');
}
const user = await this.userService.findUserByName(userRes.name);
if (!user?.userId) {
throw new ForbiddenError('invalid user info');
}
const user = await this.userService.findOrCreateUser({ name: userRes.name, email: userRes.email, ip });
return user;
}

Expand All @@ -155,7 +152,7 @@ export class TokenController extends AbstractController {
// 3. Need to implement ensureCurrentUser method in AuthAdapter, or pass in this.user
async createGranularToken(@Context() ctx: EggContext, @HTTPBody() tokenOptions: GranularTokenOptions) {
ctx.tValidate(GranularTokenOptionsRule, tokenOptions);
const user = await this.ensureWebUser();
const user = await this.ensureWebUser(ctx.ip);

// 生成 Token
const { name, description, allowedPackages, allowedScopes, cidr_whitelist, automation, readonly, expires } = tokenOptions;
Expand Down
Loading

0 comments on commit e151c3f

Please sign in to comment.