/
migrated-data.ts
153 lines (132 loc) · 3.73 KB
/
migrated-data.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import detectIndent from 'detect-indent';
import JSON5 from 'json5';
import type { BuiltInParserName } from 'prettier';
import upath from 'upath';
import { migrateConfig } from '../../../../config/migration';
import { prettier } from '../../../../expose.cjs';
import { logger } from '../../../../logger';
import { scm } from '../../../../modules/platform/scm';
import { readLocalFile } from '../../../../util/fs';
import { detectRepoFileConfig } from '../../init/merge';
export interface MigratedData {
content: string;
filename: string;
indent: Indent;
}
interface Indent {
amount: number;
indent: string;
type?: string;
}
const prettierConfigFilenames = new Set([
'.prettierrc',
'.prettierrc.json',
'.prettierrc.yml',
'.prettierrc.yaml',
'.prettierrc.json5',
'.prettierrc.js',
'.prettierrc.cjs',
'prettier.config.js',
'prettier.config.cjs',
'.prettierrc.toml',
]);
export type PrettierParser = BuiltInParserName;
export async function applyPrettierFormatting(
content: string,
parser: PrettierParser,
indent?: Indent
): Promise<string> {
try {
logger.trace('applyPrettierFormatting - START');
const fileList = await scm.getFileList();
let prettierExists = fileList.some((file) =>
prettierConfigFilenames.has(file)
);
if (!prettierExists) {
try {
const packageJsonContent = await readLocalFile('package.json', 'utf8');
prettierExists =
packageJsonContent && JSON.parse(packageJsonContent).prettier;
} catch {
logger.warn(
'applyPrettierFormatting - Error processing package.json file'
);
}
}
if (!prettierExists) {
return content;
}
const options = {
parser,
tabWidth: indent?.amount === 0 ? 2 : indent?.amount,
useTabs: indent?.type === 'tab',
};
return prettier().format(content, options);
} finally {
logger.trace('applyPrettierFormatting - END');
}
}
export class MigratedDataFactory {
// singleton
private static data: MigratedData | null;
static async getAsync(): Promise<MigratedData | null> {
if (this.data) {
return this.data;
}
const migrated = await this.build();
if (!migrated) {
return null;
}
this.data = migrated;
return this.data;
}
static reset(): void {
this.data = null;
}
static applyPrettierFormatting({
content,
filename,
indent,
}: MigratedData): Promise<string> {
const parser = upath.extname(filename).replace('.', '') as PrettierParser;
return applyPrettierFormatting(content, parser, indent);
}
private static async build(): Promise<MigratedData | null> {
let res: MigratedData | null = null;
try {
const {
configFileName,
configFileRaw: raw,
configFileParsed = {},
} = await detectRepoFileConfig();
// get migrated config
const { isMigrated, migratedConfig } = migrateConfig(configFileParsed);
if (!isMigrated) {
return null;
}
delete migratedConfig.errors;
delete migratedConfig.warnings;
// indent defaults to 2 spaces
// TODO #7154
const indent = detectIndent(raw!);
const indentSpace = indent.indent ?? ' ';
const filename = configFileName!;
let content: string;
if (filename.endsWith('.json5')) {
content = JSON5.stringify(migratedConfig, undefined, indentSpace);
} else {
content = JSON.stringify(migratedConfig, undefined, indentSpace);
}
if (!content.endsWith('\n')) {
content += '\n';
}
res = { content, filename, indent };
} catch (err) {
logger.debug(
{ err },
'MigratedDataFactory.getAsync() Error initializing renovate MigratedData'
);
}
return res;
}
}