@@ -40,8 +40,13 @@ extend( Repo.prototype, {
40
40
validatePackageJson : function ( package , version ) {
41
41
var errors = [ ] ;
42
42
43
+ /** required fields **/
44
+
45
+ // TODO: verify URL-safe characters
43
46
if ( ! package . name ) {
44
47
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." ) ;
45
50
} else if ( package . name . charAt ( 0 ) === "_" || package . name . charAt ( 0 ) === "." ) {
46
51
errors . push ( "Name cannot start with an underscore or dot." ) ;
47
52
// don't allow semantic version for plugin name
@@ -61,26 +66,117 @@ extend( Repo.prototype, {
61
66
62
67
if ( ! package . title ) {
63
68
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." ) ;
64
71
}
65
72
66
73
if ( ! package . author ) {
67
74
errors . push ( "Missing required field: author." ) ;
68
75
} else if ( ! package . author . name ) {
69
76
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
+ }
70
89
}
71
90
72
91
if ( ! package . licenses ) {
73
92
errors . push ( "Missing required field: licenses." ) ;
74
93
} else if ( ! package . licenses . length ) {
75
94
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
+ } ) ;
78
102
}
79
103
80
104
if ( ! package . dependencies ) {
81
105
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
+ }
84
180
}
85
181
86
182
return errors ;
0 commit comments