1+ import type { Document as DocumentType } from 'yaml'
12import type { CommonOptions , DepType , PackageMeta , RawDep } from '../types'
23import * as fs from 'node:fs/promises'
34import detectIndent from 'detect-indent'
45import { resolve } from 'pathe'
5- import { parse as parseYaml , stringify as stringifyYaml } from 'yaml'
6+ import { Document , parseDocument as parseYaml , stringify as stringifyYaml } from 'yaml'
67import { builtinAddons } from '../addons'
7- import { dumpDependencies , getByPath , parseDependencies , parseDependency , setByPath } from './dependencies'
8+ import { dumpDependencies , getByPath , parseDependencies , parseDependency } from './dependencies'
89
910const allDepsFields = [
1011 'dependencies' ,
@@ -21,20 +22,21 @@ function isDepFieldEnabled(key: DepType, options: CommonOptions): boolean {
2122 return key === 'peerDependencies' ? ! ! options . peer : options . depFields ?. [ key ] !== false
2223}
2324
24- export async function readYAML ( filepath : string ) : Promise < Record < string , unknown > > {
25+ export async function readYAML ( filepath : string ) : Promise < DocumentType > {
2526 const content = await fs . readFile ( filepath , 'utf-8' )
2627 if ( ! content )
27- return { }
28+ return new Document ( { } )
2829
29- const parsed = parseYaml ( content )
30+ const document = parseYaml ( content , { merge : true } )
31+ const parsed = document . toJS ( )
3032
31- if ( ! parsed || typeof parsed !== 'object' || Array . isArray ( parsed ) )
33+ if ( document . errors . length || typeof parsed !== 'object' || Array . isArray ( parsed ) )
3234 throw new TypeError ( `Invalid package.yaml structure in ${ filepath } ` )
3335
34- return parsed as Record < string , unknown >
36+ return document
3537}
3638
37- export async function writeYAML ( filepath : string , data : Record < string , unknown > ) {
39+ export async function writeYAML ( filepath : string , data : DocumentType | Record < string , unknown > ) {
3840 const { amount, type } = await fs . readFile ( filepath , 'utf-8' )
3941 . then ( detectIndent )
4042 . catch ( Object . create )
@@ -64,22 +66,23 @@ export async function loadPackageYAML(
6466 continue
6567
6668 if ( key === 'packageManager' ) {
67- if ( raw . packageManager && typeof raw . packageManager === 'string' ) {
68- const [ name , version ] = raw . packageManager . split ( '@' )
69+ const packageManager = raw . get ( key )
70+ if ( typeof packageManager === 'string' ) {
71+ const [ name , version ] = packageManager . split ( '@' )
6972 // `+` sign can be used to pin the hash of the package manager, we remove it to be semver compatible.
7073 deps . push ( parseDependency ( name , `^${ version . split ( '+' ) [ 0 ] } ` , 'packageManager' , shouldUpdate ) )
7174 }
7275 }
7376 else {
74- deps . push ( ...parseDependencies ( raw , key , shouldUpdate ) )
77+ deps . push ( ...parseDependencies ( raw . toJS ( ) , key , shouldUpdate ) )
7578 }
7679 }
7780
7881 return [
7982 {
80- name : typeof raw . name === ' string' ? raw . name : '' ,
81- private : ! ! raw . private ,
82- version : typeof raw . version === ' string' ? raw . version : '' ,
83+ name : raw . get ( ' name' ) as string ?? '' ,
84+ private : ! ! raw . get ( ' private' ) ,
85+ version : raw . get ( ' version' ) as string ?? '' ,
8386 type : 'package.yaml' ,
8487 relative,
8588 filepath,
@@ -101,16 +104,18 @@ export async function writePackageYAML(
101104 continue
102105
103106 if ( key === 'packageManager' ) {
104- const value = Object . entries ( dumpDependencies ( pkg . resolved , 'packageManager' ) ) [ 0 ]
107+ const [ value ] = Object . entries ( dumpDependencies ( pkg . resolved , 'packageManager' ) )
105108 if ( value ) {
106- pkg . raw ||= { }
107- pkg . raw . packageManager = `${ value [ 0 ] } @${ value [ 1 ] . replace ( '^' , '' ) } `
109+ pkg . raw ??= new Document ( { } )
110+ pkg . raw . set ( ' packageManager' , `${ value [ 0 ] } @${ value [ 1 ] . replace ( '^' , '' ) } ` )
108111 changed = true
109112 }
110113 }
111114 else {
112- if ( getByPath ( pkg . raw , key ) ) {
113- setByPath ( pkg . raw , key , dumpDependencies ( pkg . resolved , key ) )
115+ if ( getByPath ( pkg . raw ?. toJS ?.( ) , key ) ) {
116+ const values = Object . entries ( dumpDependencies ( pkg . resolved , key ) )
117+ values . forEach ( ( [ lastKey , value ] ) =>
118+ pkg . raw ?. setIn ( [ ...key . split ( '.' ) , lastKey ] , value ) )
114119 changed = true
115120 }
116121 }
0 commit comments