@@ -23,15 +23,13 @@ import {
2323import { IBasePluginData } from "../definitions/plugins" ;
2424import { injector } from "../common/yok" ;
2525import { EOL } from "os" ;
26- import {
27- format as prettierFormat ,
28- resolveConfig as resolvePrettierConfig ,
29- } from "prettier" ;
3026import { cache , exported } from "../common/decorators" ;
3127import { IOptions } from "../declarations" ;
3228import * as semver from "semver/preload" ;
3329import { ICleanupService } from "../definitions/cleanup-service" ;
3430
31+ type PrettierModule = typeof import ( "prettier" ) ;
32+
3533export class ProjectConfigService implements IProjectConfigService {
3634 private forceUsingNewConfig : boolean = false ;
3735 private forceUsingLegacyConfig : boolean = false ;
@@ -273,27 +271,7 @@ export default {
273271 configContent ,
274272 ) ;
275273 const newContent = transformer . setValue ( key , value ) ;
276- const prettierOptions = ( await resolvePrettierConfig (
277- this . projectHelper . projectDir ,
278- { editorconfig : true } ,
279- ) ) || {
280- semi : false ,
281- singleQuote : true ,
282- } ;
283- this . $logger . trace (
284- "updating config, prettier options: " ,
285- prettierOptions ,
286- ) ;
287- this . $fs . writeFile (
288- configFilePath ,
289- await prettierFormat ( newContent , {
290- ...prettierOptions ,
291- parser : "typescript" ,
292- // note: we don't use plugins here, since we are only formatting ts files, and they are supported by default
293- // and this also causes issues with certain plugins, like prettier-plugin-tailwindcss.
294- plugins : [ ] ,
295- } ) ,
296- ) ;
274+ this . $fs . writeFile ( configFilePath , await this . formatConfig ( newContent ) ) ;
297275 } catch ( error ) {
298276 this . $logger . error ( `Failed to update config.` + error ) ;
299277 } finally {
@@ -318,6 +296,61 @@ export default {
318296 }
319297 }
320298
299+ /**
300+ * Resolved from the project first: the formatting options come from the
301+ * project's own prettier/editorconfig setup, so the project's prettier version
302+ * is the one that understands them. Required lazily - a broken or missing
303+ * prettier must not take down the CLI, since this is a core service.
304+ */
305+ private loadPrettier ( ) : PrettierModule {
306+ const projectDir = this . projectHelper . projectDir ;
307+
308+ if ( projectDir ) {
309+ try {
310+ return require ( require . resolve ( "prettier" , { paths : [ projectDir ] } ) ) ;
311+ } catch ( error ) {
312+ this . $logger . trace (
313+ "Could not load prettier from the project, using the bundled one." ,
314+ error ,
315+ ) ;
316+ }
317+ }
318+
319+ return require ( "prettier" ) ;
320+ }
321+
322+ private async formatConfig ( content : string ) : Promise < string > {
323+ try {
324+ const prettier = this . loadPrettier ( ) ;
325+ const prettierOptions = ( await prettier . resolveConfig (
326+ this . projectHelper . projectDir ,
327+ { editorconfig : true } ,
328+ ) ) || {
329+ semi : false ,
330+ singleQuote : true ,
331+ } ;
332+ this . $logger . trace (
333+ "updating config, prettier options: " ,
334+ prettierOptions ,
335+ ) ;
336+
337+ // awaiting covers both prettier 2 (sync) and prettier 3 (async) format
338+ return await prettier . format ( content , {
339+ ...prettierOptions ,
340+ parser : "typescript" ,
341+ // note: we don't use plugins here, since we are only formatting ts files, and they are supported by default
342+ // and this also causes issues with certain plugins, like prettier-plugin-tailwindcss.
343+ plugins : [ ] ,
344+ } ) ;
345+ } catch ( error ) {
346+ this . $logger . warn (
347+ "Could not format the config with prettier - it will be written unformatted." ,
348+ ) ;
349+ this . $logger . trace ( "prettier failed with: " , error ) ;
350+ return content ;
351+ }
352+ }
353+
321354 public writeDefaultConfig ( projectDir : string , appId ?: string ) {
322355 const TSConfigPath = path . resolve ( projectDir , CONFIG_FILE_NAME_TS ) ;
323356
0 commit comments