mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-18 01:00:24 +03:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8cb7868145 |
@@ -1,32 +0,0 @@
|
||||
{
|
||||
"name": "cc-1c-skills",
|
||||
"interface": {
|
||||
"displayName": "1C Skills"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "1c-skills",
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/Nikolay-Shirokov/cc-1c-skills.git",
|
||||
"ref": "port-codex"
|
||||
},
|
||||
"policy": {
|
||||
"installation": "AVAILABLE"
|
||||
},
|
||||
"category": "Development"
|
||||
},
|
||||
{
|
||||
"name": "1c-skills-py",
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/Nikolay-Shirokov/cc-1c-skills.git",
|
||||
"ref": "port-codex-py"
|
||||
},
|
||||
"policy": {
|
||||
"installation": "AVAILABLE"
|
||||
},
|
||||
"category": "Development"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/claude-code-marketplace-manifest.json",
|
||||
"name": "cc-1c-skills",
|
||||
"description": "Маркетплейс навыков для разработки на платформе 1С:Предприятие",
|
||||
"owner": {
|
||||
"name": "Nikolay Shirokov"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "1c-skills",
|
||||
"source": "./",
|
||||
"description": "[PowerShell] Навыки для разработки на 1С:Предприятие 8.3 — абстракции над XML-форматами и CLI конфигуратора, плюс глаза и руки для тестирования через веб-клиент."
|
||||
},
|
||||
{
|
||||
"name": "1c-skills-py",
|
||||
"source": {
|
||||
"source": "github",
|
||||
"repo": "Nikolay-Shirokov/cc-1c-skills",
|
||||
"ref": "port-claude-code-py"
|
||||
},
|
||||
"description": "[Python] То же — для Linux/Mac или когда PowerShell недоступен."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
||||
"name": "1c-skills",
|
||||
"version": "2026.8.17+113dc9e",
|
||||
"description": "[PowerShell] Навыки для разработки на 1С:Предприятие 8.3 — абстракции над XML-форматами и CLI конфигуратора, плюс глаза и руки для тестирования через веб-клиент.",
|
||||
"author": {
|
||||
"name": "Nikolay Shirokov"
|
||||
@@ -27,5 +27,10 @@
|
||||
"testing",
|
||||
"test-automation"
|
||||
],
|
||||
"skills": "./.claude/skills/"
|
||||
"skills": "./.codex/skills/",
|
||||
"interface": {
|
||||
"displayName": "1C Skills (PowerShell)",
|
||||
"shortDescription": "PowerShell runtime (Windows-first)",
|
||||
"category": "Development"
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ allowed-tools:
|
||||
| `NoValidate` | Пропустить авто-валидацию |
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-edit.ps1" -ConfigPath '<path>' -Operation modify-property -Value 'Version=1.0.0.1'
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/cf-edit/scripts/cf-edit.ps1" -ConfigPath '<path>' -Operation modify-property -Value 'Version=1.0.0.1'
|
||||
```
|
||||
|
||||
## Операции
|
||||
@@ -23,7 +23,7 @@ allowed-tools:
|
||||
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-info.ps1" -ConfigPath "<путь>"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/cf-info/scripts/cf-info.ps1" -ConfigPath "<путь>"
|
||||
```
|
||||
|
||||
## Три режима
|
||||
@@ -39,7 +39,7 @@ allowed-tools:
|
||||
не будет.
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-init.ps1" -Name "МояКонфигурация"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/cf-init/scripts/cf-init.ps1" -Name "МояКонфигурация"
|
||||
```
|
||||
|
||||
## Примеры
|
||||
@@ -24,6 +24,6 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-validate.ps1" -ConfigPath "upload/cfempty"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-validate.ps1" -ConfigPath "upload/cfempty/Configuration.xml"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/cf-validate/scripts/cf-validate.ps1" -ConfigPath "upload/cfempty"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/cf-validate/scripts/cf-validate.ps1" -ConfigPath "upload/cfempty/Configuration.xml"
|
||||
```
|
||||
@@ -31,6 +31,7 @@ allowed-tools:
|
||||
| `ExtensionPath` | Путь к каталогу расширения (обязат.) |
|
||||
| `ConfigPath` | Путь к конфигурации-источнику (обязат.) |
|
||||
| `Object` | Что заимствовать (обязат.), batch через `;;` |
|
||||
| `Module` | Создать пустые модули объекта: `ObjectModule`, `ManagerModule`, `RecordSetModule`, `ValueManagerModule` (через запятую) или `None`. У типов с единственным модулем (`CommonModule`, `HTTPService`, `WebService`) он создаётся и без параметра |
|
||||
| `BorrowMainAttribute` | Заимствовать основной реквизит формы. Без параметра — не заимствует. `Form` — реквизиты, используемые на форме. `All` — все реквизиты объекта. Требует форму в -Object |
|
||||
|
||||
## Формат -Object
|
||||
@@ -65,12 +66,12 @@ allowed-tools:
|
||||
2. `/meta-edit` — добавить новый реквизит в объект расширения
|
||||
3. `/form-edit` — вывести реквизит на заимствованную форму
|
||||
|
||||
**Защита существующих данных**: если зависимый объект уже заимствован с содержимым (реквизитами, формами) — скрипт не перезаписывает его, а добавляет только недостающее.
|
||||
**Защита существующих данных**: уже заимствованный объект не перезаписывается — добавляется только недостающее. Повторный вызов безопасен: собственные реквизиты расширения, заимствованные подобъекты и код в модулях сохраняются.
|
||||
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-borrow.ps1" -ExtensionPath src\cfe\extname -ConfigPath src\cf -Object "Catalog.Контрагенты"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/cfe-borrow/scripts/cfe-borrow.ps1" -ExtensionPath src\cfe\extname -ConfigPath src\cf -Object "Catalog.Контрагенты"
|
||||
```
|
||||
|
||||
## Примеры
|
||||
@@ -79,6 +80,12 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-borrow.ps1" -Ex
|
||||
# Заимствовать один объект
|
||||
... -ExtensionPath src\cfe\extname -ConfigPath src\cf -Object "Catalog.Контрагенты"
|
||||
|
||||
# Заимствовать справочник вместе с модулями объекта и менеджера
|
||||
... -ExtensionPath src\cfe\extname -ConfigPath src\cf -Object "Catalog.Контрагенты" -Module ObjectModule,ManagerModule
|
||||
|
||||
# Общий модуль без файла модуля
|
||||
... -ExtensionPath src\cfe\extname -ConfigPath src\cf -Object "CommonModule.РаботаСФайлами" -Module None
|
||||
|
||||
# Заимствовать форму (автоматически заимствует родительский объект)
|
||||
... -ExtensionPath src\cfe\extname -ConfigPath src\cf -Object "Catalog.Контрагенты.Form.ФормаЭлемента"
|
||||
|
||||
+176
-16
@@ -1,10 +1,11 @@
|
||||
# cfe-borrow v1.31 — Borrow objects from configuration into extension (CFE)
|
||||
# cfe-borrow v1.32 — Borrow objects from configuration into extension (CFE)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)][string]$ExtensionPath,
|
||||
[Parameter(Mandatory)][string]$ConfigPath,
|
||||
[Parameter(Mandatory)][string]$Object,
|
||||
[string]$BorrowMainAttribute
|
||||
[string]$BorrowMainAttribute,
|
||||
[string]$Module
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
@@ -261,6 +262,32 @@ $childTypeDirMap = @{
|
||||
"CommonAttribute"="CommonAttributes"; "Style"="Styles"; "Bot"="Bots"; "Language"="Languages"
|
||||
}
|
||||
|
||||
# --- 4a. Модули заимствованных объектов ---
|
||||
# Порядок внутри значения — порядок выгрузки Конфигуратора: сначала «объектный» модуль
|
||||
# (ObjectModule / RecordSetModule / ValueManagerModule), затем ManagerModule.
|
||||
$script:moduleKindsByType = @{
|
||||
"CommonModule"=@("Module"); "HTTPService"=@("Module"); "WebService"=@("Module")
|
||||
"Catalog"=@("ObjectModule","ManagerModule"); "Document"=@("ObjectModule","ManagerModule")
|
||||
"Report"=@("ObjectModule","ManagerModule"); "DataProcessor"=@("ObjectModule","ManagerModule")
|
||||
"ExchangePlan"=@("ObjectModule","ManagerModule")
|
||||
"ChartOfCharacteristicTypes"=@("ObjectModule","ManagerModule")
|
||||
"ChartOfAccounts"=@("ObjectModule","ManagerModule")
|
||||
"ChartOfCalculationTypes"=@("ObjectModule","ManagerModule")
|
||||
"BusinessProcess"=@("ObjectModule","ManagerModule"); "Task"=@("ObjectModule","ManagerModule")
|
||||
"InformationRegister"=@("RecordSetModule","ManagerModule")
|
||||
"AccumulationRegister"=@("RecordSetModule","ManagerModule")
|
||||
"AccountingRegister"=@("RecordSetModule","ManagerModule")
|
||||
"CalculationRegister"=@("RecordSetModule","ManagerModule")
|
||||
"Sequence"=@("RecordSetModule","ManagerModule")
|
||||
"Constant"=@("ValueManagerModule","ManagerModule")
|
||||
"Enum"=@("ManagerModule"); "DocumentJournal"=@("ManagerModule")
|
||||
"FilterCriterion"=@("ManagerModule")
|
||||
}
|
||||
# Типы с ЕДИНСТВЕННЫМ модулем: ради него объект и заимствуют, поэтому файл создаётся молча.
|
||||
# Отказ — `-Module None`.
|
||||
$script:autoModuleTypes = @("CommonModule", "HTTPService", "WebService")
|
||||
$script:moduleKindNames = @("Module", "ObjectModule", "ManagerModule", "RecordSetModule", "ValueManagerModule")
|
||||
|
||||
# --- 4b. Russian synonym → English type ---
|
||||
$synonymMap = @{
|
||||
"Справочник"="Catalog"; "Документ"="Document"; "Перечисление"="Enum"
|
||||
@@ -591,6 +618,50 @@ if ($BorrowMainAttribute) {
|
||||
}
|
||||
}
|
||||
|
||||
# --- 9c. Validate -Module ---
|
||||
$script:requestedModules = @()
|
||||
$script:noModule = $false
|
||||
if ($Module) {
|
||||
foreach ($raw in ($Module -split '[,;]')) {
|
||||
$kind = $raw.Trim()
|
||||
if (-not $kind) { continue }
|
||||
# Сравнение РЕГИСТРОНЕЗАВИСИМОЕ явно (-ieq): в py-порте это отдельная ветка, и молчаливое
|
||||
# расхождение портов на «none» ловится только глазами.
|
||||
if ($kind -ieq "None") { $script:noModule = $true; continue }
|
||||
$canon = @($script:moduleKindNames | Where-Object { $_ -ieq $kind })
|
||||
if ($canon.Count -eq 0) {
|
||||
Write-Error "Неизвестный вид модуля '$kind'. Допустимо: $($script:moduleKindNames -join ', '), None"
|
||||
exit 1
|
||||
}
|
||||
$script:requestedModules += $canon[0]
|
||||
}
|
||||
if ($script:noModule -and $script:requestedModules.Count -gt 0) {
|
||||
Write-Error "-Module None нельзя сочетать с видами модулей"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# Какие модули создать для объекта. Тип с единственным модулем получает его всегда — уточнять
|
||||
# там нечего; -Module разбирает только неоднозначные типы. Иначе батч смешанных типов
|
||||
# (`CommonModule.X ;; Catalog.Y`) не выражался бы одним вызовом.
|
||||
function Resolve-ModuleKinds {
|
||||
param([string]$typeName)
|
||||
|
||||
if ($script:noModule) { return @() }
|
||||
$allowed = @($script:moduleKindsByType[$typeName])
|
||||
if ($allowed.Count -eq 0) { return @() }
|
||||
|
||||
if ($script:autoModuleTypes -contains $typeName) { return @($allowed[0]) }
|
||||
if ($script:requestedModules.Count -eq 0) { return @() }
|
||||
|
||||
# Порядок берём из таблицы типа, а не из порядка ключей в -Module.
|
||||
$selected = @($allowed | Where-Object { $script:requestedModules -contains $_ })
|
||||
if ($selected.Count -eq 0) {
|
||||
Warn " Тип $typeName не имеет запрошенных модулей — пропущено. Допустимо: $($allowed -join ', ')"
|
||||
}
|
||||
return $selected
|
||||
}
|
||||
|
||||
# --- 10. Helper: read source object XML ---
|
||||
# Имена реквизитов исходного объекта → uuid. Нужны для непрозрачной формы пути в ссылках
|
||||
# параметров выбора (см. Rewrite-ChoiceParameterLinks).
|
||||
@@ -1313,6 +1384,81 @@ function Test-ObjectBorrowed {
|
||||
return (Test-Path $objFile)
|
||||
}
|
||||
|
||||
# --- 10f. Helper: пометка расширенного свойства (<xr:PropertyState>) ---
|
||||
# Свойство появилось в формате 2.19 (8.3.26): на 2.18 и ниже платформа молча выбрасывает элемент
|
||||
# при загрузке. С 2.19 Конфигуратор ставит его сам при выгрузке — эмитим, чтобы исходники навыка
|
||||
# совпадали с эталоном. Имя свойства = базовое имя файла модуля (Module / ObjectModule / …),
|
||||
# у заимствованной формы — Form. Ставит тот, кто создал файл модуля (или форму).
|
||||
function Build-PropertyStateXml {
|
||||
param([string]$propertyName, [string]$indent)
|
||||
|
||||
$sb = New-Object System.Text.StringBuilder
|
||||
$sb.AppendLine("${indent}<xr:PropertyState>") | Out-Null
|
||||
$sb.AppendLine("${indent}`t<xr:Property>${propertyName}</xr:Property>") | Out-Null
|
||||
$sb.AppendLine("${indent}`t<xr:State>Extended</xr:State>") | Out-Null
|
||||
$sb.Append("${indent}</xr:PropertyState>") | Out-Null
|
||||
return $sb.ToString()
|
||||
}
|
||||
|
||||
function Set-PropertyStateFlag {
|
||||
param([string]$objFile, [string]$propertyName, [string]$formatVersion)
|
||||
|
||||
if ((Get-FormatRank $formatVersion) -lt 219) { return }
|
||||
if (-not (Test-Path $objFile)) { return }
|
||||
|
||||
$enc = New-Object System.Text.UTF8Encoding($true)
|
||||
$text = [System.IO.File]::ReadAllText($objFile, $enc)
|
||||
$nl = if ($text -match "`r`n") { "`r`n" } else { "`n" }
|
||||
|
||||
# ПЕРВЫЙ <InternalInfo> в файле — собственный у объекта: у реквизитов и подобъектов свои,
|
||||
# но они лежат ниже, внутри <ChildObjects>.
|
||||
$empty = [regex]::Match($text, '([ \t]*)<InternalInfo\s*/>')
|
||||
$open = [regex]::Match($text, '(?s)([ \t]*)<InternalInfo>(.*?)</InternalInfo>')
|
||||
|
||||
if ($empty.Success -and (-not $open.Success -or $empty.Index -lt $open.Index)) {
|
||||
$ind = $empty.Groups[1].Value
|
||||
$block = Build-PropertyStateXml $propertyName ($ind + "`t")
|
||||
$replacement = "${ind}<InternalInfo>${nl}${block}${nl}${ind}</InternalInfo>"
|
||||
$text = $text.Remove($empty.Index, $empty.Length).Insert($empty.Index, $replacement)
|
||||
} elseif ($open.Success) {
|
||||
if ($open.Groups[2].Value -match "<xr:Property>$([regex]::Escape($propertyName))</xr:Property>") { return }
|
||||
$ind = $open.Groups[1].Value
|
||||
$block = Build-PropertyStateXml $propertyName ($ind + "`t")
|
||||
# Дописываем в КОНЕЦ InternalInfo: у Конфигуратора PropertyState идёт после GeneratedType.
|
||||
$closeAt = $open.Index + $open.Length - "</InternalInfo>".Length - $ind.Length
|
||||
$text = $text.Insert($closeAt, "${block}${nl}")
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
[System.IO.File]::WriteAllText($objFile, $text, $enc)
|
||||
}
|
||||
|
||||
# --- 10g. Helper: пустой модуль заимствованного объекта ---
|
||||
function New-BorrowedModuleFile {
|
||||
param([string]$typeName, [string]$objName, [string]$moduleKind)
|
||||
|
||||
$dirName = $childTypeDirMap[$typeName]
|
||||
$objDir = Join-Path (Join-Path $extDir $dirName) $objName
|
||||
$moduleDir = Join-Path $objDir "Ext"
|
||||
if (-not (Test-Path $moduleDir)) { New-Item -ItemType Directory -Path $moduleDir -Force | Out-Null }
|
||||
|
||||
# NEVER overwrite an existing one: повторное заимствование не должно затирать дописанный код
|
||||
# (то же правило, что у модуля формы).
|
||||
$moduleFile = Join-Path $moduleDir "${moduleKind}.bsl"
|
||||
if (Test-Path $moduleFile) {
|
||||
Info " Preserved existing ${moduleKind}.bsl"
|
||||
} else {
|
||||
$enc = New-Object System.Text.UTF8Encoding($true)
|
||||
[System.IO.File]::WriteAllText($moduleFile, "", $enc)
|
||||
Info " Created: $moduleFile"
|
||||
}
|
||||
|
||||
# Флаг ставим и для уже существовавшего файла: состояние объекта должно отражать факт модуля.
|
||||
Set-PropertyStateFlag (Join-Path (Join-Path $extDir $dirName) "${objName}.xml") $moduleKind $script:formatVersion
|
||||
return $moduleFile
|
||||
}
|
||||
|
||||
# --- 11. Helper: generate InternalInfo XML ---
|
||||
function Build-InternalInfoXml {
|
||||
param([string]$typeName, [string]$objName, [string]$indent)
|
||||
@@ -2204,6 +2350,9 @@ foreach ($item in $items) {
|
||||
$hasBMA = [bool]$BorrowMainAttribute
|
||||
$formFiles = Borrow-Form $typeName $objName $formName -BorrowMainAttr:$hasBMA
|
||||
$script:borrowedFiles += $formFiles
|
||||
# Замер на 8.3.26: платформа помечает форму расширенной сразу при заимствовании,
|
||||
# даже если элементы не менялись. Флаг живёт в метаданных формы, не у владельца.
|
||||
Set-PropertyStateFlag $formFiles[0] "Form" $script:formatVersion
|
||||
$borrowedCount++
|
||||
|
||||
# Borrow main attribute if requested
|
||||
@@ -2212,26 +2361,37 @@ foreach ($item in $items) {
|
||||
}
|
||||
} else {
|
||||
# --- Object borrowing (existing logic) ---
|
||||
Info "Borrowing ${typeName}.${objName}..."
|
||||
|
||||
$src = Read-SourceObject $typeName $objName
|
||||
Info " Source UUID: $($src.Uuid)"
|
||||
|
||||
$borrowedXml = Build-BorrowedObjectXml $typeName $objName $src.Uuid $src.Properties
|
||||
|
||||
$targetDir = Join-Path $extDir $dirName
|
||||
if (-not (Test-Path $targetDir)) {
|
||||
New-Item -ItemType Directory -Path $targetDir -Force | Out-Null
|
||||
}
|
||||
|
||||
$targetFile = Join-Path $targetDir "${objName}.xml"
|
||||
$enc = New-Object System.Text.UTF8Encoding($true)
|
||||
[System.IO.File]::WriteAllText($targetFile, $borrowedXml, $enc)
|
||||
Info " Created: $targetFile"
|
||||
|
||||
# Уже заимствованный объект НЕ переписываем: в его XML лежат собственные реквизиты
|
||||
# расширения, заимствованные подобъекты и состояния, которые из источника не выводятся.
|
||||
# Повторный вызов — законный способ доделать модуль (-Module), а не переиздать заготовку.
|
||||
if (Test-ObjectBorrowed $typeName $objName) {
|
||||
Info "Already borrowed: ${typeName}.${objName} — XML сохранён без изменений"
|
||||
} else {
|
||||
Info "Borrowing ${typeName}.${objName}..."
|
||||
|
||||
$src = Read-SourceObject $typeName $objName
|
||||
Info " Source UUID: $($src.Uuid)"
|
||||
|
||||
$borrowedXml = Build-BorrowedObjectXml $typeName $objName $src.Uuid $src.Properties
|
||||
|
||||
if (-not (Test-Path $targetDir)) {
|
||||
New-Item -ItemType Directory -Path $targetDir -Force | Out-Null
|
||||
}
|
||||
|
||||
$enc = New-Object System.Text.UTF8Encoding($true)
|
||||
[System.IO.File]::WriteAllText($targetFile, $borrowedXml, $enc)
|
||||
Info " Created: $targetFile"
|
||||
}
|
||||
|
||||
Add-ToChildObjects $typeName $objName
|
||||
|
||||
$script:borrowedFiles += $targetFile
|
||||
foreach ($kind in (Resolve-ModuleKinds $typeName)) {
|
||||
$script:borrowedFiles += (New-BorrowedModuleFile $typeName $objName $kind)
|
||||
}
|
||||
$borrowedCount++
|
||||
}
|
||||
}
|
||||
+160
-12
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# cfe-borrow v1.31 — Borrow objects from configuration into extension (CFE)
|
||||
# cfe-borrow v1.32 — Borrow objects from configuration into extension (CFE)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -240,6 +240,32 @@ CHILD_TYPE_DIR_MAP = {
|
||||
"Bot": "Bots", "Language": "Languages",
|
||||
}
|
||||
|
||||
# --- Модули заимствованных объектов ---
|
||||
# Порядок внутри значения — порядок выгрузки Конфигуратора: сначала «объектный» модуль
|
||||
# (ObjectModule / RecordSetModule / ValueManagerModule), затем ManagerModule.
|
||||
MODULE_KINDS_BY_TYPE = {
|
||||
"CommonModule": ["Module"], "HTTPService": ["Module"], "WebService": ["Module"],
|
||||
"Catalog": ["ObjectModule", "ManagerModule"], "Document": ["ObjectModule", "ManagerModule"],
|
||||
"Report": ["ObjectModule", "ManagerModule"], "DataProcessor": ["ObjectModule", "ManagerModule"],
|
||||
"ExchangePlan": ["ObjectModule", "ManagerModule"],
|
||||
"ChartOfCharacteristicTypes": ["ObjectModule", "ManagerModule"],
|
||||
"ChartOfAccounts": ["ObjectModule", "ManagerModule"],
|
||||
"ChartOfCalculationTypes": ["ObjectModule", "ManagerModule"],
|
||||
"BusinessProcess": ["ObjectModule", "ManagerModule"], "Task": ["ObjectModule", "ManagerModule"],
|
||||
"InformationRegister": ["RecordSetModule", "ManagerModule"],
|
||||
"AccumulationRegister": ["RecordSetModule", "ManagerModule"],
|
||||
"AccountingRegister": ["RecordSetModule", "ManagerModule"],
|
||||
"CalculationRegister": ["RecordSetModule", "ManagerModule"],
|
||||
"Sequence": ["RecordSetModule", "ManagerModule"],
|
||||
"Constant": ["ValueManagerModule", "ManagerModule"],
|
||||
"Enum": ["ManagerModule"], "DocumentJournal": ["ManagerModule"],
|
||||
"FilterCriterion": ["ManagerModule"],
|
||||
}
|
||||
# Типы с ЕДИНСТВЕННЫМ модулем: ради него объект и заимствуют, поэтому файл создаётся молча.
|
||||
# Отказ — `-Module None`.
|
||||
AUTO_MODULE_TYPES = ["CommonModule", "HTTPService", "WebService"]
|
||||
MODULE_KIND_NAMES = ["Module", "ObjectModule", "ManagerModule", "RecordSetModule", "ValueManagerModule"]
|
||||
|
||||
SYNONYM_MAP = {
|
||||
"\u0421\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a": "Catalog",
|
||||
"\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442": "Document",
|
||||
@@ -516,6 +542,55 @@ def format_rank(ver):
|
||||
return int(m.group(1)) * 100 + int(m.group(2)) if m else 0
|
||||
|
||||
|
||||
# --- Пометка расширенного свойства (<xr:PropertyState>) ---
|
||||
# Свойство появилось в формате 2.19 (8.3.26): на 2.18 и ниже платформа молча выбрасывает элемент
|
||||
# при загрузке. С 2.19 Конфигуратор ставит его сам при выгрузке. Правило: флаг ставит тот, кто
|
||||
# создал файл модуля, — здесь это мы. Имя свойства = базовое имя файла модуля.
|
||||
# Копии этих функций есть в cfe-patch-method (навыки автономны); держать их одинаковыми — сознательно.
|
||||
def build_property_state_xml(property_name, indent):
|
||||
return "\n".join([
|
||||
f"{indent}<xr:PropertyState>",
|
||||
f"{indent}\t<xr:Property>{property_name}</xr:Property>",
|
||||
f"{indent}\t<xr:State>Extended</xr:State>",
|
||||
f"{indent}</xr:PropertyState>",
|
||||
])
|
||||
|
||||
|
||||
def set_property_state_flag(obj_file, property_name, format_version):
|
||||
if format_rank(format_version) < 219:
|
||||
return
|
||||
if not os.path.isfile(obj_file):
|
||||
return
|
||||
|
||||
with open(obj_file, "r", encoding="utf-8-sig", newline="") as fh:
|
||||
text = fh.read()
|
||||
nl = "\r\n" if "\r\n" in text else "\n"
|
||||
|
||||
# ПЕРВЫЙ <InternalInfo> в файле — собственный у объекта: у реквизитов и подобъектов свои,
|
||||
# но они лежат ниже, внутри <ChildObjects>.
|
||||
empty = re.search(r"([ \t]*)<InternalInfo\s*/>", text)
|
||||
opened = re.search(r"([ \t]*)<InternalInfo>(.*?)</InternalInfo>", text, re.S)
|
||||
|
||||
if empty and (not opened or empty.start() < opened.start()):
|
||||
ind = empty.group(1)
|
||||
block = build_property_state_xml(property_name, ind + "\t")
|
||||
replacement = f"{ind}<InternalInfo>{nl}{block}{nl}{ind}</InternalInfo>"
|
||||
text = text[:empty.start()] + replacement + text[empty.end():]
|
||||
elif opened:
|
||||
if re.search(rf"<xr:Property>{re.escape(property_name)}</xr:Property>", opened.group(2)):
|
||||
return
|
||||
ind = opened.group(1)
|
||||
block = build_property_state_xml(property_name, ind + "\t")
|
||||
# Дописываем в КОНЕЦ InternalInfo: у Конфигуратора PropertyState идёт после GeneratedType.
|
||||
close_at = opened.end() - len("</InternalInfo>") - len(ind)
|
||||
text = text[:close_at] + block + nl + text[close_at:]
|
||||
else:
|
||||
return
|
||||
|
||||
with open(obj_file, "w", encoding="utf-8-sig", newline="") as fh:
|
||||
fh.write(text)
|
||||
|
||||
|
||||
def apply_pal_ns(format_version):
|
||||
"""2.21 (8.5) добавила в шапку пространство палитры — ради <Color> у значений перечисления.
|
||||
Вставляем НА МЕСТО (после lf, перед style): платформа держит объявления по алфавиту,
|
||||
@@ -655,6 +730,7 @@ def main():
|
||||
parser.add_argument("-ConfigPath", required=True)
|
||||
parser.add_argument("-Object", required=True)
|
||||
parser.add_argument("-BorrowMainAttribute", nargs="?", const="Form", default=None)
|
||||
parser.add_argument("-Module", default=None)
|
||||
args = ci_parse_args(parser)
|
||||
|
||||
# --- 1. Resolve paths ---
|
||||
@@ -860,6 +936,25 @@ def main():
|
||||
sys.exit(1)
|
||||
return src_uuid
|
||||
|
||||
# --- Пустой модуль заимствованного объекта ---
|
||||
def new_borrowed_module_file(type_name, obj_name, module_kind):
|
||||
dir_name = CHILD_TYPE_DIR_MAP[type_name]
|
||||
module_dir = os.path.join(ext_dir, dir_name, obj_name, "Ext")
|
||||
os.makedirs(module_dir, exist_ok=True)
|
||||
|
||||
# NEVER overwrite an existing one: повторное заимствование не должно затирать дописанный
|
||||
# код (то же правило, что у модуля формы).
|
||||
module_file = os.path.join(module_dir, f"{module_kind}.bsl")
|
||||
if os.path.isfile(module_file):
|
||||
info(f" Preserved existing {module_kind}.bsl")
|
||||
else:
|
||||
write_utf8_bom(module_file, "")
|
||||
info(f" Created: {module_file}")
|
||||
|
||||
# Флаг ставим и для уже существовавшего файла: состояние объекта должно отражать факт модуля.
|
||||
set_property_state_flag(os.path.join(ext_dir, dir_name, f"{obj_name}.xml"), module_kind, format_version)
|
||||
return module_file
|
||||
|
||||
def build_internal_info_xml(type_name, obj_name, indent):
|
||||
types = GENERATED_TYPES.get(type_name)
|
||||
if not types:
|
||||
@@ -2019,6 +2114,47 @@ def main():
|
||||
print("-BorrowMainAttribute requires a form in -Object (e.g. 'Catalog.X.Form.Y')", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# --- 9c. Validate -Module ---
|
||||
requested_modules = []
|
||||
no_module = False
|
||||
if args.Module:
|
||||
for raw in re.split(r"[,;]", args.Module):
|
||||
kind = raw.strip()
|
||||
if not kind:
|
||||
continue
|
||||
# Сравнение РЕГИСТРОНЕЗАВИСИМОЕ явно: в ps1-порте `-ieq`, и молчаливое расхождение
|
||||
# портов на «none» ловится только глазами.
|
||||
if kind.lower() == "none":
|
||||
no_module = True
|
||||
continue
|
||||
canon = [k for k in MODULE_KIND_NAMES if k.lower() == kind.lower()]
|
||||
if not canon:
|
||||
print(f"Неизвестный вид модуля '{kind}'. Допустимо: {', '.join(MODULE_KIND_NAMES)}, None", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
requested_modules.append(canon[0])
|
||||
if no_module and requested_modules:
|
||||
print("-Module None нельзя сочетать с видами модулей", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Какие модули создать для объекта. Тип с единственным модулем получает его всегда — уточнять
|
||||
# там нечего; -Module разбирает только неоднозначные типы. Иначе батч смешанных типов
|
||||
# (`CommonModule.X ;; Catalog.Y`) не выражался бы одним вызовом.
|
||||
def resolve_module_kinds(type_name):
|
||||
if no_module:
|
||||
return []
|
||||
allowed = MODULE_KINDS_BY_TYPE.get(type_name, [])
|
||||
if not allowed:
|
||||
return []
|
||||
if type_name in AUTO_MODULE_TYPES:
|
||||
return [allowed[0]]
|
||||
if not requested_modules:
|
||||
return []
|
||||
# Порядок берём из таблицы типа, а не из порядка ключей в -Module.
|
||||
selected = [k for k in allowed if k in requested_modules]
|
||||
if not selected:
|
||||
warn(f" Тип {type_name} не имеет запрошенных модулей — пропущено. Допустимо: {', '.join(allowed)}")
|
||||
return selected
|
||||
|
||||
# --- 10. Process each item ---
|
||||
borrowed_count = 0
|
||||
|
||||
@@ -2070,6 +2206,9 @@ def main():
|
||||
has_bma = borrow_main_attribute_mode is not None
|
||||
form_files = borrow_form(type_name, obj_name, form_name, borrow_main_attr=has_bma)
|
||||
borrowed_files.extend(form_files)
|
||||
# Замер на 8.3.26: платформа помечает форму расширенной сразу при заимствовании,
|
||||
# даже если элементы не менялись. Флаг живёт в метаданных формы, не у владельца.
|
||||
set_property_state_flag(form_files[0], "Form", format_version)
|
||||
borrowed_count += 1
|
||||
|
||||
# Borrow main attribute if requested
|
||||
@@ -2077,23 +2216,32 @@ def main():
|
||||
borrow_main_attribute(type_name, obj_name, form_name, borrow_main_attribute_mode)
|
||||
else:
|
||||
# --- Object borrowing ---
|
||||
info(f"Borrowing {type_name}.{obj_name}...")
|
||||
|
||||
src = read_source_object(type_name, obj_name)
|
||||
info(f" Source UUID: {src['Uuid']}")
|
||||
|
||||
borrowed_xml = build_borrowed_object_xml(type_name, obj_name, src["Uuid"], src["Properties"])
|
||||
|
||||
target_dir = os.path.join(ext_dir, dir_name)
|
||||
os.makedirs(target_dir, exist_ok=True)
|
||||
|
||||
target_file = os.path.join(target_dir, f"{obj_name}.xml")
|
||||
write_xml_file(target_file, borrowed_xml)
|
||||
info(f" Created: {target_file}")
|
||||
|
||||
# Уже заимствованный объект НЕ переписываем: в его XML лежат собственные реквизиты
|
||||
# расширения, заимствованные подобъекты и состояния, которые из источника не
|
||||
# выводятся. Повторный вызов — законный способ доделать модуль (-Module), а не
|
||||
# переиздать заготовку.
|
||||
if test_object_borrowed(type_name, obj_name):
|
||||
info(f"Already borrowed: {type_name}.{obj_name} — XML сохранён без изменений")
|
||||
else:
|
||||
info(f"Borrowing {type_name}.{obj_name}...")
|
||||
|
||||
src = read_source_object(type_name, obj_name)
|
||||
info(f" Source UUID: {src['Uuid']}")
|
||||
|
||||
borrowed_xml = build_borrowed_object_xml(type_name, obj_name, src["Uuid"], src["Properties"])
|
||||
|
||||
os.makedirs(target_dir, exist_ok=True)
|
||||
write_xml_file(target_file, borrowed_xml)
|
||||
info(f" Created: {target_file}")
|
||||
|
||||
add_to_child_objects(type_name, obj_name)
|
||||
|
||||
borrowed_files.append(target_file)
|
||||
for kind in resolve_module_kinds(type_name):
|
||||
borrowed_files.append(new_borrowed_module_file(type_name, obj_name, kind))
|
||||
borrowed_count += 1
|
||||
|
||||
# --- Владельцы заимствованных справочников ---
|
||||
@@ -23,7 +23,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-diff.ps1" -ExtensionPath src\cfe\extname -ConfigPath src\cf -Mode A
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/cfe-diff/scripts/cfe-diff.ps1" -ExtensionPath src\cfe\extname -ConfigPath src\cf -Mode A
|
||||
```
|
||||
|
||||
## Mode A — обзор расширения
|
||||
@@ -44,7 +44,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-init.ps1" -Name "МоёРасширение" -OutputDir "src\cfe\МоёРасширение" -ConfigPath "src\cf"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/cfe-init/scripts/cfe-init.ps1" -Name "МоёРасширение" -OutputDir "src\cfe\МоёРасширение" -ConfigPath "src\cf"
|
||||
```
|
||||
|
||||
## Примеры
|
||||
@@ -110,7 +110,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-patch-method.ps1" -ExtensionPath src\cfe\extname -ConfigPath src\cf -ModulePath "Catalog.Контрагенты.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/cfe-patch-method/scripts/cfe-patch-method.ps1" -ExtensionPath src\cfe\extname -ConfigPath src\cf -ModulePath "Catalog.Контрагенты.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before
|
||||
```
|
||||
|
||||
## Примеры
|
||||
+101
-1
@@ -1,4 +1,4 @@
|
||||
# cfe-patch-method v2.7 — Source-aware method interceptor for 1C extension (CFE) (+прощающий ввод: имя каталога наравне с именем типа)
|
||||
# cfe-patch-method v2.8 — Source-aware method interceptor for 1C extension (CFE)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -788,6 +788,100 @@ if (Test-Path $ExtensionPath -PathType Leaf) { $ExtensionPath = Split-Path $Exte
|
||||
$cfgFile = Join-Path $ExtensionPath "Configuration.xml"
|
||||
if (-not (Test-Path $cfgFile)) { Write-Error "Configuration.xml не найден в расширении: $ExtensionPath"; exit 1 }
|
||||
|
||||
# --- Пометка расширенного свойства (<xr:PropertyState>) ---
|
||||
# Свойство появилось в формате 2.19 (8.3.26): на 2.18 и ниже платформа молча выбрасывает элемент
|
||||
# при загрузке. С 2.19 Конфигуратор ставит его сам при выгрузке. Правило: флаг ставит тот, кто
|
||||
# создал файл модуля, — здесь это мы. Имя свойства = базовое имя файла модуля.
|
||||
# Копии этих функций есть в cfe-borrow (навыки автономны); держать их одинаковыми — сознательно.
|
||||
function Get-FormatRank([string]$ver) {
|
||||
if ($ver -match '^(\d+)\.(\d+)$') { return [int]$Matches[1] * 100 + [int]$Matches[2] }
|
||||
return 0
|
||||
}
|
||||
|
||||
function Detect-FormatVersion([string]$dir) {
|
||||
$d = $dir
|
||||
while ($d) {
|
||||
# Автономная внешняя обработка/отчёт: своего Configuration.xml у неё нет, версию несёт
|
||||
# корень самой обработки. Без этого форма и макет внутри обработки 2.21 писались бы 2.17.
|
||||
$extPath = "$d.xml"
|
||||
if (Test-Path $extPath) {
|
||||
$extText = [System.IO.File]::ReadAllText($extPath, [System.Text.Encoding]::UTF8)
|
||||
$extHead = $extText.Substring(0, [Math]::Min(2000, $extText.Length))
|
||||
if ($extHead -match '<(ExternalDataProcessor|ExternalReport)[ >]' -and $extHead -match '<MetaDataObject[^>]+version="(\d+\.\d+)"') { return $Matches[1] }
|
||||
}
|
||||
$cfgPath = Join-Path $d "Configuration.xml"
|
||||
if (Test-Path $cfgPath) {
|
||||
$cfgText = [System.IO.File]::ReadAllText($cfgPath, [System.Text.Encoding]::UTF8)
|
||||
# Длину среза берём по СТРОКЕ, а не по размеру файла: размер в БАЙТАХ, Substring считает
|
||||
# СИМВОЛЫ, и на кириллице байт больше — короткий Configuration.xml ронял навык исключением.
|
||||
$head = $cfgText.Substring(0, [Math]::Min(2000, $cfgText.Length))
|
||||
if ($head -match '<MetaDataObject[^>]+version="(\d+\.\d+)"') { return $Matches[1] }
|
||||
}
|
||||
$parent = Split-Path $d -Parent
|
||||
if ($parent -eq $d) { break }
|
||||
$d = $parent
|
||||
}
|
||||
return "2.17"
|
||||
}
|
||||
|
||||
function Build-PropertyStateXml {
|
||||
param([string]$propertyName, [string]$indent)
|
||||
|
||||
$sb = New-Object System.Text.StringBuilder
|
||||
$sb.AppendLine("${indent}<xr:PropertyState>") | Out-Null
|
||||
$sb.AppendLine("${indent}`t<xr:Property>${propertyName}</xr:Property>") | Out-Null
|
||||
$sb.AppendLine("${indent}`t<xr:State>Extended</xr:State>") | Out-Null
|
||||
$sb.Append("${indent}</xr:PropertyState>") | Out-Null
|
||||
return $sb.ToString()
|
||||
}
|
||||
|
||||
function Set-PropertyStateFlag {
|
||||
param([string]$objFile, [string]$propertyName, [string]$formatVersion)
|
||||
|
||||
if ((Get-FormatRank $formatVersion) -lt 219) { return }
|
||||
if (-not (Test-Path $objFile)) { return }
|
||||
|
||||
$enc = New-Object System.Text.UTF8Encoding($true)
|
||||
$text = [System.IO.File]::ReadAllText($objFile, $enc)
|
||||
$nl = if ($text -match "`r`n") { "`r`n" } else { "`n" }
|
||||
|
||||
# ПЕРВЫЙ <InternalInfo> в файле — собственный у объекта: у реквизитов и подобъектов свои,
|
||||
# но они лежат ниже, внутри <ChildObjects>.
|
||||
$empty = [regex]::Match($text, '([ \t]*)<InternalInfo\s*/>')
|
||||
$open = [regex]::Match($text, '(?s)([ \t]*)<InternalInfo>(.*?)</InternalInfo>')
|
||||
|
||||
if ($empty.Success -and (-not $open.Success -or $empty.Index -lt $open.Index)) {
|
||||
$ind = $empty.Groups[1].Value
|
||||
$block = Build-PropertyStateXml $propertyName ($ind + "`t")
|
||||
$replacement = "${ind}<InternalInfo>${nl}${block}${nl}${ind}</InternalInfo>"
|
||||
$text = $text.Remove($empty.Index, $empty.Length).Insert($empty.Index, $replacement)
|
||||
} elseif ($open.Success) {
|
||||
if ($open.Groups[2].Value -match "<xr:Property>$([regex]::Escape($propertyName))</xr:Property>") { return }
|
||||
$ind = $open.Groups[1].Value
|
||||
$block = Build-PropertyStateXml $propertyName ($ind + "`t")
|
||||
# Дописываем в КОНЕЦ InternalInfo: у Конфигуратора PropertyState идёт после GeneratedType.
|
||||
$closeAt = $open.Index + $open.Length - "</InternalInfo>".Length - $ind.Length
|
||||
$text = $text.Insert($closeAt, "${block}${nl}")
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
[System.IO.File]::WriteAllText($objFile, $text, $enc)
|
||||
}
|
||||
|
||||
# Модуль формы сюда не попадает: у формы флаг называется Form и ставится при заимствовании,
|
||||
# а не при появлении модуля (замер на 8.3.26 — пустой модуль формы платформа не выгружает).
|
||||
function Get-ModuleFlagTarget {
|
||||
param([string[]]$relParts, [string]$extRoot)
|
||||
|
||||
if ($relParts.Count -ne 4 -or $relParts[2] -ne "Ext") { return $null }
|
||||
$prop = [System.IO.Path]::GetFileNameWithoutExtension($relParts[3])
|
||||
return @{
|
||||
File = (Join-Path (Join-Path $extRoot $relParts[0]) "$($relParts[1]).xml")
|
||||
Property = $prop
|
||||
}
|
||||
}
|
||||
|
||||
# --- Read NamePrefix ---
|
||||
$cfgDoc = New-Object System.Xml.XmlDocument
|
||||
$cfgDoc.PreserveWhitespace = $false
|
||||
@@ -1084,6 +1178,12 @@ if ($reuseRegionIdx -ge 0) {
|
||||
}
|
||||
}
|
||||
|
||||
# Модуль в расширении есть — отражаем это в метаданных объекта (формат ≥ 2.19).
|
||||
$flagTarget = Get-ModuleFlagTarget $relParts $ExtensionPath
|
||||
if ($flagTarget) {
|
||||
Set-PropertyStateFlag $flagTarget.File $flagTarget.Property (Detect-FormatVersion $ExtensionPath)
|
||||
}
|
||||
|
||||
Write-Host "[OK] Перехватчик &$decoratorRu(`"$MethodName`") — $placement"
|
||||
Write-Host " Файл: $extBsl"
|
||||
Write-Host " Процедура: $interceptorName($($method.ParamsText -replace '\s+', ' '))"
|
||||
+100
-1
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# cfe-patch-method v2.7 — Source-aware method interceptor for 1C extension (CFE) (+прощающий ввод: имя каталога наравне с именем типа)
|
||||
# cfe-patch-method v2.8 — Source-aware method interceptor for 1C extension (CFE)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -75,6 +75,99 @@ CONTEXT_RE = re.compile(
|
||||
)
|
||||
|
||||
|
||||
# --- Пометка расширенного свойства (<xr:PropertyState>) ---
|
||||
# Свойство появилось в формате 2.19 (8.3.26): на 2.18 и ниже платформа молча выбрасывает элемент
|
||||
# при загрузке. С 2.19 Конфигуратор ставит его сам при выгрузке. Правило: флаг ставит тот, кто
|
||||
# создал файл модуля, — здесь это мы. Имя свойства = базовое имя файла модуля.
|
||||
# Копии этих функций есть в cfe-borrow (навыки автономны); держать их одинаковыми — сознательно.
|
||||
def detect_format_version(d):
|
||||
while d:
|
||||
# Автономная внешняя обработка/отчёт: своего Configuration.xml у неё нет, версию несёт
|
||||
# корень самой обработки. Без этого форма и макет внутри обработки 2.21 писались бы 2.17.
|
||||
ext_path = d + ".xml"
|
||||
if os.path.isfile(ext_path):
|
||||
with open(ext_path, "r", encoding="utf-8-sig") as f:
|
||||
ext_head = f.read(2000)
|
||||
if re.search(r'<(ExternalDataProcessor|ExternalReport)[ >]', ext_head):
|
||||
m = re.search(r'<MetaDataObject[^>]+version="(\d+\.\d+)"', ext_head)
|
||||
if m:
|
||||
return m.group(1)
|
||||
cfg_path = os.path.join(d, "Configuration.xml")
|
||||
if os.path.isfile(cfg_path):
|
||||
with open(cfg_path, "r", encoding="utf-8-sig") as f:
|
||||
head = f.read(2000)
|
||||
m = re.search(r'<MetaDataObject[^>]+version="(\d+\.\d+)"', head)
|
||||
if m:
|
||||
return m.group(1)
|
||||
parent = os.path.dirname(d)
|
||||
if parent == d:
|
||||
break
|
||||
d = parent
|
||||
return "2.17"
|
||||
|
||||
|
||||
def format_rank(ver):
|
||||
""""2.20" → 220, "2.9" → 209. Строковое сравнение неверно ("2.9" > "2.17")."""
|
||||
m = re.match(r'^(\d+)\.(\d+)$', ver or '')
|
||||
return int(m.group(1)) * 100 + int(m.group(2)) if m else 0
|
||||
|
||||
|
||||
def build_property_state_xml(property_name, indent):
|
||||
return "\n".join([
|
||||
f"{indent}<xr:PropertyState>",
|
||||
f"{indent}\t<xr:Property>{property_name}</xr:Property>",
|
||||
f"{indent}\t<xr:State>Extended</xr:State>",
|
||||
f"{indent}</xr:PropertyState>",
|
||||
])
|
||||
|
||||
|
||||
def set_property_state_flag(obj_file, property_name, format_version):
|
||||
if format_rank(format_version) < 219:
|
||||
return
|
||||
if not os.path.isfile(obj_file):
|
||||
return
|
||||
|
||||
with open(obj_file, "r", encoding="utf-8-sig", newline="") as fh:
|
||||
text = fh.read()
|
||||
nl = "\r\n" if "\r\n" in text else "\n"
|
||||
|
||||
# ПЕРВЫЙ <InternalInfo> в файле — собственный у объекта: у реквизитов и подобъектов свои,
|
||||
# но они лежат ниже, внутри <ChildObjects>.
|
||||
empty = re.search(r"([ \t]*)<InternalInfo\s*/>", text)
|
||||
opened = re.search(r"([ \t]*)<InternalInfo>(.*?)</InternalInfo>", text, re.S)
|
||||
|
||||
if empty and (not opened or empty.start() < opened.start()):
|
||||
ind = empty.group(1)
|
||||
block = build_property_state_xml(property_name, ind + "\t")
|
||||
replacement = f"{ind}<InternalInfo>{nl}{block}{nl}{ind}</InternalInfo>"
|
||||
text = text[:empty.start()] + replacement + text[empty.end():]
|
||||
elif opened:
|
||||
if re.search(rf"<xr:Property>{re.escape(property_name)}</xr:Property>", opened.group(2)):
|
||||
return
|
||||
ind = opened.group(1)
|
||||
block = build_property_state_xml(property_name, ind + "\t")
|
||||
# Дописываем в КОНЕЦ InternalInfo: у Конфигуратора PropertyState идёт после GeneratedType.
|
||||
close_at = opened.end() - len("</InternalInfo>") - len(ind)
|
||||
text = text[:close_at] + block + nl + text[close_at:]
|
||||
else:
|
||||
return
|
||||
|
||||
with open(obj_file, "w", encoding="utf-8-sig", newline="") as fh:
|
||||
fh.write(text)
|
||||
|
||||
|
||||
# Модуль формы сюда не попадает: у формы флаг называется Form и ставится при заимствовании,
|
||||
# а не при появлении модуля (замер на 8.3.26 — пустой модуль формы платформа не выгружает).
|
||||
def get_module_flag_target(rel_parts, ext_root):
|
||||
if len(rel_parts) != 4 or rel_parts[2] != "Ext":
|
||||
return None
|
||||
prop = os.path.splitext(rel_parts[3])[0]
|
||||
return {
|
||||
"file": os.path.join(ext_root, rel_parts[0], f"{rel_parts[1]}.xml"),
|
||||
"property": prop,
|
||||
}
|
||||
|
||||
|
||||
def get_module_rel_path(module_path):
|
||||
parts = module_path.split(".")
|
||||
if len(parts) < 2:
|
||||
@@ -841,6 +934,12 @@ def main():
|
||||
|
||||
place_new(ext_bsl, ext_lines, ext_exists, method["chain"], core)
|
||||
|
||||
# Модуль в расширении есть — отражаем это в метаданных объекта (формат ≥ 2.19).
|
||||
flag_target = get_module_flag_target(rel_parts, extension_path)
|
||||
if flag_target:
|
||||
set_property_state_flag(flag_target["file"], flag_target["property"],
|
||||
detect_format_version(extension_path))
|
||||
|
||||
# emit summary
|
||||
placement = place_new.placement
|
||||
print('[OK] Перехватчик &%s("%s") — %s' % (decorator_ru, method_name, placement))
|
||||
@@ -10,7 +10,7 @@ allowed-tools:
|
||||
|
||||
# /cfe-validate — валидация расширения конфигурации (CFE)
|
||||
|
||||
Проверяет структурную корректность расширения: XML-формат, свойства, состав, заимствованные объекты. Аналог `/cf-validate`, но для расширений.
|
||||
Проверяет структурную корректность расширения: XML-формат, свойства, состав, заимствованные объекты, права ролей. Аналог `/cf-validate`, но для расширений.
|
||||
|
||||
## Параметры
|
||||
|
||||
@@ -34,7 +34,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-validate.ps1" -ExtensionPath "src\cfe\extname"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-validate.ps1" -ExtensionPath "src\cfe\extname\Configuration.xml"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-validate.ps1" -ExtensionPath "src\cfe\extname" -ConfigPath "src\cf"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/cfe-validate/scripts/cfe-validate.ps1" -ExtensionPath "src\cfe\extname"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/cfe-validate/scripts/cfe-validate.ps1" -ExtensionPath "src\cfe\extname\Configuration.xml"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/cfe-validate/scripts/cfe-validate.ps1" -ExtensionPath "src\cfe\extname" -ConfigPath "src\cf"
|
||||
```
|
||||
+128
-2
@@ -1,4 +1,4 @@
|
||||
# cfe-validate v1.10 — Validate 1C configuration extension structure (CFE) (полнота GeneratedType, ТЧ из AdditionalColumns, сверка путей с -ConfigPath)
|
||||
# cfe-validate v1.13 — Validate 1C configuration extension structure (CFE)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -107,7 +107,28 @@ function Get-FormatRank([string]$ver) {
|
||||
}
|
||||
|
||||
# --- Reference tables ---
|
||||
$guidPattern = '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'
|
||||
# Модули заимствованных объектов: тип → виды модулей. Имя свойства в <xr:PropertyState>
|
||||
# совпадает с базовым именем файла модуля. Копия таблицы есть в cfe-borrow (навыки автономны).
|
||||
$moduleKindsByType = @{
|
||||
"CommonModule"=@("Module"); "HTTPService"=@("Module"); "WebService"=@("Module")
|
||||
"Catalog"=@("ObjectModule","ManagerModule"); "Document"=@("ObjectModule","ManagerModule")
|
||||
"Report"=@("ObjectModule","ManagerModule"); "DataProcessor"=@("ObjectModule","ManagerModule")
|
||||
"ExchangePlan"=@("ObjectModule","ManagerModule")
|
||||
"ChartOfCharacteristicTypes"=@("ObjectModule","ManagerModule")
|
||||
"ChartOfAccounts"=@("ObjectModule","ManagerModule")
|
||||
"ChartOfCalculationTypes"=@("ObjectModule","ManagerModule")
|
||||
"BusinessProcess"=@("ObjectModule","ManagerModule"); "Task"=@("ObjectModule","ManagerModule")
|
||||
"InformationRegister"=@("RecordSetModule","ManagerModule")
|
||||
"AccumulationRegister"=@("RecordSetModule","ManagerModule")
|
||||
"AccountingRegister"=@("RecordSetModule","ManagerModule")
|
||||
"CalculationRegister"=@("RecordSetModule","ManagerModule")
|
||||
"Sequence"=@("RecordSetModule","ManagerModule")
|
||||
"Constant"=@("ValueManagerModule","ManagerModule")
|
||||
"Enum"=@("ManagerModule"); "DocumentJournal"=@("ManagerModule")
|
||||
"FilterCriterion"=@("ManagerModule")
|
||||
}
|
||||
|
||||
$guidPattern ='^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'
|
||||
$identPattern = '^[A-Za-z\u0410-\u042F\u0401\u0430-\u044F\u0451_][A-Za-z0-9\u0410-\u042F\u0401\u0430-\u044F\u0451_]*$'
|
||||
|
||||
# 7 fixed ClassIds for Configuration
|
||||
@@ -1169,8 +1190,113 @@ if (-not $script:stopped -and $script:borrowedFormsWithTree.Count -gt 0) {
|
||||
}
|
||||
}
|
||||
|
||||
# --- Check 15: основные роли расширения не дают прав на заимствованные объекты ---
|
||||
# Платформа: «Назначение прав доступа на заимствованные объекты основными ролями в
|
||||
# расширениях недопустимо». Роль вне <DefaultRoles> так делать вправе — проверяем только
|
||||
# основные. Ловится статически, а по симптому (отказ загрузки) причина не читается.
|
||||
$defaultRoleNodes = @($cfgNode.SelectNodes("md:Properties/md:DefaultRoles/xr:Item", $ns))
|
||||
if ($defaultRoleNodes.Count -gt 0) {
|
||||
$adoptedCache = @{}
|
||||
|
||||
function Test-ObjectAdopted {
|
||||
param([string]$typeName, [string]$objName)
|
||||
$key = "$typeName.$objName"
|
||||
if ($adoptedCache.ContainsKey($key)) { return $adoptedCache[$key] }
|
||||
$adoptedCache[$key] = $false
|
||||
if ($childTypeDirMap.ContainsKey($typeName)) {
|
||||
$objPath = Join-Path (Join-Path $configDir $childTypeDirMap[$typeName]) "$objName.xml"
|
||||
if (Test-Path $objPath) {
|
||||
try {
|
||||
$objDoc = New-Object System.Xml.XmlDocument
|
||||
$objDoc.Load($objPath)
|
||||
$objNs = New-Object System.Xml.XmlNamespaceManager($objDoc.NameTable)
|
||||
$objNs.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
|
||||
$ob = $objDoc.SelectSingleNode("/md:MetaDataObject/md:$typeName/md:Properties/md:ObjectBelonging", $objNs)
|
||||
if ($ob -and $ob.InnerText -eq "Adopted") { $adoptedCache[$key] = $true }
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
return $adoptedCache[$key]
|
||||
}
|
||||
|
||||
$check15Ok = $true
|
||||
$check15Count = 0
|
||||
foreach ($rn in $defaultRoleNodes) {
|
||||
$roleRef = $rn.InnerText
|
||||
if ($roleRef -notmatch '^Role\.(.+)$') { continue }
|
||||
$defRoleName = $Matches[1]
|
||||
$rightsPath = Join-Path (Join-Path (Join-Path $configDir "Roles") $defRoleName) "Ext\Rights.xml"
|
||||
if (-not (Test-Path $rightsPath)) { continue }
|
||||
try {
|
||||
$rDoc = New-Object System.Xml.XmlDocument
|
||||
$rDoc.Load($rightsPath)
|
||||
} catch {
|
||||
continue
|
||||
}
|
||||
$rNs = New-Object System.Xml.XmlNamespaceManager($rDoc.NameTable)
|
||||
$rNs.AddNamespace("r", "http://v8.1c.ru/8.2/roles")
|
||||
foreach ($nameNode in $rDoc.SelectNodes("/r:Rights/r:object/r:name", $rNs)) {
|
||||
$fullName = $nameNode.InnerText
|
||||
$segs = $fullName.Split(".")
|
||||
# Configuration.* — права самого расширения, не объект; заимствования там нет.
|
||||
if ($segs.Count -lt 2 -or $segs[0] -eq "Configuration") { continue }
|
||||
$check15Count++
|
||||
if (Test-ObjectAdopted $segs[0] $segs[1]) {
|
||||
Report-Error ("15. Роль '$defRoleName' входит в DefaultRoles и даёт права на заимствованный $($segs[0]).$($segs[1]) " +
|
||||
"($fullName): платформа это запрещает. Вынесите такие права в отдельную роль вне DefaultRoles.")
|
||||
$check15Ok = $false
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($check15Ok -and $check15Count -gt 0) {
|
||||
Report-OK "15. Основные роли: прав на заимствованные объекты нет ($check15Count checked)"
|
||||
}
|
||||
}
|
||||
|
||||
if ($script:stopped) { & $finalize; exit 1 }
|
||||
|
||||
# --- Check 16: модуль заимствованного объекта и пометка расширенного свойства ---
|
||||
# Свойство <xr:PropertyState> появилось в формате 2.19 (8.3.26); ниже платформа его молча
|
||||
# выбрасывает, поэтому там проверять нечего. С 2.19 состояние обязано соответствовать факту:
|
||||
# есть файл модуля — есть пометка, и наоборот. Перекос платформа принимает (проверено на стенде),
|
||||
# но выгрузка Конфигуратора так не выглядит — отсюда предупреждение, а не ошибка.
|
||||
if ($versionRank -ge 219 -and $childObjNode) {
|
||||
$stateIssues = @()
|
||||
$stateChecked = 0
|
||||
foreach ($child in $childObjNode.ChildNodes) {
|
||||
if ($child.NodeType -ne 'Element') { continue }
|
||||
$typeName = $child.LocalName
|
||||
if (-not $moduleKindsByType.ContainsKey($typeName)) { continue }
|
||||
if (-not $childTypeDirMap.ContainsKey($typeName)) { continue }
|
||||
$stateObjName = $child.InnerText.Trim()
|
||||
if (-not $stateObjName) { continue }
|
||||
$typeDir = Join-Path $configDir $childTypeDirMap[$typeName]
|
||||
$objFile = Join-Path $typeDir "$stateObjName.xml"
|
||||
if (-not (Test-Path $objFile)) { continue }
|
||||
$objText = [System.IO.File]::ReadAllText($objFile, [System.Text.Encoding]::UTF8)
|
||||
if ($objText -notmatch '<ObjectBelonging>Adopted</ObjectBelonging>') { continue }
|
||||
|
||||
foreach ($kind in $moduleKindsByType[$typeName]) {
|
||||
$stateChecked++
|
||||
$hasFile = Test-Path (Join-Path (Join-Path (Join-Path $typeDir $stateObjName) "Ext") "$kind.bsl")
|
||||
$hasFlag = $objText -match "<xr:Property>$kind</xr:Property>"
|
||||
if ($hasFile -and -not $hasFlag) {
|
||||
$stateIssues += "$typeName.$stateObjName — есть $kind.bsl, но нет <xr:PropertyState> для $kind"
|
||||
} elseif ($hasFlag -and -not $hasFile) {
|
||||
$stateIssues += "$typeName.$stateObjName — есть <xr:PropertyState> для $kind, но нет $kind.bsl"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($stateChecked -gt 0) {
|
||||
if ($stateIssues.Count -eq 0) {
|
||||
Report-OK "16. Модули заимствованных объектов: пометки расширенных свойств согласованы ($stateChecked)"
|
||||
} else {
|
||||
foreach ($issue in $stateIssues) { Report-Warn "16. $issue" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# --- Breadcrumb: controlled methods (&ИзменениеИКонтроль) drift is not checked here ---
|
||||
$extRootDir = Split-Path $resolvedPath -Parent
|
||||
$ctrlCount = 0
|
||||
+120
-1
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# cfe-validate v1.10 — Validate 1C configuration extension XML structure (CFE) (полнота GeneratedType, ТЧ из AdditionalColumns, сверка путей с -ConfigPath)
|
||||
# cfe-validate v1.13 — Validate 1C configuration extension XML structure (CFE)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
"""Validates extension Configuration.xml: root, InternalInfo, extension properties, ChildObjects, borrowed objects."""
|
||||
import sys, os, argparse, re
|
||||
@@ -71,6 +71,27 @@ CHILD_OBJECT_TYPES = [
|
||||
'BusinessProcess', 'Task', 'IntegrationService',
|
||||
]
|
||||
|
||||
# Модули заимствованных объектов: тип → виды модулей. Имя свойства в <xr:PropertyState>
|
||||
# совпадает с базовым именем файла модуля. Копия таблицы есть в cfe-borrow (навыки автономны).
|
||||
MODULE_KINDS_BY_TYPE = {
|
||||
"CommonModule": ["Module"], "HTTPService": ["Module"], "WebService": ["Module"],
|
||||
"Catalog": ["ObjectModule", "ManagerModule"], "Document": ["ObjectModule", "ManagerModule"],
|
||||
"Report": ["ObjectModule", "ManagerModule"], "DataProcessor": ["ObjectModule", "ManagerModule"],
|
||||
"ExchangePlan": ["ObjectModule", "ManagerModule"],
|
||||
"ChartOfCharacteristicTypes": ["ObjectModule", "ManagerModule"],
|
||||
"ChartOfAccounts": ["ObjectModule", "ManagerModule"],
|
||||
"ChartOfCalculationTypes": ["ObjectModule", "ManagerModule"],
|
||||
"BusinessProcess": ["ObjectModule", "ManagerModule"], "Task": ["ObjectModule", "ManagerModule"],
|
||||
"InformationRegister": ["RecordSetModule", "ManagerModule"],
|
||||
"AccumulationRegister": ["RecordSetModule", "ManagerModule"],
|
||||
"AccountingRegister": ["RecordSetModule", "ManagerModule"],
|
||||
"CalculationRegister": ["RecordSetModule", "ManagerModule"],
|
||||
"Sequence": ["RecordSetModule", "ManagerModule"],
|
||||
"Constant": ["ValueManagerModule", "ManagerModule"],
|
||||
"Enum": ["ManagerModule"], "DocumentJournal": ["ManagerModule"],
|
||||
"FilterCriterion": ["ManagerModule"],
|
||||
}
|
||||
|
||||
# Type -> directory mapping
|
||||
CHILD_TYPE_DIR_MAP = {
|
||||
'Language': 'Languages', 'Subsystem': 'Subsystems', 'StyleItem': 'StyleItems', 'Style': 'Styles',
|
||||
@@ -1141,10 +1162,108 @@ def main():
|
||||
if check14_ok:
|
||||
r.ok(f'14. Object paths vs source config: {path_check_count} checked')
|
||||
|
||||
# --- Check 15: основные роли расширения не дают прав на заимствованные объекты ---
|
||||
# Платформа: «Назначение прав доступа на заимствованные объекты основными ролями в
|
||||
# расширениях недопустимо». Роль вне <DefaultRoles> так делать вправе — проверяем только
|
||||
# основные. Ловится статически, а по симптому (отказ загрузки) причина не читается.
|
||||
default_role_nodes = cfg_node.findall('md:Properties/md:DefaultRoles/xr:Item', NS)
|
||||
if default_role_nodes:
|
||||
adopted_cache = {}
|
||||
|
||||
def is_object_adopted(type_name, obj_name):
|
||||
key = f"{type_name}.{obj_name}"
|
||||
if key in adopted_cache:
|
||||
return adopted_cache[key]
|
||||
adopted_cache[key] = False
|
||||
dir_name = CHILD_TYPE_DIR_MAP.get(type_name)
|
||||
if dir_name:
|
||||
obj_path = os.path.join(config_dir, dir_name, obj_name + '.xml')
|
||||
if os.path.isfile(obj_path):
|
||||
try:
|
||||
obj_root = etree.parse(obj_path).getroot()
|
||||
ob = obj_root.find(f'md:{type_name}/md:Properties/md:ObjectBelonging', NS)
|
||||
if ob is not None and (ob.text or '') == 'Adopted':
|
||||
adopted_cache[key] = True
|
||||
except Exception:
|
||||
pass
|
||||
return adopted_cache[key]
|
||||
|
||||
check15_ok = True
|
||||
check15_count = 0
|
||||
roles_ns = {'r': 'http://v8.1c.ru/8.2/roles'}
|
||||
for rn in default_role_nodes:
|
||||
m = re.match(r'^Role\.(.+)$', rn.text or '')
|
||||
if not m:
|
||||
continue
|
||||
def_role_name = m.group(1)
|
||||
rights_path = os.path.join(config_dir, 'Roles', def_role_name, 'Ext', 'Rights.xml')
|
||||
if not os.path.isfile(rights_path):
|
||||
continue
|
||||
try:
|
||||
rights_root = etree.parse(rights_path).getroot()
|
||||
except Exception:
|
||||
continue
|
||||
for name_node in rights_root.findall('r:object/r:name', roles_ns):
|
||||
full_name = name_node.text or ''
|
||||
segs = full_name.split('.')
|
||||
# Configuration.* — права самого расширения, не объект; заимствования там нет.
|
||||
if len(segs) < 2 or segs[0] == 'Configuration':
|
||||
continue
|
||||
check15_count += 1
|
||||
if is_object_adopted(segs[0], segs[1]):
|
||||
r.error(f"15. Роль '{def_role_name}' входит в DefaultRoles и даёт права на заимствованный "
|
||||
f"{segs[0]}.{segs[1]} ({full_name}): платформа это запрещает. "
|
||||
"Вынесите такие права в отдельную роль вне DefaultRoles.")
|
||||
check15_ok = False
|
||||
if check15_ok and check15_count > 0:
|
||||
r.ok(f'15. Основные роли: прав на заимствованные объекты нет ({check15_count} checked)')
|
||||
|
||||
if r.stopped:
|
||||
r.finalize(out_file)
|
||||
sys.exit(1)
|
||||
|
||||
# --- Check 16: модуль заимствованного объекта и пометка расширенного свойства ---
|
||||
# Свойство <xr:PropertyState> появилось в формате 2.19 (8.3.26); ниже платформа его молча
|
||||
# выбрасывает, поэтому там проверять нечего. С 2.19 состояние обязано соответствовать факту:
|
||||
# есть файл модуля — есть пометка, и наоборот. Перекос платформа принимает (проверено на
|
||||
# стенде), но выгрузка Конфигуратора так не выглядит — отсюда предупреждение, а не ошибка.
|
||||
if version_rank >= 219 and child_obj_node is not None:
|
||||
state_issues = []
|
||||
state_checked = 0
|
||||
for child in child_obj_node:
|
||||
if not isinstance(child.tag, str):
|
||||
continue
|
||||
type_name = etree.QName(child.tag).localname
|
||||
if type_name not in MODULE_KINDS_BY_TYPE or type_name not in CHILD_TYPE_DIR_MAP:
|
||||
continue
|
||||
obj_name_val = (child.text or '').strip()
|
||||
if not obj_name_val:
|
||||
continue
|
||||
type_dir = os.path.join(config_dir, CHILD_TYPE_DIR_MAP[type_name])
|
||||
obj_file = os.path.join(type_dir, f'{obj_name_val}.xml')
|
||||
if not os.path.isfile(obj_file):
|
||||
continue
|
||||
with open(obj_file, 'r', encoding='utf-8-sig') as f:
|
||||
obj_text = f.read()
|
||||
if '<ObjectBelonging>Adopted</ObjectBelonging>' not in obj_text:
|
||||
continue
|
||||
|
||||
for kind in MODULE_KINDS_BY_TYPE[type_name]:
|
||||
state_checked += 1
|
||||
has_file = os.path.isfile(os.path.join(type_dir, obj_name_val, 'Ext', f'{kind}.bsl'))
|
||||
has_flag = f'<xr:Property>{kind}</xr:Property>' in obj_text
|
||||
if has_file and not has_flag:
|
||||
state_issues.append(f'{type_name}.{obj_name_val} — есть {kind}.bsl, но нет <xr:PropertyState> для {kind}')
|
||||
elif has_flag and not has_file:
|
||||
state_issues.append(f'{type_name}.{obj_name_val} — есть <xr:PropertyState> для {kind}, но нет {kind}.bsl')
|
||||
|
||||
if state_checked > 0:
|
||||
if not state_issues:
|
||||
r.ok(f'16. Модули заимствованных объектов: пометки расширенных свойств согласованы ({state_checked})')
|
||||
else:
|
||||
for issue in state_issues:
|
||||
r.warn(f'16. {issue}')
|
||||
|
||||
# --- Breadcrumb: controlled methods (&ИзменениеИКонтроль) drift is not checked here ---
|
||||
ctrl_count = 0
|
||||
for dp, _dn, files in os.walk(config_dir):
|
||||
@@ -31,7 +31,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" <параметры>
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-create/scripts/db-create.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -59,14 +59,14 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" <п
|
||||
|
||||
```powershell
|
||||
# Создать файловую базу
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-create/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB"
|
||||
|
||||
# Создать серверную базу
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-create/scripts/db-create.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test"
|
||||
|
||||
# Создать из шаблона CF
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB" -UseTemplate "C:\Templates\config.cf"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-create/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB" -UseTemplate "C:\Templates\config.cf"
|
||||
|
||||
# Создать и добавить в список баз
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB" -AddToList -ListName "Новая база"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-create/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB" -AddToList -ListName "Новая база"
|
||||
```
|
||||
@@ -35,7 +35,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" <параметры>
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-dump-cf/scripts/db-dump-cf.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -60,11 +60,11 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" <п
|
||||
|
||||
```powershell
|
||||
# Выгрузка конфигурации (файловая база)
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\config.cf"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-dump-cf/scripts/db-dump-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\config.cf"
|
||||
|
||||
# Серверная база
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -OutputFile "config.cf"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-dump-cf/scripts/db-dump-cf.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -OutputFile "config.cf"
|
||||
|
||||
# Выгрузка расширения
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "ext.cfe" -Extension "МоёРасширение"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-dump-cf/scripts/db-dump-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "ext.cfe" -Extension "МоёРасширение"
|
||||
```
|
||||
@@ -38,7 +38,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" <параметры>
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-dump-dt/scripts/db-dump-dt.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -61,10 +61,10 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" <п
|
||||
|
||||
```powershell
|
||||
# Выгрузка ИБ (файловая база)
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\base.dt"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-dump-dt/scripts/db-dump-dt.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\base.dt"
|
||||
|
||||
# Серверная база
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -OutputFile "base.dt"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-dump-dt/scripts/db-dump-dt.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -OutputFile "base.dt"
|
||||
```
|
||||
|
||||
## Связанные навыки
|
||||
@@ -37,7 +37,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" <параметры>
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-dump-xml/scripts/db-dump-xml.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -76,17 +76,17 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" <
|
||||
|
||||
```powershell
|
||||
# Полная выгрузка (файловая база)
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-dump-xml/scripts/db-dump-xml.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
||||
|
||||
# Инкрементальная выгрузка
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Changes
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-dump-xml/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Changes
|
||||
|
||||
# Частичная выгрузка
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Partial -Objects "Справочник.Номенклатура,Документ.Заказ"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-dump-xml/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Partial -Objects "Справочник.Номенклатура,Документ.Заказ"
|
||||
|
||||
# Серверная база
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-dump-xml/scripts/db-dump-xml.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
||||
|
||||
# Выгрузка расширения
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\ext_src" -Mode Full -Extension "МоёРасширение"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-dump-xml/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\ext_src" -Mode Full -Extension "МоёРасширение"
|
||||
```
|
||||
@@ -36,7 +36,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" <параметры>
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-load-cf/scripts/db-load-cf.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -65,11 +65,11 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" <п
|
||||
|
||||
```powershell
|
||||
# Файловая база
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "C:\backup\config.cf"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-load-cf/scripts/db-load-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "C:\backup\config.cf"
|
||||
|
||||
# Серверная база
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test" -UserName "Admin" -Password "secret" -InputFile "config.cf"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-load-cf/scripts/db-load-cf.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test" -UserName "Admin" -Password "secret" -InputFile "config.cf"
|
||||
|
||||
# Загрузка расширения
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "ext.cfe" -Extension "МоёРасширение"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-load-cf/scripts/db-load-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "ext.cfe" -Extension "МоёРасширение"
|
||||
```
|
||||
@@ -52,7 +52,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" <параметры>
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-load-dt/scripts/db-load-dt.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -82,10 +82,10 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" <п
|
||||
|
||||
```powershell
|
||||
# Файловая база
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "C:\backup\base.dt"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-load-dt/scripts/db-load-dt.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "C:\backup\base.dt"
|
||||
|
||||
# Серверная база с ускорением загрузки
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test" -UserName "Admin" -Password "secret" -InputFile "base.dt" -JobsCount 4
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-load-dt/scripts/db-load-dt.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test" -UserName "Admin" -Password "secret" -InputFile "base.dt" -JobsCount 4
|
||||
```
|
||||
|
||||
## Связанные навыки
|
||||
@@ -38,7 +38,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" <параметры>
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-load-git/scripts/db-load-git.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -72,8 +72,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" <
|
||||
|
||||
```powershell
|
||||
# Все незафиксированные изменения
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\WS\cfsrc" -Source All -UpdateDB
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-load-git/scripts/db-load-git.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\WS\cfsrc" -Source All -UpdateDB
|
||||
|
||||
# Из диапазона коммитов
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\WS\cfsrc" -Source Commit -CommitRange "HEAD~3..HEAD"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-load-git/scripts/db-load-git.ps1" -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\WS\cfsrc" -Source Commit -CommitRange "HEAD~3..HEAD"
|
||||
```
|
||||
@@ -38,7 +38,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" <параметры>
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-load-xml/scripts/db-load-xml.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -90,14 +90,14 @@ Documents/Заказ/Forms/ФормаДокумента.xml
|
||||
|
||||
```powershell
|
||||
# Полная загрузка
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-load-xml/scripts/db-load-xml.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
||||
|
||||
# Частичная загрузка конкретных файлов
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Partial -Files "Catalogs/Номенклатура.xml,Catalogs/Номенклатура/Ext/ObjectModule.bsl"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-load-xml/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Partial -Files "Catalogs/Номенклатура.xml,Catalogs/Номенклатура/Ext/ObjectModule.bsl"
|
||||
|
||||
# Загрузка расширения
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\ext_src" -Mode Full -Extension "МоёРасширение"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-load-xml/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\ext_src" -Mode Full -Extension "МоёРасширение"
|
||||
|
||||
# Загрузка + обновление БД в одном запуске
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full -UpdateDB
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-load-xml/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full -UpdateDB
|
||||
```
|
||||
@@ -36,7 +36,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" <параметры>
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-run/scripts/db-run.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -64,14 +64,14 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" <пар
|
||||
|
||||
```powershell
|
||||
# Простой запуск
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-run/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
|
||||
|
||||
# Запуск с обработкой
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -Execute "C:\epf\МояОбработка.epf"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-run/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -Execute "C:\epf\МояОбработка.epf"
|
||||
|
||||
# Открыть по навигационной ссылке
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -URL "e1cib/data/Справочник.Номенклатура"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-run/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -URL "e1cib/data/Справочник.Номенклатура"
|
||||
|
||||
# Серверная база с параметром запуска
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -CParam "ЗапуститьОбновление"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-run/scripts/db-run.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -CParam "ЗапуститьОбновление"
|
||||
```
|
||||
@@ -35,7 +35,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" <параметры>
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-update/scripts/db-update.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -78,11 +78,11 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" <п
|
||||
|
||||
```powershell
|
||||
# Обычное обновление (файловая база)
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-update/scripts/db-update.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
|
||||
|
||||
# Динамическое обновление (серверная база)
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -Dynamic "+"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-update/scripts/db-update.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -Dynamic "+"
|
||||
|
||||
# Обновление расширения
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -Extension "МоёРасширение"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/db-update/scripts/db-update.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -Extension "МоёРасширение"
|
||||
```
|
||||
@@ -40,7 +40,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" <параметры>
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-build/scripts/epf-build.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -64,8 +64,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" <п
|
||||
|
||||
```powershell
|
||||
# Сборка обработки (файловая база)
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" -InfoBasePath "C:\Bases\MyDB" -SourceFile "src/МояОбработка.xml" -OutputFile "build/МояОбработка.epf"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-build/scripts/epf-build.ps1" -InfoBasePath "C:\Bases\MyDB" -SourceFile "src/МояОбработка.xml" -OutputFile "build/МояОбработка.epf"
|
||||
|
||||
# Серверная база
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -SourceFile "src/МояОбработка.xml" -OutputFile "build/МояОбработка.epf"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-build/scripts/epf-build.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -SourceFile "src/МояОбработка.xml" -OutputFile "build/МояОбработка.epf"
|
||||
```
|
||||
@@ -39,7 +39,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" <параметры>
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-dump/scripts/epf-dump.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -64,8 +64,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" <па
|
||||
|
||||
```powershell
|
||||
# Разборка обработки (файловая база)
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" -InfoBasePath "C:\Bases\MyDB" -InputFile "build/МояОбработка.epf" -OutputDir "src"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-dump/scripts/epf-dump.ps1" -InfoBasePath "C:\Bases\MyDB" -InputFile "build/МояОбработка.epf" -OutputDir "src"
|
||||
|
||||
# Серверная база
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -InputFile "build/МояОбработка.epf" -OutputDir "src"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-dump/scripts/epf-dump.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -InputFile "build/МояОбработка.epf" -OutputDir "src"
|
||||
```
|
||||
@@ -37,7 +37,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/init.ps1" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-FormatVersion "<версия>"]
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-init/scripts/init.ps1" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-FormatVersion "<версия>"]
|
||||
```
|
||||
|
||||
## Дальнейшие шаги
|
||||
@@ -24,7 +24,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-validate.ps1" -ObjectPath "src/МояОбработка"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-validate.ps1" -ObjectPath "src/МояОбработка/МояОбработка.xml"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МояОбработка"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МояОбработка/МояОбработка.xml"
|
||||
```
|
||||
|
||||
@@ -42,7 +42,7 @@ allowed-tools:
|
||||
Используй общий скрипт из epf-build:
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.ps1" <параметры>
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-build/scripts/epf-build.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -66,8 +66,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-bu
|
||||
|
||||
```powershell
|
||||
# Сборка отчёта (файловая база)
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.ps1" -InfoBasePath "C:\Bases\MyDB" -SourceFile "src/МойОтчёт.xml" -OutputFile "build/МойОтчёт.erf"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-build/scripts/epf-build.ps1" -InfoBasePath "C:\Bases\MyDB" -SourceFile "src/МойОтчёт.xml" -OutputFile "build/МойОтчёт.erf"
|
||||
|
||||
# Серверная база
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -SourceFile "src/МойОтчёт.xml" -OutputFile "build/МойОтчёт.erf"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-build/scripts/epf-build.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -SourceFile "src/МойОтчёт.xml" -OutputFile "build/МойОтчёт.erf"
|
||||
```
|
||||
@@ -41,7 +41,7 @@ allowed-tools:
|
||||
Используй общий скрипт из epf-dump:
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.ps1" <параметры>
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-dump/scripts/epf-dump.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -66,8 +66,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dum
|
||||
|
||||
```powershell
|
||||
# Разборка отчёта (файловая база)
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.ps1" -InfoBasePath "C:\Bases\MyDB" -InputFile "build/МойОтчёт.erf" -OutputDir "src"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-dump/scripts/epf-dump.ps1" -InfoBasePath "C:\Bases\MyDB" -InputFile "build/МойОтчёт.erf" -OutputDir "src"
|
||||
|
||||
# Серверная база
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -InputFile "build/МойОтчёт.erf" -OutputDir "src"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-dump/scripts/epf-dump.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -InputFile "build/МойОтчёт.erf" -OutputDir "src"
|
||||
```
|
||||
@@ -38,7 +38,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/init.ps1" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-FormatVersion "<версия>"] [-WithSKD]
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/erf-init/scripts/init.ps1" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-FormatVersion "<версия>"] [-WithSKD]
|
||||
```
|
||||
|
||||
## Дальнейшие шаги
|
||||
@@ -26,7 +26,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МойОтчёт"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МойОтчёт/МойОтчёт.xml"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МойОтчёт"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МойОтчёт/МойОтчёт.xml"
|
||||
```
|
||||
|
||||
@@ -32,7 +32,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-add.ps1" -ObjectPath "<ObjectPath>" -FormName "<FormName>" [-Purpose "<Purpose>"] [-Synonym "<Synonym>"] [-SetDefault]
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/form-add/scripts/form-add.ps1" -ObjectPath "<ObjectPath>" -FormName "<FormName>" [-Purpose "<Purpose>"] [-Synonym "<Synonym>"] [-SetDefault]
|
||||
```
|
||||
|
||||
## Purpose — назначение формы
|
||||
@@ -29,10 +29,10 @@ allowed-tools:
|
||||
|
||||
```powershell
|
||||
# Режим JSON DSL
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-compile.ps1" -JsonPath "<json>" -OutputPath "<Form.xml>"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/form-compile/scripts/form-compile.ps1" -JsonPath "<json>" -OutputPath "<Form.xml>"
|
||||
|
||||
# Режим from-object (объект и purpose выводятся из OutputPath; Document и Catalog)
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-compile.ps1" -FromObject -OutputPath "<.../TypePlural/ObjectName/Forms/FormName/Ext/Form.xml>"
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".codex/skills/form-compile/scripts/form-compile.ps1" -FromObject -OutputPath "<.../TypePlural/ObjectName/Forms/FormName/Ext/Form.xml>"
|
||||
```
|
||||
|
||||
## JSON DSL — справка
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user