* @brief Validates and executes a single project.batch op; returns the per-op result entry. */
| 5286 | * @brief Validates and executes a single project.batch op; returns the per-op result entry. |
| 5287 | */ |
| 5288 | static QJsonObject executeBatchOp(int index, const QJsonObject& op, bool dryRun, bool& success) |
| 5289 | { |
| 5290 | success = false; |
| 5291 | |
| 5292 | if (op.isEmpty()) { |
| 5293 | return buildBatchErrorEntry( |
| 5294 | index, |
| 5295 | QString(), |
| 5296 | API::ErrorCode::InvalidParam, |
| 5297 | QStringLiteral("ops[%1] must be an object of shape {command: string, params: object}") |
| 5298 | .arg(index), |
| 5299 | buildBatchSchemaHint()); |
| 5300 | } |
| 5301 | |
| 5302 | const auto command = op.value(QStringLiteral("command")).toString(); |
| 5303 | auto opParams = op.value(QStringLiteral("params")).toObject(); |
| 5304 | |
| 5305 | if (command.isEmpty()) { |
| 5306 | return buildBatchErrorEntry(index, |
| 5307 | QString(), |
| 5308 | API::ErrorCode::MissingParam, |
| 5309 | QStringLiteral("ops[%1].command is required (each op is " |
| 5310 | "{command: '<registered name>', params: {...}})") |
| 5311 | .arg(index), |
| 5312 | buildBatchSchemaHint()); |
| 5313 | } |
| 5314 | |
| 5315 | if (command == QStringLiteral("project.batch")) { |
| 5316 | return buildBatchErrorEntry(index, |
| 5317 | command, |
| 5318 | API::ErrorCode::InvalidParam, |
| 5319 | QStringLiteral("project.batch cannot be nested"), |
| 5320 | QJsonObject()); |
| 5321 | } |
| 5322 | |
| 5323 | if (dryRun) |
| 5324 | opParams.insert(QStringLiteral("dryRun"), true); |
| 5325 | |
| 5326 | const auto response = |
| 5327 | API::CommandRegistry::instance().execute(command, QString::number(index), opParams); |
| 5328 | |
| 5329 | QJsonObject entry; |
| 5330 | entry[QStringLiteral("index")] = index; |
| 5331 | entry[QStringLiteral("command")] = command; |
| 5332 | entry[QStringLiteral("success")] = response.success; |
| 5333 | if (response.success) { |
| 5334 | if (!response.result.isEmpty()) |
| 5335 | entry[QStringLiteral("result")] = response.result; |
| 5336 | |
| 5337 | success = true; |
| 5338 | } else { |
| 5339 | QJsonObject err; |
| 5340 | err[QStringLiteral("code")] = response.errorCode; |
| 5341 | err[QStringLiteral("message")] = response.errorMessage; |
| 5342 | if (!response.errorData.isEmpty()) |
| 5343 | err[QStringLiteral("data")] = response.errorData; |
| 5344 | |
| 5345 | entry[QStringLiteral("error")] = err; |
no test coverage detected