@@ -52,10 +52,33 @@ class PackageJson {
5252 'binRefs' ,
5353 ] )
5454
55- // default behavior, loads a package.json at given path and JSON parses
56- static async load ( path ) {
55+ // create a new empty package.json, so we can save at the given path even
56+ // though we didn't start from a parsed file
57+ static async create ( path , opts = { } ) {
5758 const p = new PackageJson ( )
58- return p . load ( path )
59+ await p . create ( path )
60+ if ( opts . data ) {
61+ return p . update ( opts . data )
62+ }
63+ return p
64+ }
65+
66+ // Loads a package.json at given path and JSON parses
67+ static async load ( path , opts = { } ) {
68+ const p = new PackageJson ( )
69+ // Avoid try/catch if we aren't going to create
70+ if ( ! opts . create ) {
71+ return p . load ( path )
72+ }
73+
74+ try {
75+ return await p . load ( path )
76+ } catch ( err ) {
77+ if ( ! err . message . startsWith ( 'Could not read package.json' ) ) {
78+ throw err
79+ }
80+ return await p . create ( path )
81+ }
5982 }
6083
6184 // read-package-json compatible behavior
@@ -159,10 +182,18 @@ class PackageJson {
159182 return undefined
160183 }
161184
185+ create ( path ) {
186+ this . #path = path
187+ this . #manifest = { }
188+ return this
189+ }
190+
191+ // This should be the ONLY way to set content in the manifest
162192 update ( content ) {
163193 if ( ! this . content ) {
164- throw new Error ( 'Can not update without existing data ' )
194+ throw new Error ( 'Can not update without content. Please `load` or `create` ' )
165195 }
196+
166197 for ( const step of knownSteps ) {
167198 this . #manifest = step ( { content, originalContent : this . content } )
168199 }
@@ -186,11 +217,8 @@ class PackageJson {
186217 [ Symbol . for ( 'newline' ) ] : newline ,
187218 } = this . content
188219
189- // These can only be undefined if we didn't parse JSON, which we currently don't support.
190- // const format = indent === undefined ? ' ' : indent
191- // const eol = newline === undefined ? '\n' : newline
192- const format = indent
193- const eol = newline
220+ const format = indent === undefined ? ' ' : indent
221+ const eol = newline === undefined ? '\n' : newline
194222 const fileContent = `${
195223 JSON . stringify ( this . content , null , format )
196224 } \n`
0 commit comments