mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 22:34:56 +00:00
336 lines
8.7 KiB
Lua
336 lines
8.7 KiB
Lua
-- package_validator/seed/scripts/db/operations.lua
|
|
-- DBAL operations for Package validation results
|
|
-- @module package_validator.db.operations
|
|
|
|
local M = {}
|
|
local json = require('json')
|
|
|
|
---------------------------------------------------------------------------
|
|
-- VALIDATION RUN OPERATIONS
|
|
---------------------------------------------------------------------------
|
|
|
|
---@class ValidationRunParams
|
|
---@field tenantId string
|
|
---@field packageName string
|
|
---@field packageVersion string|nil
|
|
---@field status string (pending, running, completed, failed)
|
|
---@field results table|nil Validation results
|
|
|
|
---Create validation run
|
|
---@param dbal table DBAL client instance
|
|
---@param params ValidationRunParams
|
|
---@return table Created run
|
|
function M.createRun(dbal, params)
|
|
return dbal:create('ValidationRun', {
|
|
tenantId = params.tenantId,
|
|
packageName = params.packageName,
|
|
packageVersion = params.packageVersion,
|
|
status = params.status or 'pending',
|
|
results = params.results and json.encode(params.results) or nil,
|
|
startedAt = os.time() * 1000,
|
|
})
|
|
end
|
|
|
|
---Get validation run by ID
|
|
---@param dbal table
|
|
---@param runId string
|
|
---@return table|nil Run
|
|
function M.getRun(dbal, runId)
|
|
local run = dbal:read('ValidationRun', runId)
|
|
if run and run.results then
|
|
run.results = json.decode(run.results)
|
|
end
|
|
return run
|
|
end
|
|
|
|
---Update run status
|
|
---@param dbal table
|
|
---@param runId string
|
|
---@param status string
|
|
---@param results table|nil
|
|
function M.updateRunStatus(dbal, runId, status, results)
|
|
local updates = {
|
|
status = status,
|
|
}
|
|
|
|
if results then
|
|
updates.results = json.encode(results)
|
|
end
|
|
|
|
if status == 'completed' or status == 'failed' then
|
|
updates.completedAt = os.time() * 1000
|
|
end
|
|
|
|
return dbal:update('ValidationRun', runId, updates)
|
|
end
|
|
|
|
---List runs for package
|
|
---@param dbal table
|
|
---@param tenantId string
|
|
---@param packageName string
|
|
---@param take number|nil
|
|
---@return table[] Runs
|
|
function M.listRuns(dbal, tenantId, packageName, take)
|
|
local result = dbal:list('ValidationRun', {
|
|
where = { tenantId = tenantId, packageName = packageName },
|
|
orderBy = { startedAt = 'desc' },
|
|
take = take or 20,
|
|
})
|
|
|
|
return result.items or {}
|
|
end
|
|
|
|
---Get latest run for package
|
|
---@param dbal table
|
|
---@param tenantId string
|
|
---@param packageName string
|
|
---@return table|nil Latest run
|
|
function M.getLatestRun(dbal, tenantId, packageName)
|
|
local runs = M.listRuns(dbal, tenantId, packageName, 1)
|
|
if #runs > 0 then
|
|
local run = runs[1]
|
|
if run.results then
|
|
run.results = json.decode(run.results)
|
|
end
|
|
return run
|
|
end
|
|
return nil
|
|
end
|
|
|
|
---------------------------------------------------------------------------
|
|
-- VALIDATION ISSUE OPERATIONS
|
|
---------------------------------------------------------------------------
|
|
|
|
---@class ValidationIssue
|
|
---@field runId string
|
|
---@field severity string (error, warning, info)
|
|
---@field code string Issue code
|
|
---@field message string
|
|
---@field file string|nil
|
|
---@field line number|nil
|
|
---@field suggestion string|nil
|
|
|
|
---Add validation issue
|
|
---@param dbal table
|
|
---@param issue ValidationIssue
|
|
---@return table Created issue
|
|
function M.addIssue(dbal, issue)
|
|
return dbal:create('ValidationIssue', {
|
|
runId = issue.runId,
|
|
severity = issue.severity,
|
|
code = issue.code,
|
|
message = issue.message,
|
|
file = issue.file,
|
|
line = issue.line,
|
|
suggestion = issue.suggestion,
|
|
createdAt = os.time() * 1000,
|
|
})
|
|
end
|
|
|
|
---Add multiple issues
|
|
---@param dbal table
|
|
---@param runId string
|
|
---@param issues table[] Array of issues
|
|
function M.addIssues(dbal, runId, issues)
|
|
for _, issue in ipairs(issues) do
|
|
issue.runId = runId
|
|
M.addIssue(dbal, issue)
|
|
end
|
|
end
|
|
|
|
---Get issues for run
|
|
---@param dbal table
|
|
---@param runId string
|
|
---@param severity string|nil Filter by severity
|
|
---@return table[] Issues
|
|
function M.getIssues(dbal, runId, severity)
|
|
local where = { runId = runId }
|
|
|
|
local result = dbal:list('ValidationIssue', {
|
|
where = where,
|
|
orderBy = { severity = 'asc' },
|
|
take = 500,
|
|
})
|
|
|
|
local issues = result.items or {}
|
|
|
|
if severity then
|
|
local filtered = {}
|
|
for _, issue in ipairs(issues) do
|
|
if issue.severity == severity then
|
|
table.insert(filtered, issue)
|
|
end
|
|
end
|
|
issues = filtered
|
|
end
|
|
|
|
return issues
|
|
end
|
|
|
|
---Count issues by severity
|
|
---@param dbal table
|
|
---@param runId string
|
|
---@return table Counts by severity
|
|
function M.countIssues(dbal, runId)
|
|
local issues = M.getIssues(dbal, runId)
|
|
|
|
local counts = {
|
|
error = 0,
|
|
warning = 0,
|
|
info = 0,
|
|
total = #issues,
|
|
}
|
|
|
|
for _, issue in ipairs(issues) do
|
|
local sev = issue.severity
|
|
if counts[sev] then
|
|
counts[sev] = counts[sev] + 1
|
|
end
|
|
end
|
|
|
|
return counts
|
|
end
|
|
|
|
---------------------------------------------------------------------------
|
|
-- VALIDATION RULE OPERATIONS
|
|
---------------------------------------------------------------------------
|
|
|
|
---@class ValidationRuleParams
|
|
---@field tenantId string
|
|
---@field name string
|
|
---@field code string Unique rule code
|
|
---@field severity string
|
|
---@field description string
|
|
---@field check string Lua function body
|
|
---@field enabled boolean|nil
|
|
|
|
---Create validation rule
|
|
---@param dbal table
|
|
---@param params ValidationRuleParams
|
|
---@return table Created rule
|
|
function M.createRule(dbal, params)
|
|
return dbal:create('ValidationRule', {
|
|
tenantId = params.tenantId,
|
|
name = params.name,
|
|
code = params.code,
|
|
severity = params.severity,
|
|
description = params.description,
|
|
check = params.check,
|
|
enabled = params.enabled ~= false,
|
|
createdAt = os.time() * 1000,
|
|
updatedAt = os.time() * 1000,
|
|
})
|
|
end
|
|
|
|
---Get rule by code
|
|
---@param dbal table
|
|
---@param tenantId string
|
|
---@param code string
|
|
---@return table|nil Rule
|
|
function M.getRule(dbal, tenantId, code)
|
|
return dbal:findFirst('ValidationRule', {
|
|
where = { tenantId = tenantId, code = code },
|
|
})
|
|
end
|
|
|
|
---List enabled rules
|
|
---@param dbal table
|
|
---@param tenantId string
|
|
---@return table[] Rules
|
|
function M.listEnabledRules(dbal, tenantId)
|
|
local result = dbal:list('ValidationRule', {
|
|
where = { tenantId = tenantId, enabled = true },
|
|
orderBy = { code = 'asc' },
|
|
take = 100,
|
|
})
|
|
|
|
return result.items or {}
|
|
end
|
|
|
|
---Update rule
|
|
---@param dbal table
|
|
---@param tenantId string
|
|
---@param code string
|
|
---@param updates table
|
|
function M.updateRule(dbal, tenantId, code, updates)
|
|
local rule = M.getRule(dbal, tenantId, code)
|
|
if rule then
|
|
updates.updatedAt = os.time() * 1000
|
|
return dbal:update('ValidationRule', rule.id, updates)
|
|
end
|
|
return nil
|
|
end
|
|
|
|
---Toggle rule enabled status
|
|
---@param dbal table
|
|
---@param tenantId string
|
|
---@param code string
|
|
---@param enabled boolean
|
|
function M.setRuleEnabled(dbal, tenantId, code, enabled)
|
|
return M.updateRule(dbal, tenantId, code, { enabled = enabled })
|
|
end
|
|
|
|
---------------------------------------------------------------------------
|
|
-- PACKAGE REGISTRY OPERATIONS
|
|
---------------------------------------------------------------------------
|
|
|
|
---Get package validation summary
|
|
---@param dbal table
|
|
---@param tenantId string
|
|
---@param packageName string
|
|
---@return table Summary
|
|
function M.getPackageSummary(dbal, tenantId, packageName)
|
|
local latestRun = M.getLatestRun(dbal, tenantId, packageName)
|
|
|
|
if not latestRun then
|
|
return {
|
|
packageName = packageName,
|
|
status = 'never_validated',
|
|
lastValidated = nil,
|
|
issueCounts = nil,
|
|
}
|
|
end
|
|
|
|
local counts = M.countIssues(dbal, latestRun.id)
|
|
|
|
return {
|
|
packageName = packageName,
|
|
status = latestRun.status,
|
|
lastValidated = latestRun.completedAt or latestRun.startedAt,
|
|
issueCounts = counts,
|
|
hasErrors = counts.error > 0,
|
|
}
|
|
end
|
|
|
|
---Get all packages validation status
|
|
---@param dbal table
|
|
---@param tenantId string
|
|
---@return table[] Package summaries
|
|
function M.getAllPackageStatus(dbal, tenantId)
|
|
-- Get unique package names from runs
|
|
local result = dbal:list('ValidationRun', {
|
|
where = { tenantId = tenantId },
|
|
orderBy = { packageName = 'asc' },
|
|
take = 10000,
|
|
})
|
|
|
|
local packageNames = {}
|
|
local seen = {}
|
|
|
|
for _, run in ipairs(result.items or {}) do
|
|
if not seen[run.packageName] then
|
|
seen[run.packageName] = true
|
|
table.insert(packageNames, run.packageName)
|
|
end
|
|
end
|
|
|
|
local summaries = {}
|
|
for _, name in ipairs(packageNames) do
|
|
table.insert(summaries, M.getPackageSummary(dbal, tenantId, name))
|
|
end
|
|
|
|
return summaries
|
|
end
|
|
|
|
return M
|