(operation, index, document, existingPathFragment)
| 304 | * @param {string} [existingPathFragment] - comes along with `document` |
| 305 | */ |
| 306 | export function validator(operation, index, document, existingPathFragment) { |
| 307 | if (typeof operation !== 'object' || operation === null || Array.isArray(operation)) { |
| 308 | throw new JsonPatchError('Operation is not an object', 'OPERATION_NOT_AN_OBJECT', index, operation, document); |
| 309 | } |
| 310 | else if (!objOps[operation.op]) { |
| 311 | throw new JsonPatchError('Operation `op` property is not one of operations defined in RFC-6902', 'OPERATION_OP_INVALID', index, operation, document); |
| 312 | } |
| 313 | else if (typeof operation.path !== 'string') { |
| 314 | throw new JsonPatchError('Operation `path` property is not a string', 'OPERATION_PATH_INVALID', index, operation, document); |
| 315 | } |
| 316 | else if (operation.path.indexOf('/') !== 0 && operation.path.length > 0) { |
| 317 | // paths that aren't empty string should start with "/" |
| 318 | throw new JsonPatchError('Operation `path` property must start with "/"', 'OPERATION_PATH_INVALID', index, operation, document); |
| 319 | } |
| 320 | else if ((operation.op === 'move' || operation.op === 'copy') && typeof operation.from !== 'string') { |
| 321 | throw new JsonPatchError('Operation `from` property is not present (applicable in `move` and `copy` operations)', 'OPERATION_FROM_REQUIRED', index, operation, document); |
| 322 | } |
| 323 | else if ((operation.op === 'add' || operation.op === 'replace' || operation.op === 'test') && operation.value === undefined) { |
| 324 | throw new JsonPatchError('Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)', 'OPERATION_VALUE_REQUIRED', index, operation, document); |
| 325 | } |
| 326 | else if ((operation.op === 'add' || operation.op === 'replace' || operation.op === 'test') && hasUndefined(operation.value)) { |
| 327 | throw new JsonPatchError('Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)', 'OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED', index, operation, document); |
| 328 | } |
| 329 | else if (document) { |
| 330 | if (operation.op == "add") { |
| 331 | var pathLen = operation.path.split("/").length; |
| 332 | var existingPathLen = existingPathFragment.split("/").length; |
| 333 | if (pathLen !== existingPathLen + 1 && pathLen !== existingPathLen) { |
| 334 | throw new JsonPatchError('Cannot perform an `add` operation at the desired path', 'OPERATION_PATH_CANNOT_ADD', index, operation, document); |
| 335 | } |
| 336 | } |
| 337 | else if (operation.op === 'replace' || operation.op === 'remove' || operation.op === '_get') { |
| 338 | if (operation.path !== existingPathFragment) { |
| 339 | throw new JsonPatchError('Cannot perform the operation at a path that does not exist', 'OPERATION_PATH_UNRESOLVABLE', index, operation, document); |
| 340 | } |
| 341 | } |
| 342 | else if (operation.op === 'move' || operation.op === 'copy') { |
| 343 | var existingValue = { op: "_get", path: operation.from, value: undefined }; |
| 344 | var error = validate([existingValue], document); |
| 345 | if (error && error.name === 'OPERATION_PATH_UNRESOLVABLE') { |
| 346 | throw new JsonPatchError('Cannot perform the operation from a path that does not exist', 'OPERATION_FROM_UNRESOLVABLE', index, operation, document); |
| 347 | } |
| 348 | } |
| 349 | } |
| 350 | } |
| 351 | /** |
| 352 | * Validates a sequence of operations. If `document` parameter is provided, the sequence is additionally validated against the object document. |
| 353 | * If error is encountered, returns a JsonPatchError object |
no test coverage detected