mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-27 07:50:47 +00:00
c32e2391a0
Refs #45216 The object counterpart to `prefer-coerce-array`: `x ?? {}` becomes `coerceObject(x)`. The rule flags a `??` whose default is a bare `{}` literal, so a populated default or an asserted `({} as Foo)` still passes; a `x ?? y ?? {}` chain maps onto `coerceObject(x, y)`. Every hit across `lib/` converted cleanly, so no disable comments were needed.
173 lines
4.4 KiB
TypeScript
173 lines
4.4 KiB
TypeScript
import { isNumber } from '@sindresorhus/is';
|
|
import JSON5 from 'json5';
|
|
import { parse as jsoncWeaverParse } from 'jsonc-weaver';
|
|
import type { JsonValue } from 'type-fest';
|
|
import { GlobalConfig } from '../config/global.ts';
|
|
import { InheritConfig, NOT_PRESENT } from '../config/inherit.ts';
|
|
import type { GlobalInheritableConfig } from '../config/types.ts';
|
|
import {
|
|
AZURE_API_USING_HOST_TYPES,
|
|
BITBUCKET_API_USING_HOST_TYPES,
|
|
BITBUCKET_SERVER_API_USING_HOST_TYPES,
|
|
FORGEJO_API_USING_HOST_TYPES,
|
|
GITEA_API_USING_HOST_TYPES,
|
|
GITHUB_API_USING_HOST_TYPES,
|
|
GITLAB_API_USING_HOST_TYPES,
|
|
} from '../constants/index.ts';
|
|
import { logger } from '../logger/index.ts';
|
|
import type { Nullish } from '../types/index.ts';
|
|
import * as hostRules from './host-rules.ts';
|
|
import { coerceObject } from './object.ts';
|
|
import { parseUrl } from './url.ts';
|
|
|
|
/**
|
|
* Tries to detect the `platform` from a url.
|
|
*
|
|
* @param url the url to detect `platform` from
|
|
* @returns matched `platform` if found, otherwise `null`
|
|
*/
|
|
export function detectPlatform(
|
|
url: string,
|
|
):
|
|
| 'azure'
|
|
| 'bitbucket'
|
|
| 'bitbucket-server'
|
|
| 'forgejo'
|
|
| 'gitea'
|
|
| 'github'
|
|
| 'gitlab'
|
|
| null {
|
|
const { hostname } = coerceObject(parseUrl(url));
|
|
if (hostname === 'dev.azure.com' || hostname?.endsWith('.visualstudio.com')) {
|
|
return 'azure';
|
|
}
|
|
if (hostname === 'bitbucket.org' || hostname === 'bitbucket.com') {
|
|
return 'bitbucket';
|
|
}
|
|
if (hostname?.includes('bitbucket')) {
|
|
return 'bitbucket-server';
|
|
}
|
|
if (hostname?.includes('forgejo')) {
|
|
return 'forgejo';
|
|
}
|
|
if (hostname && ['codeberg.org', 'codefloe.com'].includes(hostname)) {
|
|
return 'forgejo';
|
|
}
|
|
if (
|
|
hostname &&
|
|
(['gitea.com'].includes(hostname) || hostname.includes('gitea'))
|
|
) {
|
|
return 'gitea';
|
|
}
|
|
if (hostname === 'github.com' || hostname?.includes('github')) {
|
|
return 'github';
|
|
}
|
|
if (hostname === 'gitlab.com' || hostname?.includes('gitlab')) {
|
|
return 'gitlab';
|
|
}
|
|
|
|
const hostType = hostRules.hostType({ url });
|
|
|
|
if (!hostType) {
|
|
return null;
|
|
}
|
|
|
|
if (AZURE_API_USING_HOST_TYPES.includes(hostType)) {
|
|
return 'azure';
|
|
}
|
|
|
|
if (BITBUCKET_SERVER_API_USING_HOST_TYPES.includes(hostType)) {
|
|
return 'bitbucket-server';
|
|
}
|
|
if (BITBUCKET_API_USING_HOST_TYPES.includes(hostType)) {
|
|
return 'bitbucket';
|
|
}
|
|
if (FORGEJO_API_USING_HOST_TYPES.includes(hostType)) {
|
|
return 'forgejo';
|
|
}
|
|
if (GITEA_API_USING_HOST_TYPES.includes(hostType)) {
|
|
return 'gitea';
|
|
}
|
|
if (GITHUB_API_USING_HOST_TYPES.includes(hostType)) {
|
|
return 'github';
|
|
}
|
|
if (GITLAB_API_USING_HOST_TYPES.includes(hostType)) {
|
|
return 'gitlab';
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
export function noLeadingAtSymbol(input: string): string {
|
|
return input.startsWith('@') ? input.slice(1) : input;
|
|
}
|
|
|
|
export function parseJson(
|
|
content: Nullish<string>,
|
|
filename: string,
|
|
): JsonValue {
|
|
if (!content) {
|
|
return null;
|
|
}
|
|
|
|
if (filename.endsWith('.jsonc')) {
|
|
return parseJsonc(content);
|
|
}
|
|
|
|
if (filename.endsWith('.json5')) {
|
|
return JSON5.parse(content);
|
|
}
|
|
|
|
return parseJsonWithFallback(content, filename);
|
|
}
|
|
|
|
export function parseJsonWithFallback(
|
|
content: string,
|
|
context: string,
|
|
): JsonValue {
|
|
let parsedJson: JsonValue;
|
|
|
|
try {
|
|
parsedJson = parseJsonc(content);
|
|
} catch {
|
|
// warn if json5 format used in json
|
|
parsedJson = JSON5.parse(content);
|
|
logger.warn(
|
|
{ context },
|
|
'File contents are invalid JSONC but parse using JSON5. Support for this will be removed in a future release so please change to a support .json5 file name or ensure correct JSON syntax.',
|
|
);
|
|
}
|
|
|
|
return parsedJson;
|
|
}
|
|
|
|
export function parseJsonc(content: string): JsonValue {
|
|
return jsoncWeaverParse(content);
|
|
}
|
|
|
|
/**
|
|
* Use only if an option is inherited + globalOnly
|
|
* For globalOnly options use GlobalConfig.get
|
|
*/
|
|
export function getInheritedOrGlobal<Key extends keyof GlobalInheritableConfig>(
|
|
key: Key,
|
|
): GlobalInheritableConfig[Key] {
|
|
const inheritedValue = InheritConfig.get(key);
|
|
const globalValue = GlobalConfig.get(key);
|
|
if (inheritedValue !== NOT_PRESENT) {
|
|
// Don't allow inherited config to make `onboardingAutoCloseAge` a higher value than our global setting
|
|
if (
|
|
key === 'onboardingAutoCloseAge' &&
|
|
isNumber(inheritedValue) &&
|
|
isNumber(globalValue) &&
|
|
globalValue < inheritedValue
|
|
) {
|
|
return globalValue;
|
|
}
|
|
|
|
return inheritedValue;
|
|
}
|
|
|
|
return globalValue;
|
|
}
|