@yartsun/chat-widget-types 1.0.2 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +214 -115
  2. package/dist/config.types.d.ts +111 -44
  3. package/dist/config.types.d.ts.map +1 -1
  4. package/dist/config.types.js +2 -67
  5. package/dist/config.types.js.map +1 -1
  6. package/dist/index.d.ts +6 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +5 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/migration/commands.d.ts +59 -0
  11. package/dist/migration/commands.d.ts.map +1 -0
  12. package/dist/migration/commands.js +286 -0
  13. package/dist/migration/commands.js.map +1 -0
  14. package/dist/migration/examples.d.ts +198 -0
  15. package/dist/migration/examples.d.ts.map +1 -0
  16. package/dist/migration/examples.js +439 -0
  17. package/dist/migration/examples.js.map +1 -0
  18. package/dist/migration/facade.d.ts +85 -0
  19. package/dist/migration/facade.d.ts.map +1 -0
  20. package/dist/migration/facade.js +168 -0
  21. package/dist/migration/facade.js.map +1 -0
  22. package/dist/migration/migrator.d.ts +49 -0
  23. package/dist/migration/migrator.d.ts.map +1 -0
  24. package/dist/migration/migrator.js +245 -0
  25. package/dist/migration/migrator.js.map +1 -0
  26. package/dist/migration/strategies.d.ts +85 -0
  27. package/dist/migration/strategies.d.ts.map +1 -0
  28. package/dist/migration/strategies.js +217 -0
  29. package/dist/migration/strategies.js.map +1 -0
  30. package/dist/migration/types.d.ts +196 -0
  31. package/dist/migration/types.d.ts.map +1 -0
  32. package/dist/migration/types.js +5 -0
  33. package/dist/migration/types.js.map +1 -0
  34. package/dist/utils.d.ts +1 -11
  35. package/dist/utils.d.ts.map +1 -1
  36. package/dist/utils.js +3 -127
  37. package/dist/utils.js.map +1 -1
  38. package/package.json +13 -4
  39. package/src/config.types.ts +132 -118
  40. package/src/index.ts +26 -0
  41. package/src/migration/commands.ts +314 -0
  42. package/src/migration/examples.ts +471 -0
  43. package/src/migration/facade.ts +196 -0
  44. package/src/migration/migrator.ts +361 -0
  45. package/src/migration/strategies.ts +249 -0
  46. package/src/migration/types.ts +182 -0
  47. package/src/utils.ts +3 -143
