@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.
- package/README.md +214 -115
- package/dist/config.types.d.ts +111 -44
- package/dist/config.types.d.ts.map +1 -1
- package/dist/config.types.js +2 -67
- package/dist/config.types.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/migration/commands.d.ts +59 -0
- package/dist/migration/commands.d.ts.map +1 -0
- package/dist/migration/commands.js +286 -0
- package/dist/migration/commands.js.map +1 -0
- package/dist/migration/examples.d.ts +198 -0
- package/dist/migration/examples.d.ts.map +1 -0
- package/dist/migration/examples.js +439 -0
- package/dist/migration/examples.js.map +1 -0
- package/dist/migration/facade.d.ts +85 -0
- package/dist/migration/facade.d.ts.map +1 -0
- package/dist/migration/facade.js +168 -0
- package/dist/migration/facade.js.map +1 -0
- package/dist/migration/migrator.d.ts +49 -0
- package/dist/migration/migrator.d.ts.map +1 -0
- package/dist/migration/migrator.js +245 -0
- package/dist/migration/migrator.js.map +1 -0
- package/dist/migration/strategies.d.ts +85 -0
- package/dist/migration/strategies.d.ts.map +1 -0
- package/dist/migration/strategies.js +217 -0
- package/dist/migration/strategies.js.map +1 -0
- package/dist/migration/types.d.ts +196 -0
- package/dist/migration/types.d.ts.map +1 -0
- package/dist/migration/types.js +5 -0
- package/dist/migration/types.js.map +1 -0
- package/dist/utils.d.ts +1 -11
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +3 -127
- package/dist/utils.js.map +1 -1
- package/package.json +13 -4
- package/src/config.types.ts +132 -118
- package/src/index.ts +26 -0
- package/src/migration/commands.ts +314 -0
- package/src/migration/examples.ts +471 -0
- package/src/migration/facade.ts +196 -0
- package/src/migration/migrator.ts +361 -0
- package/src/migration/strategies.ts +249 -0
- package/src/migration/types.ts +182 -0
- 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
|
+
}
|