Initial SQL-only 1C adapter baseline
This commit is contained in:
@@ -0,0 +1,325 @@
|
||||
param(
|
||||
[string]$Server = $env:ONEC_SQL_SERVER,
|
||||
[string]$Database = $env:ONEC_SQL_DATABASE,
|
||||
[string]$User = $env:ONEC_SQL_USER,
|
||||
[string]$Password = $env:ONEC_SQL_PASSWORD,
|
||||
[string]$OutputDir = "reports\1c-sql\saved-state-object-report",
|
||||
[string]$BaseMetadataDir = "reports\1c-sql\upo\structured-metadata-all-kinds",
|
||||
[string]$ExtensionGuidIndex = "reports\1c-sql\upo\xml-guid-index-extensions.json",
|
||||
[string]$ExtensionManifestSummary = "reports\1c-sql\upo\extension-manifest-xml-part-summary.json",
|
||||
[string]$ConfigCASAllDir = "reports\1c-sql\upo\ConfigCAS-all",
|
||||
[string]$Python = "python",
|
||||
[string]$MarkdownOutput = "",
|
||||
[int]$MarkdownMaxDiffLines = 80,
|
||||
[switch]$SkipMarkdown
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
if (-not $Server) { throw "Server is required. Use -Server or ONEC_SQL_SERVER." }
|
||||
if (-not $Database) { throw "Database is required. Use -Database or ONEC_SQL_DATABASE." }
|
||||
if (-not $User) { throw "User is required. Use -User or ONEC_SQL_USER." }
|
||||
if (-not $Password) { throw "Password is required. Use -Password or ONEC_SQL_PASSWORD." }
|
||||
|
||||
$repoRoot = (Resolve-Path ".").ProviderPath
|
||||
$resolvedOutput = [System.IO.Path]::GetFullPath($OutputDir)
|
||||
New-Item -ItemType Directory -Force -Path $resolvedOutput | Out-Null
|
||||
|
||||
$comparisonPath = Join-Path $resolvedOutput "saved-state-object-comparison.json"
|
||||
$detailPath = Join-Path $resolvedOutput "saved-state-object-details.json"
|
||||
$checkPath = Join-Path $resolvedOutput "saved-state-object-report-check.json"
|
||||
$configSaveDir = Join-Path $resolvedOutput "ConfigSave"
|
||||
$configCASSaveDir = Join-Path $resolvedOutput "ConfigCASSave"
|
||||
$activeConfigDir = Join-Path $resolvedOutput "ActiveConfig"
|
||||
$activeConfigCASDir = Join-Path $resolvedOutput "ActiveConfigCAS"
|
||||
|
||||
foreach ($dir in @($configSaveDir, $configCASSaveDir, $activeConfigDir, $activeConfigCASDir)) {
|
||||
New-Item -ItemType Directory -Force -Path $dir | Out-Null
|
||||
}
|
||||
|
||||
function Invoke-Step {
|
||||
param(
|
||||
[string]$Name,
|
||||
[scriptblock]$Script
|
||||
)
|
||||
$started = Get-Date
|
||||
& $Script
|
||||
[pscustomobject]@{
|
||||
name = $Name
|
||||
started_at = $started.ToString("o")
|
||||
finished_at = (Get-Date).ToString("o")
|
||||
passed = $true
|
||||
}
|
||||
}
|
||||
|
||||
function Read-JsonFile {
|
||||
param([string]$Path)
|
||||
return Get-Content -LiteralPath $Path -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
}
|
||||
|
||||
function Export-TableFiles {
|
||||
param(
|
||||
[string]$Table,
|
||||
[string]$TargetDir,
|
||||
[string[]]$FileName
|
||||
)
|
||||
$args = @(
|
||||
"-NoProfile", "-ExecutionPolicy", "Bypass",
|
||||
"-File", "scripts\export_1c_sql_files.ps1",
|
||||
"-Server", $Server,
|
||||
"-Database", $Database,
|
||||
"-User", $User,
|
||||
"-Password", $Password,
|
||||
"-Table", $Table,
|
||||
"-OutputPath", $TargetDir
|
||||
)
|
||||
[object[]]$normalizedFileName = @($FileName)
|
||||
if (($normalizedFileName | Measure-Object).Count -gt 0) {
|
||||
$args += "-FileName"
|
||||
$args += $normalizedFileName
|
||||
}
|
||||
$json = & powershell @args
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Export failed for $Table."
|
||||
}
|
||||
return ($json | Out-String | ConvertFrom-Json)
|
||||
}
|
||||
|
||||
function Get-JsonProperty {
|
||||
param(
|
||||
[object]$Object,
|
||||
[string]$Name,
|
||||
[object]$Default = $null
|
||||
)
|
||||
if ($null -eq $Object) { return $Default }
|
||||
if ($Object.PSObject.Properties.Name -contains $Name) {
|
||||
return $Object.$Name
|
||||
}
|
||||
return $Default
|
||||
}
|
||||
|
||||
function Join-LimitedValues {
|
||||
param(
|
||||
[object[]]$Values,
|
||||
[int]$Limit = 12
|
||||
)
|
||||
$items = @($Values | Where-Object { $null -ne $_ -and [string]$_ -ne "" } | Select-Object -First $Limit)
|
||||
return ,$items
|
||||
}
|
||||
|
||||
function New-AgentSummary {
|
||||
param(
|
||||
[object]$Comparison,
|
||||
[object]$Detail
|
||||
)
|
||||
$detailByName = @{}
|
||||
foreach ($item in @($Detail.object_details)) {
|
||||
$fullName = [string](Get-JsonProperty -Object $item -Name "full_name" -Default "")
|
||||
if ($fullName) { $detailByName[$fullName] = $item }
|
||||
}
|
||||
|
||||
$objects = @()
|
||||
foreach ($change in @($Comparison.object_changes)) {
|
||||
$fullName = [string](Get-JsonProperty -Object $change -Name "full_name" -Default (Get-JsonProperty -Object $change -Name "name" -Default ""))
|
||||
$item = $null
|
||||
if ($fullName -and $detailByName.ContainsKey($fullName)) {
|
||||
$item = $detailByName[$fullName]
|
||||
}
|
||||
|
||||
$parts = @()
|
||||
$addedTerms = @()
|
||||
$removedTerms = @()
|
||||
$textDiffParts = 0
|
||||
$activeMissingParts = 0
|
||||
foreach ($part in @((Get-JsonProperty -Object $item -Name "details" -Default @()))) {
|
||||
$payload = Get-JsonProperty -Object $part -Name "payload" -Default $null
|
||||
$diff = Get-JsonProperty -Object $payload -Name "text_diff" -Default $null
|
||||
$semanticHints = Get-JsonProperty -Object $payload -Name "semantic_hints" -Default $null
|
||||
$activeExists = Get-JsonProperty -Object $part -Name "active_exists" -Default $null
|
||||
if ($activeExists -eq $false) { $activeMissingParts += 1 }
|
||||
if ($null -ne $diff) {
|
||||
$textDiffParts += 1
|
||||
$addedTerms += @(Get-JsonProperty -Object $semanticHints -Name "added_terms" -Default @())
|
||||
$removedTerms += @(Get-JsonProperty -Object $semanticHints -Name "removed_terms" -Default @())
|
||||
}
|
||||
$parts += [pscustomobject]@{
|
||||
file_name = Get-JsonProperty -Object $part -Name "file_name" -Default $null
|
||||
payload_role = Get-JsonProperty -Object $part -Name "payload_role" -Default $null
|
||||
saved_table = Get-JsonProperty -Object $part -Name "saved_table" -Default $null
|
||||
active_table = Get-JsonProperty -Object $part -Name "active_table" -Default $null
|
||||
active_exists = $activeExists
|
||||
text_comparable = Get-JsonProperty -Object $payload -Name "text_comparable" -Default $null
|
||||
summary = Get-JsonProperty -Object $payload -Name "summary" -Default $null
|
||||
delta_chars = Get-JsonProperty -Object $diff -Name "delta_chars" -Default $null
|
||||
}
|
||||
}
|
||||
|
||||
$objects += [pscustomobject]@{
|
||||
full_name = $fullName
|
||||
layer = Get-JsonProperty -Object $change -Name "layer" -Default $null
|
||||
extension = Get-JsonProperty -Object $change -Name "extension" -Default $null
|
||||
kind = Get-JsonProperty -Object $change -Name "kind" -Default $null
|
||||
kind_ru = Get-JsonProperty -Object $change -Name "kind_ru" -Default $null
|
||||
name = Get-JsonProperty -Object $change -Name "name" -Default $null
|
||||
synonym = Get-JsonProperty -Object $change -Name "synonym" -Default $null
|
||||
change_state = Get-JsonProperty -Object $change -Name "change_state" -Default $null
|
||||
parts_count = ($parts | Measure-Object).Count
|
||||
text_diff_parts = $textDiffParts
|
||||
active_missing_parts = $activeMissingParts
|
||||
added_terms = Join-LimitedValues -Values ($addedTerms | Sort-Object -Unique) -Limit 12
|
||||
removed_terms = Join-LimitedValues -Values ($removedTerms | Sort-Object -Unique) -Limit 12
|
||||
parts = $parts
|
||||
}
|
||||
}
|
||||
|
||||
$systemChanges = @()
|
||||
foreach ($change in @($Comparison.system_changes)) {
|
||||
$systemChanges += [pscustomobject]@{
|
||||
name = Get-JsonProperty -Object $change -Name "name" -Default $null
|
||||
layer = Get-JsonProperty -Object $change -Name "layer" -Default $null
|
||||
extension = Get-JsonProperty -Object $change -Name "extension" -Default $null
|
||||
}
|
||||
}
|
||||
|
||||
return [pscustomobject]@{
|
||||
purpose = "Compact agent-facing summary of saved-but-not-applied changes in 1C terms."
|
||||
default_next_action = "Inspect object details before generating or applying any code changes."
|
||||
object_changes = $objects
|
||||
system_changes = $systemChanges
|
||||
object_names = @($objects | ForEach-Object { $_.full_name })
|
||||
system_change_names = @($systemChanges | ForEach-Object { $_.name })
|
||||
}
|
||||
}
|
||||
|
||||
$steps = @()
|
||||
|
||||
$steps += Invoke-Step "compare_saved_state_objects" {
|
||||
& powershell -NoProfile -ExecutionPolicy Bypass -File scripts\compare_1c_saved_state_objects.ps1 `
|
||||
-Server $Server `
|
||||
-Database $Database `
|
||||
-User $User `
|
||||
-Password $Password `
|
||||
-BaseMetadataDir $BaseMetadataDir `
|
||||
-ExtensionGuidIndex $ExtensionGuidIndex `
|
||||
-Output $comparisonPath | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) { throw "Saved-state object comparison failed." }
|
||||
}
|
||||
|
||||
$comparison = Read-JsonFile $comparisonPath
|
||||
|
||||
$steps += Invoke-Step "export_config_save" {
|
||||
$null = Export-TableFiles -Table "ConfigSave" -TargetDir $configSaveDir
|
||||
}
|
||||
|
||||
$steps += Invoke-Step "export_config_cas_save" {
|
||||
$null = Export-TableFiles -Table "ConfigCASSave" -TargetDir $configCASSaveDir
|
||||
}
|
||||
|
||||
$activeConfigFiles = @(
|
||||
$comparison.object_changes |
|
||||
ForEach-Object { $_.storage } |
|
||||
Where-Object { $_.active_table -eq "Config" } |
|
||||
ForEach-Object { [string]$_.file_name } |
|
||||
Sort-Object -Unique
|
||||
)
|
||||
$activeConfigCASFiles = @(
|
||||
$comparison.object_changes |
|
||||
ForEach-Object { $_.storage } |
|
||||
Where-Object { $_.active_table -eq "ConfigCAS" -and $_.active_exists } |
|
||||
ForEach-Object { [string]$_.file_name } |
|
||||
Sort-Object -Unique
|
||||
)
|
||||
|
||||
$steps += Invoke-Step "export_active_config_payloads" {
|
||||
if (($activeConfigFiles | Measure-Object).Count -gt 0) {
|
||||
$null = Export-TableFiles -Table "Config" -TargetDir $activeConfigDir -FileName $activeConfigFiles
|
||||
}
|
||||
}
|
||||
|
||||
$steps += Invoke-Step "export_active_config_cas_payloads" {
|
||||
if (($activeConfigCASFiles | Measure-Object).Count -gt 0) {
|
||||
$null = Export-TableFiles -Table "ConfigCAS" -TargetDir $activeConfigCASDir -FileName $activeConfigCASFiles
|
||||
}
|
||||
}
|
||||
|
||||
$steps += Invoke-Step "analyze_saved_state_object_details" {
|
||||
& $Python scripts\analyze_1c_saved_state_object_details.py `
|
||||
--comparison $comparisonPath `
|
||||
--config-save-dir $configSaveDir `
|
||||
--config-dir $activeConfigDir `
|
||||
--config-cas-save-dir $configCASSaveDir `
|
||||
--config-cas-dir $activeConfigCASDir `
|
||||
--extension-manifest-summary $ExtensionManifestSummary `
|
||||
--config-cas-all-dir $ConfigCASAllDir `
|
||||
--output $detailPath | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) { throw "Saved-state detail analysis failed." }
|
||||
}
|
||||
|
||||
$detail = Read-JsonFile $detailPath
|
||||
$agentSummary = New-AgentSummary -Comparison $comparison -Detail $detail
|
||||
|
||||
$reportPath = Join-Path $resolvedOutput "saved-state-object-report.json"
|
||||
if (-not $MarkdownOutput) {
|
||||
$MarkdownOutput = Join-Path $resolvedOutput "saved-state-object-report.md"
|
||||
} else {
|
||||
$MarkdownOutput = [System.IO.Path]::GetFullPath($MarkdownOutput)
|
||||
}
|
||||
|
||||
$result = [pscustomobject]@{
|
||||
schema = "onec_saved_state_object_report.v1"
|
||||
server = $Server
|
||||
database = $Database
|
||||
report = $reportPath
|
||||
markdown = if ($SkipMarkdown) { $null } else { $MarkdownOutput }
|
||||
check = $checkPath
|
||||
output_dir = $resolvedOutput
|
||||
comparison = $comparisonPath
|
||||
detail = $detailPath
|
||||
agent_summary = $agentSummary
|
||||
payload_dirs = [pscustomobject]@{
|
||||
config_save = $configSaveDir
|
||||
config_cas_save = $configCASSaveDir
|
||||
active_config = $activeConfigDir
|
||||
active_config_cas = $activeConfigCASDir
|
||||
active_config_cas_all = $ConfigCASAllDir
|
||||
}
|
||||
counts = [pscustomobject]@{
|
||||
object_changes = $comparison.counts.object_changes
|
||||
system_changes = $comparison.counts.system_changes
|
||||
detail_objects = $detail.counts.objects
|
||||
detail_parts = $detail.counts.details
|
||||
}
|
||||
steps = $steps
|
||||
safety = [pscustomobject]@{
|
||||
read_only = $true
|
||||
sql_write_performed = $false
|
||||
public_terms_are_1c_objects = $true
|
||||
secrets_in_report = $false
|
||||
}
|
||||
}
|
||||
|
||||
$result | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $reportPath -Encoding UTF8
|
||||
|
||||
if (-not $SkipMarkdown) {
|
||||
$steps += Invoke-Step "render_saved_state_markdown" {
|
||||
& $Python scripts\render_1c_saved_state_object_report_markdown.py `
|
||||
--report $reportPath `
|
||||
--output $MarkdownOutput `
|
||||
--max-diff-lines $MarkdownMaxDiffLines | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) { throw "Saved-state Markdown rendering failed." }
|
||||
}
|
||||
$result.steps = $steps
|
||||
$result | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $reportPath -Encoding UTF8
|
||||
}
|
||||
|
||||
$steps += Invoke-Step "check_saved_state_report" {
|
||||
& $Python scripts\check_1c_saved_state_object_report.py `
|
||||
--report $reportPath `
|
||||
--output $checkPath | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) { throw "Saved-state report check failed." }
|
||||
}
|
||||
$result.steps = $steps
|
||||
$result | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $reportPath -Encoding UTF8
|
||||
|
||||
$result | ConvertTo-Json -Depth 12
|
||||
Reference in New Issue
Block a user