@@ -0,0 +1,361 @@
1
+ /**
2
+ * Основной класс мигратора конфигураций виджета чата
3
+ */
4
+
5
+ import {
6
+ MigrationResult,
7
+ MigrationContext,
8
+ MigrationOptions,
9
+ MigrationReport,
10
+ MigrationLogger,
11
+ ConfigVersion
12
+ } from './types'
13
+ import { WidgetConfig } from '../config.types'
14
+ import { getStrategiesForMigration } from './strategies'
15
+ import { DefaultVersionDetector, CommandFactory } from './commands'
16
+
17
+ /** Дефолтный логгер для миграции */
18
+ export class DefaultMigrationLogger implements MigrationLogger {
19
+ constructor(private verbose: boolean = false) {}
20
+
21
+ info(message: string, context?: any): void {
22
+ if (this.verbose) {
23
+ console.log(`[INFO] ${message}`, context ? JSON.stringify(context, null, 2) : '')
24
+ }
25
+ }
26
+
27
+ warn(message: string, context?: any): void {
28
+ console.warn(`[WARN] ${message}`, context ? JSON.stringify(context, null, 2) : '')
29
+ }
30
+
31
+ error(message: string, context?: any): void {
32
+ console.error(`[ERROR] ${message}`, context ? JSON.stringify(context, null, 2) : '')
33
+ }
34
+
35
+ debug(message: string, context?: any): void {
36
+ if (this.verbose) {
37
+ console.debug(`[DEBUG] ${message}`, context ? JSON.stringify(context, null, 2) : '')
38
+ }
39
+ }
40
+ }
41
+
42
+ /** Основной класс мигратора */
43
+ export class ConfigMigrator {
44
+ private logger: MigrationLogger
45
+ private versionDetector: DefaultVersionDetector
46
+
47
+ constructor(logger?: MigrationLogger) {
48
+ this.logger = logger || new DefaultMigrationLogger()
49
+ this.versionDetector = new DefaultVersionDetector()
50
+ }
51
+
52
+ /**
53
+ * Выполнить миграцию конфигурации
54
+ */
55
+ async migrate<T = WidgetConfig>(
56
+ config: any,
57
+ targetVersion: ConfigVersion,
58
+ options: MigrationOptions = {}
59
+ ): Promise<MigrationResult<T>> {
60
+ const startTime = Date.now()
61
+ this.logger.info(`Начинаем миграцию к версии ${targetVersion}`)
62
+
63
+ try {
64
+ // Детекция текущей версии
65
+ const currentVersion = this.versionDetector.detect(config)
66
+ if (!currentVersion) {
67
+ return this.createErrorResult('Не удалось определить версию исходной конфигурации', startTime)
68
+ }
69
+
70
+ this.logger.info(`Определена исходная версия: ${currentVersion}`)
71
+
72
+ // Проверяем, нужна ли миграция
73
+ if (currentVersion === targetVersion) {
74
+ this.logger.info('Конфигурация уже соответствует целевой версии')
75
+ return this.createSuccessResult(config as T, currentVersion, targetVersion, [], startTime)
76
+ }
77
+
78
+ // Создаем план миграции
79
+ const migrationPath = this.buildMigrationPath(currentVersion, targetVersion)
80
+ if (migrationPath.length === 0) {
81
+ return this.createErrorResult(
82
+ `Не найден путь миграции с ${currentVersion} на ${targetVersion}`,
83
+ startTime
84
+ )
85
+ }
86
+
87
+ this.logger.info(`План миграции: ${migrationPath.map(step => `${step.from} -> ${step.to}`).join(' -> ')}`)
88
+
89
+ // Выполняем миграцию по шагам
90
+ let currentConfig = config
91
+ const appliedStrategies: string[] = []
92
+ const allWarnings: string[] = []
93
+
94
+ for (const step of migrationPath) {
95
+ const stepResult = await this.executeStep(currentConfig, step.from, step.to, options)
96
+
97
+ if (!stepResult.success) {
98
+ return this.createErrorResult(
99
+ `Ошибка на шаге ${step.from} -> ${step.to}: ${stepResult.errors.join(', ')}`,
100
+ startTime,
101
+ stepResult.errors
102
+ )
103
+ }
104
+
105
+ currentConfig = stepResult.data
106
+ appliedStrategies.push(...stepResult.appliedStrategies)
107
+ allWarnings.push(...stepResult.warnings)
108
+ }
109
+
110
+ // Финальная валидация
111
+ const validateCommand = CommandFactory.createCommand('ValidateConfig')
112
+ if (validateCommand) {
113
+ const validationResult = validateCommand.execute(currentConfig, { version: targetVersion })
114
+ if (!validationResult.success && options.strict) {
115
+ return this.createErrorResult(
116
+ `Валидация не прошла: ${validationResult.errors.join(', ')}`,
117
+ startTime,
118
+ validationResult.errors
119
+ )
120
+ }
121
+ allWarnings.push(...validationResult.warnings)
122
+ }
123
+
124
+ this.logger.info('Миграция успешно завершена')
125
+ return this.createSuccessResult(
126
+ currentConfig as T,
127
+ currentVersion,
128
+ targetVersion,
129
+ appliedStrategies,
130
+ startTime,
131
+ allWarnings
132
+ )
133
+
134
+ } catch (error) {
135
+ this.logger.error('Критическая ошибка при миграции', error)
136
+ return this.createErrorResult(`Критическая ошибка: ${error}`, startTime)
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Получить отчет о возможной миграции без её выполнения
142
+ */
143
+ async dryRun(
144
+ config: any,
145
+ targetVersion: ConfigVersion,
146
+ _options: MigrationOptions = {}
147
+ ): Promise<MigrationReport> {
148
+ const startTime = Date.now()
149
+
150
+ try {
151
+ const currentVersion = this.versionDetector.detect(config)
152
+ if (!currentVersion) {
153
+ return this.createFailedReport(startTime, 'unknown', targetVersion, 'Не удалось определить версию')
154
+ }
155
+
156
+ const migrationPath = this.buildMigrationPath(currentVersion, targetVersion)
157
+ const strategies = migrationPath.flatMap(step =>
158
+ getStrategiesForMigration(step.from, step.to)
159
+ )
160
+
161
+ return {
162
+ timestamp: new Date(),
163
+ fromVersion: currentVersion,
164
+ toVersion: targetVersion,
165
+ success: true,
166
+ duration: Date.now() - startTime,
167
+ appliedStrategies: strategies.map(strategy => ({
168
+ name: strategy.name,
169
+ success: true,
170
+ errors: [],
171
+ warnings: []
172
+ })),
173
+ totalErrors: 0,
174
+ totalWarnings: 0,
175
+ summary: `Будет применено ${strategies.length} стратегий для миграции с ${currentVersion} на ${targetVersion}`
176
+ }
177
+ } catch (error) {
178
+ return this.createFailedReport(startTime, 'unknown', targetVersion, `Ошибка: ${error}`)
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Выполнить один шаг миграции
184
+ */
185
+ private async executeStep(
186
+ config: any,
187
+ fromVersion: ConfigVersion,
188
+ toVersion: ConfigVersion,
189
+ options: MigrationOptions
190
+ ): Promise<MigrationResult<any>> {
191
+ const startTime = Date.now()
192
+
193
+ this.logger.info(`Выполняем шаг: ${fromVersion} -> ${toVersion}`)
194
+
195
+ // Получаем стратегии для этого шага
196
+ let strategies = getStrategiesForMigration(fromVersion, toVersion)
197
+
198
+ // Фильтруем стратегии согласно опциям
199
+ if (options.onlyStrategies?.length) {
200
+ strategies = strategies.filter(s => options.onlyStrategies!.includes(s.name))
201
+ }
202
+ if (options.excludeStrategies?.length) {
203
+ strategies = strategies.filter(s => !options.excludeStrategies!.includes(s.name))
204
+ }
205
+
206
+ if (strategies.length === 0) {
207
+ return this.createErrorResult(
208
+ `Не найдено стратегий для миграции ${fromVersion} -> ${toVersion}`,
209
+ startTime
210
+ )
211
+ }
212
+
213
+ const context: MigrationContext = {
214
+ fromVersion,
215
+ toVersion,
216
+ config,
217
+ options
218
+ }
219
+
220
+ let currentConfig = { ...config }
221
+ const appliedStrategies: string[] = []
222
+ const allErrors: string[] = []
223
+ const allWarnings: string[] = []
224
+
225
+ // Применяем каждую стратегию
226
+ for (const strategy of strategies) {
227
+ this.logger.debug(`Применяем стратегию: ${strategy.name}`)
228
+
229
+ if (!strategy.canApply({ ...context, config: currentConfig })) {
230
+ this.logger.debug(`Стратегия ${strategy.name} не применима, пропускаем`)
231
+ continue
232
+ }
233
+
234
+ const result = strategy.apply({ ...context, config: currentConfig })
235
+
236
+ if (!result.success) {
237
+ this.logger.error(`Стратегия ${strategy.name} завершилась с ошибкой`, result.errors)
238
+ allErrors.push(...result.errors)
239
+
240
+ if (options.strict) {
241
+ return this.createErrorResult(
242
+ `Стратегия ${strategy.name} завершилась с ошибкой: ${result.errors.join(', ')}`,
243
+ startTime,
244
+ allErrors
245
+ )
246
+ }
247
+ } else {
248
+ if (result.modified && result.data) {
249
+ currentConfig = result.data
250
+ }
251
+ appliedStrategies.push(strategy.name)
252
+ allWarnings.push(...result.warnings)
253
+ this.logger.debug(`Стратегия ${strategy.name} успешно применена`)
254
+ }
255
+ }
256
+
257
+ return this.createSuccessResult(
258
+ currentConfig,
259
+ fromVersion,
260
+ toVersion,
261
+ appliedStrategies,
262
+ startTime,
263
+ allWarnings,
264
+ allErrors
265
+ )
266
+ }
267
+
268
+ /**
269
+ * Построить путь миграции между версиями
270
+ */
271
+ private buildMigrationPath(from: ConfigVersion, to: ConfigVersion): Array<{from: ConfigVersion, to: ConfigVersion}> {
272
+ // Простая логика для последовательной миграции
273
+ // В будущем можно расширить для более сложных сценариев
274
+
275
+ const versions: ConfigVersion[] = ['1.0', '2.0', '3.0']
276
+ const fromIndex = versions.indexOf(from)
277
+ const toIndex = versions.indexOf(to)
278
+
279
+ if (fromIndex === -1 || toIndex === -1) {
280
+ return []
281
+ }
282
+
283
+ const path: Array<{from: ConfigVersion, to: ConfigVersion}> = []
284
+
285
+ if (fromIndex < toIndex) {
286
+ // Прямая миграция (вперед)
287
+ for (let i = fromIndex; i < toIndex; i++) {
288
+ path.push({ from: versions[i], to: versions[i + 1] })
289
+ }
290
+ } else if (fromIndex > toIndex) {
291
+ // Обратная миграция (назад) - пока не поддерживается
292
+ // В будущем можно добавить стратегии downgrade
293
+ return []
294
+ }
295
+
296
+ return path
297
+ }
298
+
299
+ /**
300
+ * Создать успешный результат миграции
301
+ */
302
+ private createSuccessResult<T>(
303
+ data: T,
304
+ fromVersion: ConfigVersion,
305
+ toVersion: ConfigVersion,
306
+ appliedStrategies: string[],
307
+ _startTime: number,
308
+ warnings: string[] = [],
309
+ errors: string[] = []
310
+ ): MigrationResult<T> {
311
+ return {
312
+ success: true,
313
+ data,
314
+ errors,
315
+ warnings,
316
+ fromVersion,
317
+ toVersion,
318
+ appliedStrategies
319
+ }
320
+ }
321
+
322
+ /**
323
+ * Создать результат с ошибкой
324
+ */
325
+ private createErrorResult<T = any>(
326
+ message: string,
327
+ _startTime: number,
328
+ errors: string[] = []
329
+ ): MigrationResult<T> {
330
+ return {
331
+ success: false,
332
+ errors: [message, ...errors],
333
+ warnings: [],
334
+ fromVersion: 'unknown' as any,
335
+ toVersion: 'unknown' as any,
336
+ appliedStrategies: []
337
+ }
338
+ }
339
+
340
+ /**
341
+ * Создать неудачный отчет
342
+ */
343
+ private createFailedReport(
344
+ _startTime: number,
345
+ fromVersion: ConfigVersion | 'unknown',
346
+ toVersion: ConfigVersion,
347
+ message: string
348
+ ): MigrationReport {
349
+ return {
350
+ timestamp: new Date(),
351
+ fromVersion: fromVersion as ConfigVersion,
352
+ toVersion,
353
+ success: false,
354
+ duration: Date.now() - _startTime,
355
+ appliedStrategies: [],
356
+ totalErrors: 1,
357
+ totalWarnings: 0,
358
+ summary: message
359
+ }
360
+ }
361
+ }
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Стратегии миграции конфигураций виджета чата
3
+ */
4
+
5
+ import { DEFAULT_CONFIG } from '../config.types'
6
+ import {
7
+ MigrationStrategy,
8
+ MigrationContext,
9
+ MigrationStepResult,
10
+ ConfigV1
11
+ } from './types'
12
+
13
+ /** Базовый класс для стратегий миграции */
14
+ export abstract class BaseMigrationStrategy implements MigrationStrategy {
15
+ abstract name: string
16
+ abstract description: string
17
+ abstract appliesTo: { from: any; to: any }
18
+
19
+ canApply(context: MigrationContext): boolean {
20
+ return context.fromVersion === this.appliesTo.from &&
21
+ context.toVersion === this.appliesTo.to
22
+ }
23
+
24
+ abstract apply(context: MigrationContext): MigrationStepResult
25
+
26
+ rollback?(_context: MigrationContext): MigrationStepResult {
27
+ return {
28
+ success: false,
29
+ errors: [`Rollback not implemented for strategy: ${this.name}`],
30
+ warnings: [],
31
+ modified: false
32
+ }
33
+ }
34
+
35
+ protected createSuccessResult(data: any, warnings: string[] = []): MigrationStepResult {
36
+ return {
37
+ success: true,
38
+ data,
39
+ errors: [],
40
+ warnings,
41
+ modified: true
42
+ }
43
+ }
44
+
45
+ protected createErrorResult(errors: string[], data?: any): MigrationStepResult {
46
+ return {
47
+ success: false,
48
+ data,
49
+ errors,
50
+ warnings: [],
51
+ modified: false
52
+ }
53
+ }
54
+ }
55
+
56
+ /** Стратегия добавления новых полей в settings для V1->V2 */
57
+ export class AddSettingsFieldsV1toV2Strategy extends BaseMigrationStrategy {
58
+ name = 'AddSettingsFieldsV1toV2'
59
+ description = 'Добавляет новые поля loader, buttonStyle, buttonType в settings'
60
+ appliesTo = { from: '1.0' as const, to: '2.0' as const }
61
+
62
+ apply(context: MigrationContext): MigrationStepResult {
63
+ try {
64
+ const config = { ...context.config } as ConfigV1
65
+ const warnings: string[] = []
66
+
67
+ // Добавляем новые поля в settings
68
+ const newSettings = {
69
+ ...config.settings,
70
+ loader: DEFAULT_CONFIG.settings.loader, // 'dots'
71
+ }
72
+
73
+ warnings.push(`Добавлены поля loader: '${newSettings.loader}'`)
74
+
75
+ return this.createSuccessResult(
76
+ { ...config, settings: newSettings },
77
+ warnings
78
+ )
79
+ } catch (error) {
80
+ return this.createErrorResult([`Ошибка при добавлении полей settings: ${error}`])
81
+ }
82
+ }
83
+ }
84
+
85
+ /** Стратегия добавления chipStyle в top.params для V1->V2 */
86
+ export class AddChipStyleV1toV2Strategy extends BaseMigrationStrategy {
87
+ name = 'AddChipStyleV1toV2'
88
+ description = 'Добавляет поле chipStyle в sections.top.params'
89
+ appliesTo = { from: '1.0' as const, to: '2.0' as const }
90
+
91
+ apply(context: MigrationContext): MigrationStepResult {
92
+ try {
93
+ const config = { ...context.config }
94
+ const warnings: string[] = []
95
+
96
+ // Добавляем chipStyle в top.params
97
+ config.sections.top.params = {
98
+ ...config.sections.top.params,
99
+ chipStyle: DEFAULT_CONFIG.sections.top.params.chipStyle // 'filled'
100
+ }
101
+
102
+ warnings.push(`Добавлено поле chipStyle: '${DEFAULT_CONFIG.sections.top.params.chipStyle}' в sections.top.params`)
103
+
104
+ return this.createSuccessResult(config, warnings)
105
+ } catch (error) {
106
+ return this.createErrorResult([`Ошибка при добавлении chipStyle: ${error}`])
107
+ }
108
+ }
109
+ }
110
+
111
+ /** Стратегия добавления bgType для сообщений в V1->V2 */
112
+ export class AddMessageBgTypeV1toV2Strategy extends BaseMigrationStrategy {
113
+ name = 'AddMessageBgTypeV1toV2'
114
+ description = 'Добавляет поле bgType в messageUser и messageBot'
115
+ appliesTo = { from: '1.0' as const, to: '2.0' as const }
116
+
117
+ apply(context: MigrationContext): MigrationStepResult {
118
+ try {
119
+ const config = { ...context.config }
120
+ const warnings: string[] = []
121
+
122
+ // Добавляем bgType в messageUser и messageBot
123
+ config.sections.inside.messageUser = {
124
+ ...config.sections.inside.messageUser,
125
+ bgType: DEFAULT_CONFIG.sections.inside.messageUser.bgType // 'bubble'
126
+ }
127
+
128
+ config.sections.inside.messageBot = {
129
+ ...config.sections.inside.messageBot,
130
+ bgType: DEFAULT_CONFIG.sections.inside.messageBot.bgType // 'plain'
131
+ }
132
+
133
+ warnings.push('Добавлены поля bgType для messageUser и messageBot')
134
+
135
+ return this.createSuccessResult(config, warnings)
136
+ } catch (error) {
137
+ return this.createErrorResult([`Ошибка при добавлении bgType для сообщений: ${error}`])
138
+ }
139
+ }
140
+ }
141
+
142
+ /** Стратегия добавления новых кнопок approve/reject в V1->V2 */
143
+ export class AddActionButtonsV1toV2Strategy extends BaseMigrationStrategy {
144
+ name = 'AddActionButtonsV1toV2'
145
+ description = 'Добавляет кнопки aprooveButton и rejectButton в inside секцию'
146
+ appliesTo = { from: '1.0' as const, to: '2.0' as const }
147
+
148
+ apply(context: MigrationContext): MigrationStepResult {
149
+ try {
150
+ const config = { ...context.config }
151
+ const warnings: string[] = []
152
+
153
+ // Добавляем новые кнопки
154
+ config.sections.inside = {
155
+ ...config.sections.inside
156
+ }
157
+
158
+ warnings.push('Добавлены кнопки aprooveButton и rejectButton')
159
+
160
+ return this.createSuccessResult(config, warnings)
161
+ } catch (error) {
162
+ return this.createErrorResult([`Ошибка при добавлении кнопок действий: ${error}`])
163
+ }
164
+ }
165
+ }
166
+
167
+ /** Стратегия расширения inputSend для V1->V2 */
168
+ export class EnhanceInputSendV1toV2Strategy extends BaseMigrationStrategy {
169
+ name = 'EnhanceInputSendV1toV2'
170
+ description = 'Добавляет borderStyle, inputStyle, bgType в inputSend'
171
+ appliesTo = { from: '1.0' as const, to: '2.0' as const }
172
+
173
+ apply(context: MigrationContext): MigrationStepResult {
174
+ try {
175
+ const config = { ...context.config }
176
+ const warnings: string[] = []
177
+
178
+ // Расширяем inputSend
179
+ config.sections.bottom.inputSend = {
180
+ ...config.sections.bottom.inputSend,
181
+ borderStyle: DEFAULT_CONFIG.sections.bottom.inputSend.borderStyle,
182
+ inputStyle: DEFAULT_CONFIG.sections.bottom.inputSend.inputStyle, // 'inside'
183
+ bgType: DEFAULT_CONFIG.sections.bottom.inputSend.bgType // 'plain'
184
+ }
185
+
186
+ warnings.push('Расширен inputSend с новыми полями borderStyle, inputStyle, bgType')
187
+
188
+ return this.createSuccessResult(config, warnings)
189
+ } catch (error) {
190
+ return this.createErrorResult([`Ошибка при расширении inputSend: ${error}`])
191
+ }
192
+ }
193
+ }
194
+
195
+ /** Стратегия добавления warningAlert и disclaimer в V1->V2 */
196
+ export class AddBottomElementsV1toV2Strategy extends BaseMigrationStrategy {
197
+ name = 'AddBottomElementsV1toV2'
198
+ description = 'Добавляет warningAlert и disclaimer в bottom секцию'
199
+ appliesTo = { from: '1.0' as const, to: '2.0' as const }
200
+
201
+ apply(context: MigrationContext): MigrationStepResult {
202
+ try {
203
+ const config = { ...context.config }
204
+ const warnings: string[] = []
205
+
206
+ // Добавляем новые элементы в bottom
207
+ config.sections.bottom = {
208
+ ...config.sections.bottom,
209
+ warningAlert: DEFAULT_CONFIG.sections.bottom.warningAlert
210
+ }
211
+
212
+ warnings.push('Добавлены warningAlert и disclaimer в bottom секцию')
213
+
214
+ return this.createSuccessResult(config, warnings)
215
+ } catch (error) {
216
+ return this.createErrorResult([`Ошибка при добавлении элементов bottom: ${error}`])
217
+ }
218
+ }
219
+ }
220
+
221
+ /** Реестр всех стратегий миграции V1->V2 */
222
+ export const V1_TO_V2_STRATEGIES: MigrationStrategy[] = [
223
+ new AddSettingsFieldsV1toV2Strategy(),
224
+ new AddChipStyleV1toV2Strategy(),
225
+ new AddMessageBgTypeV1toV2Strategy(),
226
+ new AddActionButtonsV1toV2Strategy(),
227
+ new EnhanceInputSendV1toV2Strategy(),
228
+ new AddBottomElementsV1toV2Strategy()
229
+ ]
230
+
231
+ /** Получить все стратегии для конкретного перехода версий */
232
+ export function getStrategiesForMigration(from: string, to: string): MigrationStrategy[] {
233
+ const allStrategies = [
234
+ ...V1_TO_V2_STRATEGIES
235
+ // Здесь можно добавить стратегии для других версий: V2_TO_V3_STRATEGIES и т.д.
236
+ ]
237
+
238
+ return allStrategies.filter(strategy =>
239
+ strategy.appliesTo.from === from && strategy.appliesTo.to === to
240
+ )
241
+ }
242
+
243
+ /** Получить все доступные стратегии */
244
+ export function getAllStrategies(): MigrationStrategy[] {
245
+ return [
246
+ ...V1_TO_V2_STRATEGIES
247
+ // Добавляйте сюда новые группы стратегий для других версий
248
+ ]
249
+ }