Skip to content

Commit 866d401

Browse files
committed
Added type checks for all package.json fields.
1 parent 0524d55 commit 866d401

File tree

1 file changed

+100
-4
lines changed

1 file changed

+100
-4
lines changed

src/service.js

+100-4
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,13 @@ extend( Repo.prototype, {
4040
validatePackageJson: function( package, version ) {
4141
var errors = [];
4242

43+
/** required fields **/
44+
45+
// TODO: verify URL-safe characters
4346
if ( !package.name ) {
4447
errors.push( "Missing required field: name." );
48+
} else if ( typeof package.name !== "string" ) {
49+
errors.push( "Invalid data type for name; must be a string." );
4550
} else if ( package.name.charAt( 0 ) === "_" || package.name.charAt( 0 ) === "." ) {
4651
errors.push( "Name cannot start with an underscore or dot." );
4752
// don't allow semantic version for plugin name
@@ -61,26 +66,117 @@ extend( Repo.prototype, {
6166

6267
if ( !package.title ) {
6368
errors.push( "Missing required field: title." );
69+
} else if ( typeof package.title !== "string" ) {
70+
errors.push( "Invalid data type for title; must be a string." );
6471
}
6572

6673
if ( !package.author ) {
6774
errors.push( "Missing required field: author." );
6875
} else if ( !package.author.name ) {
6976
errors.push( "Missing required field: author.name." );
77+
} else {
78+
if ( typeof package.author.name !== "string" ) {
79+
errors.push( "Invalid data type for author.name; must be a string." );
80+
}
81+
// TODO: verify email address format
82+
if ( "email" in package.author && typeof package.author.email !== "string" ) {
83+
errors.push( "Invalid data type for author.email; must be a string." );
84+
}
85+
// TODO: verify url format
86+
if ( "url" in package.author && typeof package.author.url !== "string" ) {
87+
errors.push( "Invalid data type for author.url; must be a string." );
88+
}
7089
}
7190

7291
if ( !package.licenses ) {
7392
errors.push( "Missing required field: licenses." );
7493
} else if ( !package.licenses.length ) {
7594
errors.push( "There must be at least one license." );
76-
} else if ( package.licenses.filter(function( license ) { return !license.url; }).length ) {
77-
errors.push( "Missing required field: license.url." );
95+
} else {
96+
package.licenses.forEach(function( license, i ) {
97+
// TDOO: verify url format
98+
if ( !license.url ) {
99+
errors.push( "Missing required field: licenses[" + i + "].url." );
100+
}
101+
});
78102
}
79103

80104
if ( !package.dependencies ) {
81105
errors.push( "Missing required field: dependencies." );
82-
} else if ( !package.dependencies.jquery ) {
83-
errors.push( "Missing required dependency: jquery." );
106+
} else {
107+
if ( !package.dependencies.jquery ) {
108+
errors.push( "Missing required dependency: jquery." );
109+
}
110+
Object.keys( package.dependencies ).forEach(function( dependency ) {
111+
// TODO: validate name
112+
// TODO: validate version
113+
});
114+
}
115+
116+
/** optional fields **/
117+
118+
if ( "description" in package && typeof package.description !== "string" ) {
119+
errors.push( "Invalid data type for description; must be a string." );
120+
}
121+
122+
if ( "keywords" in package ) {
123+
if ( !Array.isArray( package.keywords ) ) {
124+
errors.push( "Invalid data type for keywords; must be an array." );
125+
} else {
126+
package.keywords.forEach(function( keyword, i ) {
127+
// TODO: any character restrictions on keywords?
128+
if ( typeof keyword !== "string" ) {
129+
errors.push( "Invalid data type for keywords[" + i + "]; must be a string." );
130+
}
131+
});
132+
}
133+
}
134+
135+
// TODO: verify url format
136+
if ( "homepage" in package && typeof package.homepage !== "string" ) {
137+
errors.push( "Invalid data type for homepage; must be a string." );
138+
}
139+
140+
// TODO: verify url format
141+
if ( "docs" in package && typeof package.docs !== "string" ) {
142+
errors.push( "Invalid data type for docs; must be a string." );
143+
}
144+
145+
// TODO: verify url format
146+
if ( "demo" in package && typeof package.demo !== "string" ) {
147+
errors.push( "Invalid data type for demo; must be a string." );
148+
}
149+
150+
if ( "maintainers" in package ) {
151+
if ( !Array.isArray( package.maintainers ) ) {
152+
errors.push( "Invalid data type for maintainers; must be an array." );
153+
} else {
154+
package.maintainers.forEach(function( maintainer, i ) {
155+
if ( typeof maintainer.name !== "string" ) {
156+
errors.push( "Invalid data type for maintainers[" + i + "].name; must be a string." );
157+
}
158+
// TODO: verify email address format
159+
if ( "email" in maintainer && typeof maintainer.email !== "string" ) {
160+
errors.push( "Invalid data type for maintainers[" + i + "].email; must be a string." );
161+
}
162+
// TODO: verify url format
163+
if ( "url" in maintainer && typeof maintainer.url !== "string" ) {
164+
errors.push( "Invalid data type for maintainers[" + i + "].url; must be a string." );
165+
}
166+
});
167+
}
168+
}
169+
170+
if ( "files" in package ) {
171+
if ( !Array.isArray( package.files ) ) {
172+
errors.push( "Invalid data type for files; must be an array." );
173+
} else {
174+
package.files.forEach(function( file, i ) {
175+
if ( typeof file !== "string" ) {
176+
errors.push( "Invalid data type for files[" + i + "]; must be a string." );
177+
}
178+
});
179+
}
84180
}
85181

86182
return errors;

0 commit comments

Comments
 (0)