@@ -52,37 +52,37 @@ class PackageJson {
5252 'binRefs' ,
5353 ] )
5454
55- // default behavior, just loads and parses
55+ // default behavior, loads a package.json at given path and JSON parses
5656 static async load ( path ) {
57- return await new PackageJson ( path ) . load ( )
57+ const p = new PackageJson ( )
58+ return p . load ( path )
5859 }
5960
6061 // read-package-json compatible behavior
6162 static async prepare ( path , opts ) {
62- return await new PackageJson ( path ) . prepare ( opts )
63+ const p = new PackageJson ( )
64+ await p . load ( path , true )
65+ return p . prepare ( opts )
6366 }
6467
6568 // read-package-json-fast compatible behavior
6669 static async normalize ( path , opts ) {
67- return await new PackageJson ( path ) . normalize ( opts )
70+ const p = new PackageJson ( )
71+ await p . load ( path )
72+ return p . normalize ( opts )
6873 }
6974
70- #filename
7175 #path
72- #manifest = { }
76+ #manifest
7377 #readFileContent = ''
74- #fromIndex = false
78+ #canSave = true
7579
76- constructor ( path ) {
80+ // Load content from given path
81+ async load ( path , parseIndex ) {
7782 this . #path = path
78- this . #filename = resolve ( path , 'package.json' )
79- }
80-
81- async load ( parseIndex ) {
8283 let parseErr
8384 try {
84- this . #readFileContent =
85- await readFile ( this . #filename, 'utf8' )
85+ this . #readFileContent = await readFile ( this . filename , 'utf8' )
8686 } catch ( err ) {
8787 err . message = `Could not read package.json: ${ err } `
8888 if ( ! parseIndex ) {
@@ -92,31 +92,58 @@ class PackageJson {
9292 }
9393
9494 if ( parseErr ) {
95- const indexFile = resolve ( this . # path, 'index.js' )
95+ const indexFile = resolve ( this . path , 'index.js' )
9696 let indexFileContent
9797 try {
9898 indexFileContent = await readFile ( indexFile , 'utf8' )
9999 } catch ( err ) {
100100 throw parseErr
101101 }
102102 try {
103- this . #manifest = fromComment ( indexFileContent )
103+ this . fromComment ( indexFileContent )
104104 } catch ( err ) {
105105 throw parseErr
106106 }
107- this . #fromIndex = true
107+ // This wasn't a package.json so prevent saving
108+ this . #canSave = false
108109 return this
109110 }
110111
112+ return this . fromJSON ( this . #readFileContent)
113+ }
114+
115+ // Load data from a JSON string/buffer
116+ fromJSON ( data ) {
111117 try {
112- this . #manifest = parseJSON ( this . #readFileContent )
118+ this . #manifest = parseJSON ( data )
113119 } catch ( err ) {
114120 err . message = `Invalid package.json: ${ err } `
115121 throw err
116122 }
117123 return this
118124 }
119125
126+ // Load data from a comment
127+ // /**package { "name": "foo", "version": "1.2.3", ... } **/
128+ fromComment ( data ) {
129+ data = data . split ( / ^ \/ \* \* p a c k a g e (?: \s | $ ) / m)
130+
131+ if ( data . length < 2 ) {
132+ throw new Error ( 'File has no package in comments' )
133+ }
134+ data = data [ 1 ]
135+ data = data . split ( / \* \* \/ $ / m)
136+
137+ if ( data . length < 2 ) {
138+ throw new Error ( 'File has no package in comments' )
139+ }
140+ data = data [ 0 ]
141+ data = data . replace ( / ^ \s * \* / mg, '' )
142+
143+ this . #manifest = parseJSON ( data )
144+ return this
145+ }
146+
120147 get content ( ) {
121148 return this . #manifest
122149 }
@@ -125,58 +152,59 @@ class PackageJson {
125152 return this . #path
126153 }
127154
128- update ( content ) {
129- // validates both current manifest and content param
130- const invalidContent =
131- typeof this . #manifest !== 'object'
132- || typeof content !== 'object'
133- if ( invalidContent ) {
134- throw Object . assign (
135- new Error ( `Can't update invalid package.json data` ) ,
136- { code : 'EPACKAGEJSONUPDATE' }
137- )
155+ get filename ( ) {
156+ if ( this . path ) {
157+ return resolve ( this . path , 'package.json' )
138158 }
159+ return undefined
160+ }
139161
162+ update ( content ) {
163+ if ( ! this . content ) {
164+ throw new Error ( 'Can not update without existing data' )
165+ }
140166 for ( const step of knownSteps ) {
141- this . #manifest = step ( { content, originalContent : this . #manifest } )
167+ this . #manifest = step ( { content, originalContent : this . content } )
142168 }
143169
144170 // unknown properties will just be overwitten
145171 for ( const [ key , value ] of Object . entries ( content ) ) {
146172 if ( ! knownKeys . has ( key ) ) {
147- this . #manifest [ key ] = value
173+ this . content [ key ] = value
148174 }
149175 }
150176
151177 return this
152178 }
153179
154180 async save ( ) {
155- if ( this . #fromIndex ) {
181+ if ( ! this . #canSave ) {
156182 throw new Error ( 'No package.json to save to' )
157183 }
158184 const {
159185 [ Symbol . for ( 'indent' ) ] : indent ,
160186 [ Symbol . for ( 'newline' ) ] : newline ,
161- } = this . #manifest
187+ } = this . content
162188
163- const format = indent === undefined ? ' ' : indent
164- const eol = newline === undefined ? '\n' : newline
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
165194 const fileContent = `${
166- JSON . stringify ( this . #manifest , null , format )
195+ JSON . stringify ( this . content , null , format )
167196 } \n`
168197 . replace ( / \n / g, eol )
169198
170199 if ( fileContent . trim ( ) !== this . #readFileContent. trim ( ) ) {
171- return await writeFile ( this . # filename, fileContent )
200+ return await writeFile ( this . filename , fileContent )
172201 }
173202 }
174203
175204 async normalize ( opts = { } ) {
176205 if ( ! opts . steps ) {
177206 opts . steps = this . constructor . normalizeSteps
178207 }
179- await this . load ( )
180208 await normalize ( this , opts )
181209 return this
182210 }
@@ -185,29 +213,9 @@ class PackageJson {
185213 if ( ! opts . steps ) {
186214 opts . steps = this . constructor . prepareSteps
187215 }
188- await this . load ( true )
189216 await normalize ( this , opts )
190217 return this
191218 }
192219}
193220
194- // /**package { "name": "foo", "version": "1.2.3", ... } **/
195- function fromComment ( data ) {
196- data = data . split ( / ^ \/ \* \* p a c k a g e (?: \s | $ ) / m)
197-
198- if ( data . length < 2 ) {
199- throw new Error ( 'File has no package in comments' )
200- }
201- data = data [ 1 ]
202- data = data . split ( / \* \* \/ $ / m)
203-
204- if ( data . length < 2 ) {
205- throw new Error ( 'File has no package in comments' )
206- }
207- data = data [ 0 ]
208- data = data . replace ( / ^ \s * \* / mg, '' )
209-
210- return parseJSON ( data )
211- }
212-
213221module . exports = PackageJson
0 commit comments