diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1 index f2fac8c8..b12fe6e7 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.ps1 +++ b/.claude/skills/meta-compile/scripts/meta-compile.ps1 @@ -1,4 +1,4 @@ -# meta-compile v1.56 — Compile 1C metadata object from JSON +# meta-compile v1.57 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -468,7 +468,7 @@ $script:typeNamespaceMap = @{ $script:cfgBareTypes = @("ConstantsSet", "ReportBuilder", "FilterCriterion") $script:cfgObjectKinds = @("Catalog","Document","Enum","ChartOfAccounts","ChartOfCharacteristicTypes", "ChartOfCalculationTypes","ExchangePlan","BusinessProcess","Task","InformationRegister","AccumulationRegister", - "AccountingRegister","CalculationRegister","DataProcessor","Report","DocumentJournal","Constant","ConstantValue") + "AccountingRegister","CalculationRegister","DataProcessor","Report","DocumentJournal","Constant","ConstantValue","Sequence","Recalculation") $script:typeSynonyms["таблицазначений"] = "ValueTable" $script:typeSynonyms["деревозначений"] = "ValueTree" $script:typeSynonyms["списокзначений"] = "ValueListType" @@ -631,6 +631,18 @@ function Emit-TypeContent { X "$indentcfg:$typeStr" return } + # Голый объектный метатип (без имени) — напр. в Source подписки на событие: + # - Object/RecordSet → «любой объект категории» = TypeSet cfg: (множество); + # - Manager/List/Selection/RecordKey/RecordManager → сам тип менеджера/списка = Type cfg: (единичный). + # ConstantValueManager (голый) — исключение: множество менеджеров значений констант = TypeSet (прочие *Manager → Type). + if (($typeStr -match '^(\w+)(Object|RecordSet)$' -and $script:cfgObjectKinds -contains $Matches[1]) -or $typeStr -eq 'ConstantValueManager') { + X "$indentcfg:$typeStr" + return + } + if ($typeStr -match '^(\w+)(Manager|List|Selection|RecordKey|RecordManager)$' -and $script:cfgObjectKinds -contains $Matches[1]) { + X "$indentcfg:$typeStr" + return + } # Reference types — use local xmlns declaration for 1C compatibility if ($typeStr -match '^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|ExchangePlanRef|BusinessProcessRef|BusinessProcessRoutePointRef|TaskRef)\.(.+)$') { @@ -2640,7 +2652,7 @@ function Emit-CommonModuleProperties { X "$i$(Esc-Xml $objName)" Emit-MLText $i "Synonym" $synonym - X "$i" + if ($def.comment) { X "$i$(Esc-XmlText $def.comment)" } else { X "$i" } # Context shortcuts $context = if ($def.context) { "$($def.context)" } else { "" } @@ -2682,7 +2694,7 @@ function Emit-ScheduledJobProperties { X "$i$(Esc-Xml $objName)" Emit-MLText $i "Synonym" $synonym - X "$i" + if ($def.comment) { X "$i$(Esc-XmlText $def.comment)" } else { X "$i" } $methodName = if ($def.methodName) { "$($def.methodName)" } else { "" } # Ensure CommonModule. prefix @@ -2691,9 +2703,9 @@ function Emit-ScheduledJobProperties { } X "$i$(Esc-Xml $methodName)" - # $synonym может быть {ru,en}; здесь Description — плоская строка, берём ru-текст. - $description = if ($def.description) { "$($def.description)" } elseif ($synonym -is [string]) { $synonym } else { "" } - X "$i$(Esc-Xml $description)" + # Description — плоская строка (дефолт ПУСТО: корпус 662 пустых / 209 заданы; не подставляем синоним — иначе роундтрип рвётся). + $description = if ($def.description) { "$($def.description)" } else { "" } + if ($description) { X "$i$(Esc-XmlText $description)" } else { X "$i" } $key = if ($def.key) { "$($def.key)" } else { "" } X "$i$(Esc-Xml $key)" @@ -2716,17 +2728,15 @@ function Emit-EventSubscriptionProperties { X "$i$(Esc-Xml $objName)" Emit-MLText $i "Synonym" $synonym - X "$i" + if ($def.comment) { X "$i$(Esc-XmlText $def.comment)" } else { X "$i" } - # Source — array of v8:Type + # Source — набор типов-источников (объектные типы CatalogObject.X/DocumentObject.X/…RecordSet/…Manager → + # cfg:; ссылочные → d5p1). Единый эмиттер Emit-TypeContent (см. §cfg-типы). Прощающий ввод русских корней типа. $sources = @() if ($def.source) { $sources = @($def.source) } if ($sources.Count -gt 0) { X "$i" - foreach ($src in $sources) { - $resolved = Resolve-TypeStr "$src" - X "$i`td5p1:$resolved" - } + foreach ($src in $sources) { Emit-TypeContent "$i`t" (Resolve-TypeStr "$src") } X "$i" } else { X "$i" diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py index 4306d9fc..f9163701 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.py +++ b/.claude/skills/meta-compile/scripts/meta-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# meta-compile v1.56 — Compile 1C metadata object from JSON +# meta-compile v1.57 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -542,7 +542,7 @@ cfg_bare_types = {"ConstantsSet", "ReportBuilder", "FilterCriterion"} cfg_object_kinds = {"Catalog", "Document", "Enum", "ChartOfAccounts", "ChartOfCharacteristicTypes", "ChartOfCalculationTypes", "ExchangePlan", "BusinessProcess", "Task", "InformationRegister", "AccumulationRegister", "AccountingRegister", "CalculationRegister", "DataProcessor", "Report", - "DocumentJournal", "Constant", "ConstantValue"} + "DocumentJournal", "Constant", "ConstantValue", "Sequence", "Recalculation"} def resolve_type_str(type_str): if not type_str: @@ -660,6 +660,16 @@ def emit_type_content(indent, type_str): if m3 and m3.group(1) in cfg_object_kinds: X(f'{indent}cfg:{type_str}') return + # Голый объектный метатип (без имени): Object/RecordSet + ConstantValueManager → «любой объект категории» = TypeSet cfg:; + # прочие Manager/List/Selection → сам тип менеджера/списка = Type cfg: (напр. в Source подписки на событие). + mbs = re.match(r'^(\w+)(Object|RecordSet)$', type_str) + if (mbs and mbs.group(1) in cfg_object_kinds) or type_str == 'ConstantValueManager': + X(f'{indent}cfg:{type_str}') + return + mbt = re.match(r'^(\w+)(Manager|List|Selection|RecordKey|RecordManager)$', type_str) + if mbt and mbt.group(1) in cfg_object_kinds: + X(f'{indent}cfg:{type_str}') + return # Reference types — use local xmlns declaration for 1C compatibility m = re.match(r'^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|ExchangePlanRef|BusinessProcessRef|BusinessProcessRoutePointRef|TaskRef)\.(.+)$', type_str) @@ -2648,7 +2658,10 @@ def emit_common_module_properties(indent): i = indent X(f'{i}{esc_xml(obj_name)}') emit_mltext(i, 'Synonym', synonym) - X(f'{i}') + if defn.get('comment'): + X(f'{i}{esc_xml_text(str(defn["comment"]))}') + else: + X(f'{i}') context = str(defn['context']) if defn.get('context') else '' global_val = 'true' if defn.get('global') is True else 'false' server = 'false' @@ -2692,15 +2705,21 @@ def emit_scheduled_job_properties(indent): i = indent X(f'{i}{esc_xml(obj_name)}') emit_mltext(i, 'Synonym', synonym) - X(f'{i}') + if defn.get('comment'): + X(f'{i}{esc_xml_text(str(defn["comment"]))}') + else: + X(f'{i}') method_name = str(defn['methodName']) if defn.get('methodName') else '' # Ensure CommonModule. prefix if method_name and not method_name.startswith('CommonModule.'): method_name = f'CommonModule.{method_name}' X(f'{i}{esc_xml(method_name)}') - # synonym может быть {ru,en}; Description — плоская строка, берём ru-текст. - description = str(defn['description']) if defn.get('description') else (synonym if isinstance(synonym, str) else '') - X(f'{i}{esc_xml(description)}') + # Description — плоская строка (дефолт ПУСТО, не синоним — иначе роундтрип рвётся). + description = str(defn['description']) if defn.get('description') else '' + if description: + X(f'{i}{esc_xml_text(description)}') + else: + X(f'{i}') key = str(defn['key']) if defn.get('key') else '' X(f'{i}{esc_xml(key)}') use = 'true' if defn.get('use') is True else 'false' @@ -2716,13 +2735,15 @@ def emit_event_subscription_properties(indent): i = indent X(f'{i}{esc_xml(obj_name)}') emit_mltext(i, 'Synonym', synonym) - X(f'{i}') + if defn.get('comment'): + X(f'{i}{esc_xml_text(str(defn["comment"]))}') + else: + X(f'{i}') sources = list(defn.get('source', [])) if sources: X(f'{i}') for src in sources: - resolved = resolve_type_str(str(src)) - X(f'{i}\td5p1:{resolved}') + emit_type_content(f'{i}\t', resolve_type_str(str(src))) X(f'{i}') else: X(f'{i}') diff --git a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 index 1e1e3a63..d6d32140 100644 --- a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 +++ b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 @@ -1,4 +1,4 @@ -# meta-decompile v0.47 — XML объекта метаданных 1С → JSON-черновик формата meta-compile +# meta-decompile v0.48 — XML объекта метаданных 1С → JSON-черновик формата meta-compile # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # # Поддержаны: Catalog, ExchangePlan, ChartOfCharacteristicTypes, ChartOfAccounts, ChartOfCalculationTypes, Document, @@ -92,8 +92,8 @@ foreach ($c in $rootEl.ChildNodes) { if ($c.NodeType -eq 'Element') { $objNode = if (-not $objNode) { [Console]::Error.WriteLine("meta-decompile: пустой MetaDataObject"); exit 3 } $objType = $objNode.LocalName -if ($objType -notin @('Catalog', 'ExchangePlan', 'ChartOfCharacteristicTypes', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Document', 'InformationRegister', 'AccumulationRegister', 'AccountingRegister', 'CalculationRegister', 'BusinessProcess', 'Task', 'Enum', 'Report', 'DataProcessor', 'Constant', 'DefinedType', 'FunctionalOption', 'DocumentJournal', 'Sequence', 'FilterCriterion', 'DocumentNumerator', 'SettingsStorage')) { - [Console]::Error.WriteLine("meta-decompile: тип '$objType' пока не поддержан (…, Sequence, FilterCriterion, DocumentNumerator, SettingsStorage)"); exit 3 +if ($objType -notin @('Catalog', 'ExchangePlan', 'ChartOfCharacteristicTypes', 'ChartOfAccounts', 'ChartOfCalculationTypes', 'Document', 'InformationRegister', 'AccumulationRegister', 'AccountingRegister', 'CalculationRegister', 'BusinessProcess', 'Task', 'Enum', 'Report', 'DataProcessor', 'Constant', 'DefinedType', 'FunctionalOption', 'DocumentJournal', 'Sequence', 'FilterCriterion', 'DocumentNumerator', 'SettingsStorage', 'CommonModule', 'EventSubscription', 'ScheduledJob')) { + [Console]::Error.WriteLine("meta-decompile: тип '$objType' пока не поддержан (…, CommonModule, EventSubscription, ScheduledJob)"); exit 3 } $props = $objNode.SelectSingleNode('md:Properties', $nsm) @@ -656,6 +656,38 @@ if ($objType -eq 'SettingsStorage') { $fv = P $fp[0]; if ($fv) { $dsl[$fp[1]] = $fv } } } +# CommonModule — общий модуль: флаги контекста компиляции + повторное использование значений (тело .bsl вне скоупа). +if ($objType -eq 'CommonModule') { + Add-BoolProp 'global' 'Global' $false + Add-BoolProp 'clientManagedApplication' 'ClientManagedApplication' $false + Add-BoolProp 'server' 'Server' $false + Add-BoolProp 'externalConnection' 'ExternalConnection' $false + Add-BoolProp 'clientOrdinaryApplication' 'ClientOrdinaryApplication' $false + Add-BoolProp 'serverCall' 'ServerCall' $false + Add-BoolProp 'privileged' 'Privileged' $false + Add-EnumProp 'returnValuesReuse' 'ReturnValuesReuse' 'DontUse' +} +# EventSubscription — подписка на событие: источники (набор типов), событие, обработчик. +if ($objType -eq 'EventSubscription') { + $srcNode = $props.SelectSingleNode('md:Source', $nsm) + if ($srcNode) { + # Источник — набор v8:Type (конкретный CatalogObject.X) И/ИЛИ v8:TypeSet (голый метатип ExchangePlanObject). + $srcTypes = @($srcNode.SelectNodes('v8:Type|v8:TypeSet', $nsm) | ForEach-Object { Strip-NsPrefix $_.InnerText.Trim() }) + if ($srcTypes.Count -gt 0) { $dsl['source'] = [System.Collections.ArrayList]@($srcTypes) } + } + Add-EnumProp 'event' 'Event' 'BeforeWrite' + $h = P 'Handler'; if ($h) { $dsl['handler'] = $h } +} +# ScheduledJob — регламентное задание: метод, ключ, флаги, рестарт. +if ($objType -eq 'ScheduledJob') { + $mn = P 'MethodName'; if ($mn) { $dsl['methodName'] = $mn } + $descr = P 'Description'; if ($descr) { $dsl['description'] = $descr } + $k = P 'Key'; if ($k) { $dsl['key'] = $k } + Add-BoolProp 'use' 'Use' $false + Add-BoolProp 'predefined' 'Predefined' $false + Add-IntProp 'restartCountOnFailure' 'RestartCountOnFailure' 3 + Add-IntProp 'restartIntervalOnFailure' 'RestartIntervalOnFailure' 10 +} # Constant — богатый одиночный реквизит: Type + свойства значения (как у реквизита) + object-уровень. if ($objType -eq 'Constant') { $vt = Get-TypeShorthand ($props.SelectSingleNode('md:Type', $nsm)) diff --git a/tests/skills/cases/meta-compile/event-subscription-sources.json b/tests/skills/cases/meta-compile/event-subscription-sources.json new file mode 100644 index 00000000..ee4e4811 --- /dev/null +++ b/tests/skills/cases/meta-compile/event-subscription-sources.json @@ -0,0 +1,21 @@ +{ + "name": "Подписка на событие — смешанные источники (Type/TypeSet)", + "input": { + "type": "EventSubscription", + "name": "МоиОбработчики", + "source": [ + "CatalogObject.Номенклатура", + "DocumentObject", + "DocumentManager", + "ConstantValueManager", + "InformationRegisterRecordSet" + ], + "event": "OnWrite", + "handler": "ОбработкаСобытий.Обработать" + }, + "validatePath": "EventSubscriptions/МоиОбработчики", + "skipValidation": true, + "expect": { + "files": ["EventSubscriptions/МоиОбработчики.xml"] + } +} diff --git a/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/Configuration.xml b/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/Configuration.xml new file mode 100644 index 00000000..c66cc840 --- /dev/null +++ b/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/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 + + + + Русский + МоиОбработчики + + + \ No newline at end of file diff --git a/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/EventSubscriptions/МоиОбработчики.xml b/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/EventSubscriptions/МоиОбработчики.xml new file mode 100644 index 00000000..211e7f56 --- /dev/null +++ b/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/EventSubscriptions/МоиОбработчики.xml @@ -0,0 +1,24 @@ + + + + + МоиОбработчики + + + ru + Мои обработчики + + + + + cfg:CatalogObject.Номенклатура + cfg:DocumentObject + cfg:DocumentManager + cfg:ConstantValueManager + cfg:InformationRegisterRecordSet + + OnWrite + CommonModule.ОбработкаСобытий.Обработать + + + diff --git a/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/Ext/ClientApplicationInterface.xml b/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/Ext/ClientApplicationInterface.xml new file mode 100644 index 00000000..3c1161b2 --- /dev/null +++ b/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/Ext/ClientApplicationInterface.xml @@ -0,0 +1,18 @@ + + + + + UUID-002 + + + + + UUID-004 + + + + + + + + \ No newline at end of file diff --git a/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/Languages/Русский.xml b/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/Languages/Русский.xml new file mode 100644 index 00000000..37c60d78 --- /dev/null +++ b/tests/skills/cases/meta-compile/snapshots/event-subscription-sources/Languages/Русский.xml @@ -0,0 +1,16 @@ + + + + + Русский + + + ru + Русский + + + + ru + + + \ No newline at end of file diff --git a/tests/skills/cases/meta-compile/snapshots/event-subscription/EventSubscriptions/ПриЗаписиДокумента.xml b/tests/skills/cases/meta-compile/snapshots/event-subscription/EventSubscriptions/ПриЗаписиДокумента.xml index c643a80f..f7f3feb7 100644 --- a/tests/skills/cases/meta-compile/snapshots/event-subscription/EventSubscriptions/ПриЗаписиДокумента.xml +++ b/tests/skills/cases/meta-compile/snapshots/event-subscription/EventSubscriptions/ПриЗаписиДокумента.xml @@ -11,7 +11,7 @@ - d5p1:DocumentObject.ПриходнаяНакладная + cfg:DocumentObject.ПриходнаяНакладная BeforeWrite CommonModule.ОбработкаСобытий.ПриЗаписиДокумента diff --git a/tests/skills/cases/meta-compile/snapshots/scheduled-job/ScheduledJobs/ОбменДанными.xml b/tests/skills/cases/meta-compile/snapshots/scheduled-job/ScheduledJobs/ОбменДанными.xml index c9714ef4..acc206d9 100644 --- a/tests/skills/cases/meta-compile/snapshots/scheduled-job/ScheduledJobs/ОбменДанными.xml +++ b/tests/skills/cases/meta-compile/snapshots/scheduled-job/ScheduledJobs/ОбменДанными.xml @@ -11,7 +11,7 @@ CommonModule.ОбменДаннымиСервер.Выполнить - Обмен данными + false false