diff --git a/.claude/skills/meta-edit/child-operations.md b/.claude/skills/meta-edit/child-operations.md
index 62ad8e645..4be02f942 100644
--- a/.claude/skills/meta-edit/child-operations.md
+++ b/.claude/skills/meta-edit/child-operations.md
@@ -43,6 +43,22 @@
-Operation add-column -Value "Тип: EnumRef.ТипыДокументов"
```
+## add-field (таблица внешнего источника)
+
+Поле задаётся как обычный реквизит, плюс три своих ключа: `nameInDataSource` (умолчание — имя поля),
+`readOnly`, `allowNull`. Флаги строковой формы — `readonly`, `nullable`.
+
+```json
+{ "add": { "fields": [
+ "barcode: String(20) | nullable",
+ { "name": "cost", "type": "Number(15,2)", "nameInDataSource": "cost_net", "readOnly": true }
+] } }
+```
+
+Сам внешний источник точечно не правится: и таблица (отдельный файл), и функция (узел с полным
+набором свойств) собираются `meta-compile` по описанию источника целиком. Удалить таблицу —
+`meta-remove ExternalDataSource.<Источник>.Table.<Таблица>`.
+
## add-ts
Формат: `ИмяТЧ: Реквизит1: Тип1, Реквизит2: Тип2, ...`
diff --git a/.claude/skills/meta-edit/scripts/meta-edit.ps1 b/.claude/skills/meta-edit/scripts/meta-edit.ps1
index 9d0e0b166..90511deb7 100644
--- a/.claude/skills/meta-edit/scripts/meta-edit.ps1
+++ b/.claude/skills/meta-edit/scripts/meta-edit.ps1
@@ -1,4 +1,4 @@
-# meta-edit v1.43 — Edit existing 1C metadata object XML
+# meta-edit v1.44 — Edit existing 1C metadata object XML
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
[CmdletBinding(PositionalBinding=$false)]
param(
@@ -465,6 +465,7 @@ $script:childTypeSynonyms = @{
"templates" = "templates"; "макеты" = "templates"
"commands" = "commands"; "команды" = "commands"
"properties" = "properties"; "свойства" = "properties"
+ "fields" = "fields"; "поля" = "fields"
}
# Type synonyms (from meta-compile)
@@ -955,6 +956,10 @@ function Parse-AttributeShorthand {
indexing = if ($val.indexing) { "$($val.indexing)" } else { "" }
after = if ($val.after) { "$($val.after)" } else { "" }
before = if ($val.before) { "$($val.before)" } else { "" }
+ # Поле таблицы внешнего источника (контекст eds-field).
+ nameInDataSource = if ($val.nameInDataSource) { "$($val.nameInDataSource)" } else { "" }
+ readOnly = if ($val.readOnly -eq $true) { $true } else { $false }
+ allowNull = if ($val.allowNull -eq $true) { $true } else { $false }
}
# Map flags to properties
if ($result.flags -contains "req" -and -not $result.fillChecking) {
@@ -994,6 +999,7 @@ function Parse-EnumValueShorthand {
function Get-AttributeContext {
switch ($script:objType) {
"Catalog" { return "catalog" }
+ "Table" { return "eds-field" }
"Document" { return "document" }
{ $_ -in @("InformationRegister","AccumulationRegister","AccountingRegister","CalculationRegister") } { return "register" }
{ $_ -in @("DataProcessor","Report","ExternalDataProcessor","ExternalReport") } { return "processor" }
@@ -1022,7 +1028,7 @@ $script:reservedByContext = @{
}
function Build-AttributeFragment {
- param($parsed, [string]$context, [string]$indent)
+ param($parsed, [string]$context, [string]$indent, [string]$elemTag = "Attribute")
if (-not $context) { $context = Get-AttributeContext }
@@ -1037,7 +1043,7 @@ function Build-AttributeFragment {
exit 1
}
}
- } elseif ($context -notin @("tabular", "processor-tabular") -and
+ } elseif ($context -notin @("tabular", "processor-tabular", "eds-field") -and
($script:reservedAttrNames.ContainsKey($attrName) -or ($script:reservedAttrNames.Values -contains $attrName))) {
Write-Warning "Attribute '$attrName' conflicts with a standard attribute name. This may cause errors when loading into 1C."
}
@@ -1045,7 +1051,7 @@ function Build-AttributeFragment {
$uuid = New-Guid-String
$sb = New-Object System.Text.StringBuilder
- $sb.AppendLine("$indent") | Out-Null
+ $sb.AppendLine("$indent<$elemTag uuid=`"$uuid`">") | Out-Null
$sb.AppendLine("$indent`t") | Out-Null
$sb.AppendLine("$indent`t`t$(Esc-XmlText $parsed.name)") | Out-Null
$sb.AppendLine($(Build-MLTextXml "$indent`t`t" "Synonym" $parsed.synonym)) | Out-Null
@@ -1084,22 +1090,39 @@ function Build-AttributeFragment {
if ($parsed.fillChecking) { $fillChecking = Normalize-EnumValue "FillChecking" $parsed.fillChecking }
$sb.AppendLine("$indent`t`t$fillChecking") | Out-Null
- $sb.AppendLine("$indent`t`tItems") | Out-Null
+ # Поле внешнего источника (eds-field) не имеет ChoiceFoldersAndItems и LinkByType, а ChoiceForm
+ # у него стоит ПОСЛЕ ChoiceHistoryOnInput — порядок снят с выгрузки платформы.
+ if ($context -ne "eds-field") {
+ $sb.AppendLine("$indent`t`tItems") | Out-Null
+ }
$sb.AppendLine("$indent`t`t") | Out-Null
$sb.AppendLine("$indent`t`t") | Out-Null
$sb.AppendLine("$indent`t`tAuto") | Out-Null
$sb.AppendLine("$indent`t`tAuto") | Out-Null
- $sb.AppendLine("$indent`t`t") | Out-Null
- $sb.AppendLine("$indent`t`t") | Out-Null
+ if ($context -ne "eds-field") {
+ $sb.AppendLine("$indent`t`t") | Out-Null
+ $sb.AppendLine("$indent`t`t") | Out-Null
+ }
$sb.AppendLine("$indent`t`tAuto") | Out-Null
+ if ($context -eq "eds-field") {
+ $sb.AppendLine("$indent`t`t") | Out-Null
+ $nids = if ($parsed.nameInDataSource) { "$($parsed.nameInDataSource)" } else { $parsed.name }
+ $sb.AppendLine("$indent`t`t$(Esc-XmlText $nids)") | Out-Null
+ $ro = if ($parsed.readOnly -eq $true -or $parsed.flags -contains "readonly") { "true" } else { "false" }
+ $sb.AppendLine("$indent`t`t$ro") | Out-Null
+ $an = if ($parsed.allowNull -eq $true -or $parsed.flags -contains "nullable") { "true" } else { "false" }
+ $sb.AppendLine("$indent`t`t$an") | Out-Null
+ }
+
# Use — catalog only
if ($context -eq "catalog") {
$sb.AppendLine("$indent`t`t") | Out-Null
}
# Indexing/FullTextSearch/DataHistory — not for non-stored objects (processor, processor-tabular)
- if ($context -notin @("processor", "processor-tabular")) {
+ # Поля внешнего источника: индексами чужой таблицы 1С не владеет.
+ if ($context -notin @("processor", "processor-tabular", "eds-field")) {
$indexing = "DontIndex"
if ($parsed.flags -contains "index") { $indexing = "Index" }
if ($parsed.flags -contains "indexadditional") { $indexing = "IndexWithAdditionalOrder" }
@@ -1111,7 +1134,7 @@ function Build-AttributeFragment {
}
$sb.AppendLine("$indent`t") | Out-Null
- $sb.Append("$indent") | Out-Null
+ $sb.Append("$indent$elemTag>") | Out-Null
return $sb.ToString()
}
@@ -1538,11 +1561,15 @@ $script:validChildTypes = @{
"CalculationRegister" = @("dimensions","resources","attributes","forms","templates","commands")
"DocumentJournal" = @("columns","forms","templates","commands")
"Constant" = @("forms")
+ # Внешний источник данных правится целиком через meta-compile: и таблица (отдельный файл),
+ # и функция (узел с полным набором свойств) требуют эмиттера, который живёт там.
+ "ExternalDataSource" = @()
+ "Table" = @("fields","forms","templates","commands")
}
# Canonical child order in ChildObjects
$script:childOrder = @(
- "Resource", "Dimension", "Attribute", "TabularSection",
+ "Resource", "Dimension", "Attribute", "TabularSection", "Field", "Function",
"AccountingFlag", "ExtDimensionAccountingFlag",
"EnumValue", "Column", "AddressingAttribute", "Recalculation",
"Form", "Template", "Command"
@@ -1559,6 +1586,7 @@ $script:childTypeToXmlTag = @{
"forms" = "Form"
"templates" = "Template"
"commands" = "Command"
+ "fields" = "Field"
}
# ============================================================
@@ -1904,11 +1932,15 @@ function Process-Add($addDef) {
return
}
- # Validate allowed
- $allowed = $script:validChildTypes[$script:objType]
- if ($allowed -and $childType -notin $allowed) {
- Warn "$childType not allowed for $($script:objType), skipping"
- return
+ # Validate allowed. Проверяем НАЛИЧИЕ ключа, а не истинность списка: пустой список
+ # ($script:objType без допустимых детей) трактовался как «ограничений нет», и чужой
+ # ребёнок молча записывался в объект.
+ if ($script:validChildTypes.ContainsKey($script:objType)) {
+ $allowed = $script:validChildTypes[$script:objType]
+ if ($childType -notin $allowed) {
+ Warn "$childType not allowed for $($script:objType), skipping"
+ return
+ }
}
$xmlTag = $script:childTypeToXmlTag[$childType]
@@ -1941,6 +1973,25 @@ function Process-Add($addDef) {
$existingNames[$parsed.name] = "Attribute"
}
}
+ "fields" {
+ # Поле таблицы внешнего источника: тот же парсер реквизита, свой тег и контекст.
+ foreach ($item in $items) {
+ $parsed = Parse-AttributeShorthand $item
+ if ($existingNames.ContainsKey($parsed.name)) {
+ Warn "Field '$($parsed.name)' already exists, skipping"
+ continue
+ }
+ $fragmentXml = Build-AttributeFragment $parsed "eds-field" $indent "Field"
+ $nodes = Import-Fragment $fragmentXml
+ $refNode = Find-InsertionPoint "Field" $parsed
+ foreach ($node in $nodes) {
+ Insert-BeforeElement $script:childObjectsEl $node $refNode $indent
+ }
+ Info "Added field: $($parsed.name)"
+ $script:addCount++
+ $existingNames[$parsed.name] = "Field"
+ }
+ }
"tabularSections" {
foreach ($item in $items) {
$tsName = if ($item -is [string]) { "$item" } else { "$($item.name)" }
diff --git a/.claude/skills/meta-edit/scripts/meta-edit.py b/.claude/skills/meta-edit/scripts/meta-edit.py
index 0ad834873..e3a4759c0 100644
--- a/.claude/skills/meta-edit/scripts/meta-edit.py
+++ b/.claude/skills/meta-edit/scripts/meta-edit.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# meta-edit v1.43 — Edit existing 1C metadata object XML
+# meta-edit v1.44 — Edit existing 1C metadata object XML
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -503,6 +503,7 @@ child_type_synonyms = {
"templates": "templates", "макеты": "templates",
"commands": "commands", "команды": "commands",
"properties": "properties", "свойства": "properties",
+ "fields": "fields", "поля": "fields",
}
type_synonyms = {
@@ -967,6 +968,10 @@ def parse_attribute_shorthand(val):
"indexing": normalize_enum_value("Indexing", str(val.get("indexing", ""))) if val.get("indexing") else "",
"after": str(val.get("after", "")),
"before": str(val.get("before", "")),
+ # Поле таблицы внешнего источника (контекст eds-field).
+ "nameInDataSource": str(val.get("nameInDataSource", "")),
+ "readOnly": val.get("readOnly") is True,
+ "allowNull": val.get("allowNull") is True,
}
# Map flags to properties
if "req" in result["flags"] and not result["fillChecking"]:
@@ -1002,6 +1007,8 @@ def get_attribute_context():
"""Determine attribute context from object type."""
if obj_type == "Catalog":
return "catalog"
+ if obj_type == "Table":
+ return "eds-field"
if obj_type == "Document":
return "document"
if obj_type in ("InformationRegister", "AccumulationRegister", "AccountingRegister", "CalculationRegister"):
@@ -1057,7 +1064,7 @@ RESERVED_BY_CONTEXT = {
}
-def build_attribute_fragment(parsed, context, indent):
+def build_attribute_fragment(parsed, context, indent, elem_tag="Attribute"):
"""Build XML fragment string for an Attribute element."""
if not context:
context = get_attribute_context()
@@ -1069,13 +1076,13 @@ def build_attribute_fragment(parsed, context, indent):
if attr_name.lower() in ctx_reserved:
print(f"meta-edit: имя реквизита '{attr_name}' зарезервировано стандартным реквизитом объекта '{context}'. Выберите другое имя.", file=sys.stderr)
sys.exit(1)
- elif context not in ('tabular', 'processor-tabular') and (attr_name in RESERVED_ATTR_NAMES or attr_name in RESERVED_ATTR_NAMES_RU):
+ elif context not in ('tabular', 'processor-tabular', 'eds-field') and (attr_name in RESERVED_ATTR_NAMES or attr_name in RESERVED_ATTR_NAMES_RU):
print(f"WARNING: Attribute '{attr_name}' conflicts with a standard attribute name. This may cause errors when loading into 1C.", file=sys.stderr)
uid = new_uuid()
lines = []
- lines.append(f'{indent}')
+ lines.append(f'{indent}<{elem_tag} uuid="{uid}">')
lines.append(f"{indent}\t")
lines.append(f"{indent}\t\t{esc_xml_text(parsed['name'])}")
lines.append(build_mltext_xml(f"{indent}\t\t", "Synonym", parsed["synonym"]))
@@ -1114,21 +1121,35 @@ def build_attribute_fragment(parsed, context, indent):
fill_checking = parsed["fillChecking"]
lines.append(f"{indent}\t\t{fill_checking}")
- lines.append(f"{indent}\t\tItems")
+ # Поле внешнего источника (eds-field) не имеет ChoiceFoldersAndItems и LinkByType, а ChoiceForm
+ # у него стоит ПОСЛЕ ChoiceHistoryOnInput — порядок снят с выгрузки платформы.
+ if context != "eds-field":
+ lines.append(f"{indent}\t\tItems")
lines.append(f"{indent}\t\t")
lines.append(f"{indent}\t\t")
lines.append(f"{indent}\t\tAuto")
lines.append(f"{indent}\t\tAuto")
- lines.append(f"{indent}\t\t")
- lines.append(f"{indent}\t\t")
+ if context != "eds-field":
+ lines.append(f"{indent}\t\t")
+ lines.append(f"{indent}\t\t")
lines.append(f"{indent}\t\tAuto")
+ if context == "eds-field":
+ lines.append(f"{indent}\t\t")
+ nids = parsed.get("nameInDataSource") or parsed["name"]
+ lines.append(f"{indent}\t\t{esc_xml_text(str(nids))}")
+ ro = "true" if (parsed.get("readOnly") is True or "readonly" in parsed["flags"]) else "false"
+ lines.append(f"{indent}\t\t{ro}")
+ an = "true" if (parsed.get("allowNull") is True or "nullable" in parsed["flags"]) else "false"
+ lines.append(f"{indent}\t\t{an}")
+
# Use -- catalog only
if context == "catalog":
lines.append(f"{indent}\t\t")
# Indexing/FullTextSearch/DataHistory -- not for non-stored objects
- if context not in ("processor", "processor-tabular"):
+ # Поля внешнего источника: индексами чужой таблицы 1С не владеет.
+ if context not in ("processor", "processor-tabular", "eds-field"):
indexing = "DontIndex"
if "index" in parsed["flags"]:
indexing = "Index"
@@ -1141,7 +1162,7 @@ def build_attribute_fragment(parsed, context, indent):
lines.append(f"{indent}\t\tUse")
lines.append(f"{indent}\t")
- lines.append(f"{indent}")
+ lines.append(f"{indent}{elem_tag}>")
return "\r\n".join(lines)
@@ -1530,11 +1551,15 @@ valid_child_types = {
"CalculationRegister": ["dimensions", "resources", "attributes", "forms", "templates", "commands"],
"DocumentJournal": ["columns", "forms", "templates", "commands"],
"Constant": ["forms"],
+ # Внешний источник данных правится целиком через meta-compile: и таблица (отдельный файл),
+ # и функция (узел с полным набором свойств) требуют эмиттера, который живёт там.
+ "ExternalDataSource": [],
+ "Table": ["fields", "forms", "templates", "commands"],
}
# Canonical child order in ChildObjects
child_order = [
- "Resource", "Dimension", "Attribute", "TabularSection",
+ "Resource", "Dimension", "Attribute", "TabularSection", "Field", "Function",
"AccountingFlag", "ExtDimensionAccountingFlag",
"EnumValue", "Column", "AddressingAttribute", "Recalculation",
"Form", "Template", "Command",
@@ -1551,6 +1576,7 @@ child_type_to_xml_tag = {
"forms": "Form",
"templates": "Template",
"commands": "Command",
+ "fields": "Field",
}
# ============================================================
@@ -1855,11 +1881,13 @@ def process_add(add_def):
warn(f"Unknown add child type: {raw_key}")
continue
- # Validate allowed
- allowed = valid_child_types.get(obj_type)
- if allowed and child_type not in allowed:
- warn(f"{child_type} not allowed for {obj_type}, skipping")
- continue
+ # Validate allowed. Проверяем НАЛИЧИЕ ключа, а не истинность списка: пустой список
+ # (объект без допустимых детей) трактовался как «ограничений нет», и чужой ребёнок
+ # молча записывался в объект.
+ if obj_type in valid_child_types:
+ if child_type not in valid_child_types[obj_type]:
+ warn(f"{child_type} not allowed for {obj_type}, skipping")
+ continue
xml_tag = child_type_to_xml_tag.get(child_type)
if not xml_tag:
@@ -1886,6 +1914,22 @@ def process_add(add_def):
add_count += 1
existing_names[parsed["name"]] = "Attribute"
+ elif child_type == "fields":
+ # Поле таблицы внешнего источника: тот же парсер реквизита, свой тег и контекст.
+ for item in items:
+ parsed = parse_attribute_shorthand(item)
+ if parsed["name"] in existing_names:
+ warn(f"Field '{parsed['name']}' already exists, skipping")
+ continue
+ fragment_xml = build_attribute_fragment(parsed, "eds-field", indent, "Field")
+ nodes = import_fragment(fragment_xml)
+ ref_node = find_insertion_point("Field", parsed)
+ for node in nodes:
+ insert_before_element(child_objects_el, node, ref_node, indent)
+ info(f"Added field: {parsed['name']}")
+ add_count += 1
+ existing_names[parsed["name"]] = "Field"
+
elif child_type == "tabularSections":
for item in items:
if isinstance(item, str):
diff --git a/.claude/skills/meta-remove/SKILL.md b/.claude/skills/meta-remove/SKILL.md
index 168352119..f82eb7077 100644
--- a/.claude/skills/meta-remove/SKILL.md
+++ b/.claude/skills/meta-remove/SKILL.md
@@ -24,7 +24,7 @@ allowed-tools:
| Параметр | Обязательный | Описание |
|------------|:------------:|-------------------------------------------------|
| ConfigDir | да | Корневая директория выгрузки (где Configuration.xml) |
-| Object | да | Тип и имя объекта: `Catalog.Товары`, `Document.Заказ` и т.д. |
+| Object | да | Тип и имя объекта: `Catalog.Товары`, `Document.Заказ` и т.д. Таблица внешнего источника — четырьмя частями: `ExternalDataSource.PG.Table.products` |
| DryRun | нет | Только показать что будет удалено, без изменений |
| KeepFiles | нет | Не удалять файлы, только дерегистрировать |
| Force | нет | Удалить несмотря на найденные ссылки; ссылки на формы объекта при этом очищаются |
diff --git a/.claude/skills/meta-remove/scripts/meta-remove.ps1 b/.claude/skills/meta-remove/scripts/meta-remove.ps1
index 665a51c24..fae531979 100644
--- a/.claude/skills/meta-remove/scripts/meta-remove.ps1
+++ b/.claude/skills/meta-remove/scripts/meta-remove.ps1
@@ -1,4 +1,4 @@
-# meta-remove v1.11 — Remove metadata object from 1C configuration dump
+# meta-remove v1.12 — Remove metadata object from 1C configuration dump
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
[CmdletBinding(PositionalBinding=$false)]
param(
@@ -60,6 +60,7 @@ $typePluralMap = @{
"WSReference" = "WSReferences"
"StyleItem" = "StyleItems"
"Language" = "Languages"
+ "ExternalDataSource" = "ExternalDataSources"
}
# --- Resolve paths ---
@@ -216,21 +217,47 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) {
# --- Parse object spec ---
-$parts = $Object -split "\.", 2
-if ($parts.Count -ne 2 -or -not $parts[0] -or -not $parts[1]) {
- Write-Host "[ERROR] Invalid object format '$Object'. Expected: Type.Name (e.g. Catalog.Товары)"
- exit 1
+# Таблица внешнего источника — единственный объект с четырёхчастным именем: она лежит не в
+# каталоге вида, а внутри источника, и числится в ChildObjects файла источника, не конфигурации.
+$edsSource = ""
+if ($Object -match '^ExternalDataSource\.([^.]+)\.Table\.(.+)$') {
+ $edsSource = $Matches[1]
+ $objType = "Table"
+ $objName = $Matches[2]
+} else {
+ $parts = $Object -split "\.", 2
+ if ($parts.Count -ne 2 -or -not $parts[0] -or -not $parts[1]) {
+ Write-Host "[ERROR] Invalid object format '$Object'. Expected: Type.Name (e.g. Catalog.Товары) or ExternalDataSource.Источник.Table.Таблица"
+ exit 1
+ }
+ $objType = $parts[0]
+ $objName = $parts[1]
}
-$objType = $parts[0]
-$objName = $parts[1]
-
-if (-not $typePluralMap.ContainsKey($objType)) {
- Write-Host "[ERROR] Unknown type '$objType'. Supported: $($typePluralMap.Keys -join ', ')"
- exit 1
+if ($edsSource) {
+ $typePlural = Join-Path (Join-Path "ExternalDataSources" $edsSource) "Tables"
+} else {
+ if (-not $typePluralMap.ContainsKey($objType)) {
+ Write-Host "[ERROR] Unknown type '$objType'. Supported: $($typePluralMap.Keys -join ', ')"
+ exit 1
+ }
+ $typePlural = $typePluralMap[$objType]
}
-$typePlural = $typePluralMap[$objType]
+# Реестр, где объект числится: обычно ChildObjects конфигурации, а для таблицы — файл источника.
+if ($edsSource) {
+ $registryXml = Join-Path (Join-Path $ConfigDir "ExternalDataSources") "$edsSource.xml"
+ $registryRoot = "ExternalDataSource"
+ $registryLabel = "ExternalDataSources/$edsSource.xml"
+ if (-not (Test-Path $registryXml)) {
+ Write-Host "[ERROR] Внешний источник '$edsSource' не найден: $registryLabel"
+ exit 1
+ }
+} else {
+ $registryXml = $configXml
+ $registryRoot = "Configuration"
+ $registryLabel = "Configuration.xml"
+}
Write-Host "=== meta-remove: ${objType}.${objName} ==="
Write-Host ""
@@ -304,10 +331,10 @@ if (-not $hasXml -and -not $hasDir) {
# Check if registered in Configuration.xml before proceeding
$cfgCheckDoc = New-Object System.Xml.XmlDocument
$cfgCheckDoc.PreserveWhitespace = $true
- $cfgCheckDoc.Load($configXml)
+ $cfgCheckDoc.Load($registryXml)
$cfgCheckNs = New-Object System.Xml.XmlNamespaceManager($cfgCheckDoc.NameTable)
$cfgCheckNs.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
- $cfgCheckNode = $cfgCheckDoc.DocumentElement.SelectSingleNode("md:Configuration/md:ChildObjects", $cfgCheckNs)
+ $cfgCheckNode = $cfgCheckDoc.DocumentElement.SelectSingleNode("md:$registryRoot/md:ChildObjects", $cfgCheckNs)
$registeredInCfg = $false
if ($cfgCheckNode) {
foreach ($child in @($cfgCheckNode.ChildNodes)) {
@@ -390,6 +417,18 @@ if ($ruMgr) {
# English manager = plural directory name
$searchPatterns += "$typePlural.$objName"
+# 2а) Внешний источник данных: ссылки на сам источник и на его таблицы
+if ($objType -eq "ExternalDataSource") {
+ $searchPatterns += "ExternalDataSource.$objName."
+ $searchPatterns += "ВнешниеИсточникиДанных.$objName"
+ $searchPatterns += "ExternalDataSources.$objName"
+}
+if ($edsSource) {
+ $searchPatterns += "ExternalDataSource.$edsSource.Table.$objName"
+ $searchPatterns += "ExternalDataSourceTableRef.$edsSource.$objName"
+ $searchPatterns += "ВнешниеИсточникиДанных.$edsSource.Таблицы.$objName"
+}
+
# 3) CommonModule: method calls in BSL (ModuleName.)
if ($objType -eq "CommonModule") {
$searchPatterns += "$objName."
@@ -504,22 +543,22 @@ if ($references.Count -gt 0) {
Write-Host "[OK] No references found"
}
-# --- 3. Remove from Configuration.xml ChildObjects ---
+# --- 3. Remove from registry ChildObjects (Configuration.xml или файл внешнего источника) ---
Write-Host ""
-Write-Host "--- Configuration.xml ---"
+Write-Host "--- $registryLabel ---"
$xmlDoc = New-Object System.Xml.XmlDocument
$xmlDoc.PreserveWhitespace = $true
-$xmlDoc.Load($configXml)
+$xmlDoc.Load($registryXml)
$ns = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
$ns.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
$ns.AddNamespace("v8", "http://v8.1c.ru/8.1/data/core")
-$cfgNode = $xmlDoc.DocumentElement.SelectSingleNode("md:Configuration", $ns)
+$cfgNode = $xmlDoc.DocumentElement.SelectSingleNode("md:$registryRoot", $ns)
if (-not $cfgNode) {
- Write-Host "[ERROR] Configuration element not found in Configuration.xml"
+ Write-Host "[ERROR] $registryRoot element not found in $registryLabel"
$errors++
} else {
$childObjects = $cfgNode.SelectSingleNode("md:ChildObjects", $ns)
@@ -570,10 +609,10 @@ if (-not $cfgNode) {
$xmlText = [regex]::Replace($xmlText, '(?s)||(?<=\S) />', { param($m) if ($m.Value -eq ' />') { '/>' } else { $m.Value } })
# Целевой перевод строки: стиль файла-назначения — правка наследует его (#44/#46/#47),
# новый файл получает канон выгрузки CRLF. Зеркало _detect_xml_style в py-порту.
- $targetEol = if ((Test-Path -LiteralPath $configXml) -and ([System.IO.File]::ReadAllText($configXml) -notmatch "`r`n")) { "`n" } else { "`r`n" }
+ $targetEol = if ((Test-Path -LiteralPath $registryXml) -and ([System.IO.File]::ReadAllText($registryXml) -notmatch "`r`n")) { "`n" } else { "`r`n" }
$xmlText = ($xmlText -replace "`r`n", "`n") -replace "`n", $targetEol
- [System.IO.File]::WriteAllText($configXml, $xmlText, $enc)
- Write-Host "[OK] Configuration.xml saved"
+ [System.IO.File]::WriteAllText($registryXml, $xmlText, $enc)
+ Write-Host "[OK] $registryLabel saved"
}
}
diff --git a/.claude/skills/meta-remove/scripts/meta-remove.py b/.claude/skills/meta-remove/scripts/meta-remove.py
index ab7ec5b53..4316b3232 100644
--- a/.claude/skills/meta-remove/scripts/meta-remove.py
+++ b/.claude/skills/meta-remove/scripts/meta-remove.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# meta-remove v1.11 — Remove metadata object from 1C configuration dump
+# meta-remove v1.12 — Remove metadata object from 1C configuration dump
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -250,6 +250,7 @@ TYPE_PLURAL_MAP = {
"WSReference": "WSReferences",
"StyleItem": "StyleItems",
"Language": "Languages",
+ "ExternalDataSource": "ExternalDataSources",
}
# Type -> reference type names (used in XML elements)
@@ -388,19 +389,42 @@ def main():
sys.exit(1)
# --- Parse object spec ---
- parts = args.Object.split(".", 1)
- if len(parts) != 2 or not parts[0] or not parts[1]:
- print(f"[ERROR] Invalid object format '{args.Object}'. Expected: Type.Name (e.g. Catalog.\u0422\u043e\u0432\u0430\u0440\u044b)")
- sys.exit(1)
+ # Таблица внешнего источника — единственный объект с четырёхчастным именем: она лежит не в
+ # каталоге вида, а внутри источника, и числится в ChildObjects файла источника, не конфигурации.
+ eds_source = ""
+ m_eds = re.match(r'^ExternalDataSource\.([^.]+)\.Table\.(.+)$', args.Object)
+ if m_eds:
+ eds_source = m_eds.group(1)
+ obj_type = "Table"
+ obj_name = m_eds.group(2)
+ else:
+ parts = args.Object.split(".", 1)
+ if len(parts) != 2 or not parts[0] or not parts[1]:
+ print(f"[ERROR] Invalid object format '{args.Object}'. Expected: Type.Name (e.g. Catalog.\u0422\u043e\u0432\u0430\u0440\u044b) or ExternalDataSource.\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a.Table.\u0422\u0430\u0431\u043b\u0438\u0446\u0430")
+ sys.exit(1)
+ obj_type = parts[0]
+ obj_name = parts[1]
- obj_type = parts[0]
- obj_name = parts[1]
+ if eds_source:
+ type_plural = os.path.join("ExternalDataSources", eds_source, "Tables")
+ else:
+ if obj_type not in TYPE_PLURAL_MAP:
+ print(f"[ERROR] Unknown type '{obj_type}'. Supported: {', '.join(TYPE_PLURAL_MAP.keys())}")
+ sys.exit(1)
+ type_plural = TYPE_PLURAL_MAP[obj_type]
- if obj_type not in TYPE_PLURAL_MAP:
- print(f"[ERROR] Unknown type '{obj_type}'. Supported: {', '.join(TYPE_PLURAL_MAP.keys())}")
- sys.exit(1)
-
- type_plural = TYPE_PLURAL_MAP[obj_type]
+ # Реестр, где объект числится: обычно ChildObjects конфигурации, а для таблицы — файл источника.
+ if eds_source:
+ registry_xml = os.path.join(config_dir, "ExternalDataSources", f"{eds_source}.xml")
+ registry_root = "ExternalDataSource"
+ registry_label = f"ExternalDataSources/{eds_source}.xml"
+ if not os.path.isfile(registry_xml):
+ print(f"[ERROR] \u0412\u043d\u0435\u0448\u043d\u0438\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a '{eds_source}' \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d: {registry_label}")
+ sys.exit(1)
+ else:
+ registry_xml = config_xml
+ registry_root = "Configuration"
+ registry_label = "Configuration.xml"
print(f"=== meta-remove: {obj_type}.{obj_name} ===")
print()
@@ -425,7 +449,7 @@ def main():
if not has_xml and not has_dir:
# Check if registered in Configuration.xml before proceeding
- cfg_check_tree = etree.parse(config_xml, etree.XMLParser(remove_blank_text=False))
+ cfg_check_tree = etree.parse(registry_xml, etree.XMLParser(remove_blank_text=False))
cfg_check_root = cfg_check_tree.getroot()
child_objects = cfg_check_root.find(f"{{{MD_NS}}}Configuration/{{{MD_NS}}}ChildObjects")
registered_in_cfg = False
@@ -463,6 +487,16 @@ def main():
search_patterns.append(f"{ru_mgr}.{obj_name}")
search_patterns.append(f"{type_plural}.{obj_name}")
+ # 2а) Внешний источник данных: ссылки на сам источник и на его таблицы
+ if obj_type == "ExternalDataSource":
+ search_patterns.append(f"ExternalDataSource.{obj_name}.")
+ search_patterns.append(f"\u0412\u043d\u0435\u0448\u043d\u0438\u0435\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438\u0414\u0430\u043d\u043d\u044b\u0445.{obj_name}")
+ search_patterns.append(f"ExternalDataSources.{obj_name}")
+ if eds_source:
+ search_patterns.append(f"ExternalDataSource.{eds_source}.Table.{obj_name}")
+ search_patterns.append(f"ExternalDataSourceTableRef.{eds_source}.{obj_name}")
+ search_patterns.append(f"\u0412\u043d\u0435\u0448\u043d\u0438\u0435\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438\u0414\u0430\u043d\u043d\u044b\u0445.{eds_source}.\u0422\u0430\u0431\u043b\u0438\u0446\u044b.{obj_name}")
+
# 3) CommonModule: method calls
if obj_type == "CommonModule":
search_patterns.append(f"{obj_name}.")
@@ -578,17 +612,17 @@ def main():
else:
print("[OK] No references found")
- # --- 3. Remove from Configuration.xml ChildObjects ---
+ # --- 3. Remove from registry ChildObjects (Configuration.xml или файл внешнего источника) ---
print()
- print("--- Configuration.xml ---")
+ print(f"--- {registry_label} ---")
xml_parser = etree.XMLParser(remove_blank_text=False)
- tree = etree.parse(config_xml, xml_parser)
+ tree = etree.parse(registry_xml, xml_parser)
xml_root = tree.getroot()
- cfg_node = xml_root.find(f"{{{MD_NS}}}Configuration")
+ cfg_node = xml_root.find(f"{{{MD_NS}}}{registry_root}")
if cfg_node is None:
- print("[ERROR] Configuration element not found in Configuration.xml")
+ print(f"[ERROR] {registry_root} element not found in {registry_label}")
errors += 1
else:
child_objects = cfg_node.find(f"{{{MD_NS}}}ChildObjects")
@@ -611,8 +645,8 @@ def main():
# Save Configuration.xml
if actions > 0 and not args.DryRun:
- save_xml_bom(tree, config_xml)
- print("[OK] Configuration.xml saved")
+ save_xml_bom(tree, registry_xml)
+ print(f"[OK] {registry_label} saved")
# --- 4. Remove from subsystem Content ---
print()
diff --git a/tests/skills/cases/meta-edit/eds-add-field.json b/tests/skills/cases/meta-edit/eds-add-field.json
new file mode 100644
index 000000000..def7e8713
--- /dev/null
+++ b/tests/skills/cases/meta-edit/eds-add-field.json
@@ -0,0 +1,42 @@
+{
+ "name": "Поле в таблицу внешнего источника; реквизит туда не пускают",
+ "setup": "empty-config",
+ "preRun": [
+ {
+ "script": "meta-compile/scripts/meta-compile",
+ "input": {
+ "type": "ExternalDataSource",
+ "name": "PG",
+ "tables": {
+ "products": {
+ "keyFields": ["id"],
+ "fields": ["id: Number(10,0)", "name: String(150)"]
+ }
+ }
+ },
+ "args": { "-JsonPath": "{inputFile}", "-OutputDir": "{workDir}" }
+ }
+ ],
+ "params": { "objectPath": "ExternalDataSources/PG/Tables/products.xml" },
+ "input": {
+ "add": {
+ "fields": [
+ "barcode: String(20) | nullable",
+ { "name": "cost", "type": "Number(15,2)", "nameInDataSource": "cost_net", "readOnly": true }
+ ],
+ "attributes": ["Лишний: String(10)"]
+ }
+ },
+ "expect": {
+ "stdoutContains": ["Added field: barcode", "Added field: cost", "attributes not allowed for Table"],
+ "fileContains": [
+ {
+ "file": "ExternalDataSources/PG/Tables/products.xml",
+ "text": ["cost_net", "true", ""] }
+ ]
+ }
+}
diff --git a/tests/skills/cases/meta-edit/snapshots/eds-add-field/Configuration.xml b/tests/skills/cases/meta-edit/snapshots/eds-add-field/Configuration.xml
new file mode 100644
index 000000000..da0e784ee
--- /dev/null
+++ b/tests/skills/cases/meta-edit/snapshots/eds-add-field/Configuration.xml
@@ -0,0 +1,252 @@
+
+
+
+
+
+ UUID-002
+ UUID-003
+
+
+ UUID-004
+ UUID-005
+
+
+ UUID-006
+ UUID-007
+
+
+ UUID-008
+ UUID-009
+
+
+ UUID-010
+ UUID-011
+
+
+ UUID-012
+ UUID-013
+
+
+ UUID-014
+ UUID-015
+
+
+
+ TestConfig
+
+
+ ru
+ TestConfig
+
+
+
+
+ Version8_3_24
+ ManagedApplication
+
+ PlatformApplication
+
+ Russian
+
+
+
+
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Biometrics
+ true
+
+
+ Location
+ false
+
+
+ BackgroundLocation
+ false
+
+
+ BluetoothPrinters
+ false
+
+
+ WiFiPrinters
+ false
+
+
+ Contacts
+ false
+
+
+ Calendars
+ false
+
+
+ PushNotifications
+ false
+
+
+ LocalNotifications
+ false
+
+
+ InAppPurchases
+ false
+
+
+ PersonalComputerFileExchange
+ false
+
+
+ Ads
+ false
+
+
+ NumberDialing
+ false
+
+
+ CallProcessing
+ false
+
+
+ CallLog
+ false
+
+
+ AutoSendSMS
+ false
+
+
+ ReceiveSMS
+ false
+
+
+ SMSLog
+ false
+
+
+ Camera
+ false
+
+
+ Microphone
+ false
+
+
+ MusicLibrary
+ false
+
+
+ PictureAndVideoLibraries
+ false
+
+
+ AudioPlaybackAndVibration
+ false
+
+
+ BackgroundAudioPlaybackAndVibration
+ false
+
+
+ InstallPackages
+ false
+
+
+ OSBackup
+ true
+
+
+ ApplicationUsageStatistics
+ false
+
+
+ BarcodeScanning
+ false
+
+
+ BackgroundAudioRecording
+ false
+
+
+ AllFilesAccess
+ false
+
+
+ Videoconferences
+ false
+
+
+ NFC
+ false
+
+
+ DocumentScanning
+ false
+
+
+ SpeechToText
+ false
+
+
+ Geofences
+ false
+
+
+ IncomingShareRequests
+ false
+
+
+ AllIncomingShareRequestsTypesProcessing
+ false
+
+
+
+
+
+ Normal
+
+
+ Language.Русский
+
+
+
+
+
+ Managed
+ NotAutoFree
+ DontUse
+ DontUse
+ TaxiEnableVersion8_2
+ DontUse
+ Version8_3_24
+
+
+
+ Русский
+ PG
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-edit/snapshots/eds-add-field/Ext/ClientApplicationInterface.xml b/tests/skills/cases/meta-edit/snapshots/eds-add-field/Ext/ClientApplicationInterface.xml
new file mode 100644
index 000000000..3c1161b2d
--- /dev/null
+++ b/tests/skills/cases/meta-edit/snapshots/eds-add-field/Ext/ClientApplicationInterface.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ UUID-002
+
+
+
+
+ UUID-004
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-edit/snapshots/eds-add-field/ExternalDataSources/PG.xml b/tests/skills/cases/meta-edit/snapshots/eds-add-field/ExternalDataSources/PG.xml
new file mode 100644
index 000000000..a1b89619b
--- /dev/null
+++ b/tests/skills/cases/meta-edit/snapshots/eds-add-field/ExternalDataSources/PG.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+ UUID-002
+ UUID-003
+
+
+ UUID-004
+ UUID-005
+
+
+ UUID-006
+ UUID-007
+
+
+
+ PG
+
+
+ ru
+ PG
+
+
+
+ Automatic
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-edit/snapshots/eds-add-field/ExternalDataSources/PG/Tables/products.xml b/tests/skills/cases/meta-edit/snapshots/eds-add-field/ExternalDataSources/PG/Tables/products.xml
new file mode 100644
index 000000000..10024164c
--- /dev/null
+++ b/tests/skills/cases/meta-edit/snapshots/eds-add-field/ExternalDataSources/PG/Tables/products.xml
@@ -0,0 +1,254 @@
+
+
+
+
+
+ UUID-002
+ UUID-003
+
+
+ UUID-004
+ UUID-005
+
+
+ UUID-006
+ UUID-007
+
+
+ UUID-008
+ UUID-009
+
+
+ UUID-010
+ UUID-011
+
+
+ UUID-012
+ UUID-013
+
+
+ UUID-014
+ UUID-015
+
+
+ UUID-016
+ UUID-017
+
+
+
+ products
+
+
+ ru
+ products
+
+
+
+ Table
+ products
+
+ NonobjectData
+
+ ExternalDataSource.PG.Table.products.Field.id
+
+
+
+
+
+ true
+ false
+
+ Auto
+ Begin
+ Directly
+ Auto
+
+
+
+
+
+
+
+
+
+
+
+ false
+ false
+ Auto
+
+ InDialog
+
+
+ Automatic
+
+
+
+
+ id
+
+
+ ru
+ id
+
+
+
+
+ xs:decimal
+
+ 10
+ 0
+ Any
+
+
+ false
+
+
+
+ false
+
+ false
+ false
+
+
+ false
+ 0
+ DontCheck
+
+
+ Auto
+ Auto
+ Auto
+
+ id
+ false
+ false
+
+
+
+
+ name
+
+
+ ru
+ name
+
+
+
+
+ xs:string
+
+ 150
+ Variable
+
+
+ false
+
+
+
+ false
+
+ false
+ false
+
+
+ false
+
+ DontCheck
+
+
+ Auto
+ Auto
+ Auto
+
+ name
+ false
+ false
+
+
+
+
+ barcode
+
+
+ ru
+ barcode
+
+
+
+
+ xs:string
+
+ 20
+ Variable
+
+
+ false
+
+
+
+ false
+
+ false
+ false
+
+
+ false
+
+ DontCheck
+
+
+ Auto
+ Auto
+ Auto
+
+ barcode
+ false
+ true
+
+
+
+
+ cost
+
+
+ ru
+ cost
+
+
+
+
+ xs:decimal
+
+ 15
+ 2
+ Any
+
+
+ false
+
+
+
+ false
+
+ false
+ false
+
+
+ false
+ 0
+ DontCheck
+
+
+ Auto
+ Auto
+ Auto
+
+ cost_net
+ true
+ false
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-edit/snapshots/eds-add-field/Languages/Русский.xml b/tests/skills/cases/meta-edit/snapshots/eds-add-field/Languages/Русский.xml
new file mode 100644
index 000000000..37c60d786
--- /dev/null
+++ b/tests/skills/cases/meta-edit/snapshots/eds-add-field/Languages/Русский.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ Русский
+
+
+ ru
+ Русский
+
+
+
+ ru
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-remove/eds-table.json b/tests/skills/cases/meta-remove/eds-table.json
new file mode 100644
index 000000000..253ca3ac9
--- /dev/null
+++ b/tests/skills/cases/meta-remove/eds-table.json
@@ -0,0 +1,28 @@
+{
+ "name": "Таблица внешнего источника: файл удалён, имя убрано из ChildObjects источника",
+ "preRun": [
+ {
+ "script": "meta-compile/scripts/meta-compile",
+ "input": {
+ "type": "ExternalDataSource",
+ "name": "PG",
+ "tables": {
+ "products": { "keyFields": ["id"], "fields": ["id: Number(10,0)"] },
+ "prices": ["product_id: Number(10,0)", "price: Number(15,2)"]
+ }
+ },
+ "args": { "-JsonPath": "{inputFile}", "-OutputDir": "{workDir}" }
+ }
+ ],
+ "object": "ExternalDataSource.PG.Table.prices",
+ "expect": {
+ "files": ["ExternalDataSources/PG.xml", "ExternalDataSources/PG/Tables/products.xml"],
+ "filesAbsent": ["ExternalDataSources/PG/Tables/prices.xml"],
+ "fileContains": [
+ { "file": "ExternalDataSources/PG.xml", "text": "" }
+ ],
+ "fileNotContains": [
+ { "file": "ExternalDataSources/PG.xml", "text": "" }
+ ]
+ }
+}
diff --git a/tests/skills/cases/meta-remove/snapshots/eds-table/Configuration.xml b/tests/skills/cases/meta-remove/snapshots/eds-table/Configuration.xml
new file mode 100644
index 000000000..da0e784ee
--- /dev/null
+++ b/tests/skills/cases/meta-remove/snapshots/eds-table/Configuration.xml
@@ -0,0 +1,252 @@
+
+
+
+
+
+ UUID-002
+ UUID-003
+
+
+ UUID-004
+ UUID-005
+
+
+ UUID-006
+ UUID-007
+
+
+ UUID-008
+ UUID-009
+
+
+ UUID-010
+ UUID-011
+
+
+ UUID-012
+ UUID-013
+
+
+ UUID-014
+ UUID-015
+
+
+
+ TestConfig
+
+
+ ru
+ TestConfig
+
+
+
+
+ Version8_3_24
+ ManagedApplication
+
+ PlatformApplication
+
+ Russian
+
+
+
+
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Biometrics
+ true
+
+
+ Location
+ false
+
+
+ BackgroundLocation
+ false
+
+
+ BluetoothPrinters
+ false
+
+
+ WiFiPrinters
+ false
+
+
+ Contacts
+ false
+
+
+ Calendars
+ false
+
+
+ PushNotifications
+ false
+
+
+ LocalNotifications
+ false
+
+
+ InAppPurchases
+ false
+
+
+ PersonalComputerFileExchange
+ false
+
+
+ Ads
+ false
+
+
+ NumberDialing
+ false
+
+
+ CallProcessing
+ false
+
+
+ CallLog
+ false
+
+
+ AutoSendSMS
+ false
+
+
+ ReceiveSMS
+ false
+
+
+ SMSLog
+ false
+
+
+ Camera
+ false
+
+
+ Microphone
+ false
+
+
+ MusicLibrary
+ false
+
+
+ PictureAndVideoLibraries
+ false
+
+
+ AudioPlaybackAndVibration
+ false
+
+
+ BackgroundAudioPlaybackAndVibration
+ false
+
+
+ InstallPackages
+ false
+
+
+ OSBackup
+ true
+
+
+ ApplicationUsageStatistics
+ false
+
+
+ BarcodeScanning
+ false
+
+
+ BackgroundAudioRecording
+ false
+
+
+ AllFilesAccess
+ false
+
+
+ Videoconferences
+ false
+
+
+ NFC
+ false
+
+
+ DocumentScanning
+ false
+
+
+ SpeechToText
+ false
+
+
+ Geofences
+ false
+
+
+ IncomingShareRequests
+ false
+
+
+ AllIncomingShareRequestsTypesProcessing
+ false
+
+
+
+
+
+ Normal
+
+
+ Language.Русский
+
+
+
+
+
+ Managed
+ NotAutoFree
+ DontUse
+ DontUse
+ TaxiEnableVersion8_2
+ DontUse
+ Version8_3_24
+
+
+
+ Русский
+ PG
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-remove/snapshots/eds-table/Ext/ClientApplicationInterface.xml b/tests/skills/cases/meta-remove/snapshots/eds-table/Ext/ClientApplicationInterface.xml
new file mode 100644
index 000000000..3c1161b2d
--- /dev/null
+++ b/tests/skills/cases/meta-remove/snapshots/eds-table/Ext/ClientApplicationInterface.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ UUID-002
+
+
+
+
+ UUID-004
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-remove/snapshots/eds-table/ExternalDataSources/PG.xml b/tests/skills/cases/meta-remove/snapshots/eds-table/ExternalDataSources/PG.xml
new file mode 100644
index 000000000..a1b89619b
--- /dev/null
+++ b/tests/skills/cases/meta-remove/snapshots/eds-table/ExternalDataSources/PG.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+ UUID-002
+ UUID-003
+
+
+ UUID-004
+ UUID-005
+
+
+ UUID-006
+ UUID-007
+
+
+
+ PG
+
+
+ ru
+ PG
+
+
+
+ Automatic
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-remove/snapshots/eds-table/ExternalDataSources/PG/Tables/products.xml b/tests/skills/cases/meta-remove/snapshots/eds-table/ExternalDataSources/PG/Tables/products.xml
new file mode 100644
index 000000000..205ef9363
--- /dev/null
+++ b/tests/skills/cases/meta-remove/snapshots/eds-table/ExternalDataSources/PG/Tables/products.xml
@@ -0,0 +1,130 @@
+
+
+
+
+
+ UUID-002
+ UUID-003
+
+
+ UUID-004
+ UUID-005
+
+
+ UUID-006
+ UUID-007
+
+
+ UUID-008
+ UUID-009
+
+
+ UUID-010
+ UUID-011
+
+
+ UUID-012
+ UUID-013
+
+
+ UUID-014
+ UUID-015
+
+
+ UUID-016
+ UUID-017
+
+
+
+ products
+
+
+ ru
+ products
+
+
+
+ Table
+ products
+
+ NonobjectData
+
+ ExternalDataSource.PG.Table.products.Field.id
+
+
+
+
+
+ true
+ false
+
+ Auto
+ Begin
+ Directly
+ Auto
+
+
+
+
+
+
+
+
+
+
+
+ false
+ false
+ Auto
+
+ InDialog
+
+
+ Automatic
+
+
+
+
+ id
+
+
+ ru
+ id
+
+
+
+
+ xs:decimal
+
+ 10
+ 0
+ Any
+
+
+ false
+
+
+
+ false
+
+ false
+ false
+
+
+ false
+ 0
+ DontCheck
+
+
+ Auto
+ Auto
+ Auto
+
+ id
+ false
+ false
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/skills/cases/meta-remove/snapshots/eds-table/Languages/Русский.xml b/tests/skills/cases/meta-remove/snapshots/eds-table/Languages/Русский.xml
new file mode 100644
index 000000000..37c60d786
--- /dev/null
+++ b/tests/skills/cases/meta-remove/snapshots/eds-table/Languages/Русский.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ Русский
+
+
+ ru
+ Русский
+
+
+
+ ru
+
+
+
\ No newline at end of file