(source, prefix, errors, requireImmutableLocator)
| 282 | } |
| 283 | |
| 284 | function validateGitHubSource(source, prefix, errors, requireImmutableLocator) { |
| 285 | if (!source || typeof source !== "object" || Array.isArray(source)) { |
| 286 | errors.push(`${prefix}: "source" must be an object`); |
| 287 | return; |
| 288 | } |
| 289 | |
| 290 | if (source.source !== "github") { |
| 291 | errors.push(`${prefix}: "source.source" must be "github"`); |
| 292 | } |
| 293 | |
| 294 | if (!isNonEmptyString(source.repo)) { |
| 295 | errors.push(`${prefix}: "source.repo" is required and must be a non-empty string`); |
| 296 | } else if (!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(source.repo)) { |
| 297 | errors.push(`${prefix}: "source.repo" must be in "owner/repo" format`); |
| 298 | } |
| 299 | |
| 300 | if (source.path !== undefined) { |
| 301 | validateRelativePath(source.path, prefix, errors); |
| 302 | } |
| 303 | |
| 304 | if (source.ref !== undefined) { |
| 305 | validateImmutableRef(source.ref, prefix, errors); |
| 306 | } |
| 307 | |
| 308 | if (source.sha !== undefined) { |
| 309 | validateCommitSha(source.sha, prefix, errors); |
| 310 | } |
| 311 | |
| 312 | if (requireImmutableLocator && source.ref === undefined && source.sha === undefined) { |
| 313 | errors.push(`${prefix}: one of "source.ref" or "source.sha" is required for public external plugin submissions`); |
| 314 | } |
| 315 | } |
| 316 | |
| 317 | export function validateExternalPlugin(plugin, index, options = {}) { |
| 318 | const policy = resolvePolicy(options.policy ?? options); |
no test coverage detected