@stacksjs/ts-cloud-core 0.1.1

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 (251) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +321 -0
  3. package/package.json +31 -0
  4. package/src/advanced-features.test.ts +465 -0
  5. package/src/aws/cloudformation.ts +421 -0
  6. package/src/aws/cloudfront.ts +158 -0
  7. package/src/aws/credentials.test.ts +132 -0
  8. package/src/aws/credentials.ts +545 -0
  9. package/src/aws/index.ts +87 -0
  10. package/src/aws/s3.test.ts +188 -0
  11. package/src/aws/s3.ts +1088 -0
  12. package/src/aws/signature.test.ts +670 -0
  13. package/src/aws/signature.ts +1155 -0
  14. package/src/backup/disaster-recovery.test.ts +726 -0
  15. package/src/backup/disaster-recovery.ts +500 -0
  16. package/src/backup/index.ts +34 -0
  17. package/src/backup/manager.test.ts +498 -0
  18. package/src/backup/manager.ts +432 -0
  19. package/src/cicd/circleci.ts +430 -0
  20. package/src/cicd/github-actions.ts +424 -0
  21. package/src/cicd/gitlab-ci.ts +255 -0
  22. package/src/cicd/index.ts +8 -0
  23. package/src/cli/history.ts +396 -0
  24. package/src/cli/index.ts +10 -0
  25. package/src/cli/progress.ts +458 -0
  26. package/src/cli/repl.ts +454 -0
  27. package/src/cli/suggestions.ts +327 -0
  28. package/src/cli/table.test.ts +319 -0
  29. package/src/cli/table.ts +332 -0
  30. package/src/cloudformation/builder.test.ts +327 -0
  31. package/src/cloudformation/builder.ts +378 -0
  32. package/src/cloudformation/builders/api-gateway.ts +449 -0
  33. package/src/cloudformation/builders/cache.ts +334 -0
  34. package/src/cloudformation/builders/cdn.ts +278 -0
  35. package/src/cloudformation/builders/compute.ts +485 -0
  36. package/src/cloudformation/builders/database.ts +392 -0
  37. package/src/cloudformation/builders/functions.ts +343 -0
  38. package/src/cloudformation/builders/messaging.ts +140 -0
  39. package/src/cloudformation/builders/monitoring.ts +300 -0
  40. package/src/cloudformation/builders/network.ts +264 -0
  41. package/src/cloudformation/builders/queue.ts +147 -0
  42. package/src/cloudformation/builders/security.ts +399 -0
  43. package/src/cloudformation/builders/storage.ts +285 -0
  44. package/src/cloudformation/index.ts +30 -0
  45. package/src/cloudformation/types.ts +173 -0
  46. package/src/compliance/aws-config.ts +543 -0
  47. package/src/compliance/cloudtrail.ts +376 -0
  48. package/src/compliance/compliance.test.ts +423 -0
  49. package/src/compliance/guardduty.ts +446 -0
  50. package/src/compliance/index.ts +66 -0
  51. package/src/compliance/security-hub.ts +456 -0
  52. package/src/containers/build-optimization.ts +416 -0
  53. package/src/containers/containers.test.ts +508 -0
  54. package/src/containers/image-scanning.ts +360 -0
  55. package/src/containers/index.ts +9 -0
  56. package/src/containers/registry.ts +293 -0
  57. package/src/containers/service-mesh.ts +520 -0
  58. package/src/database/database.test.ts +762 -0
  59. package/src/database/index.ts +9 -0
  60. package/src/database/migrations.ts +444 -0
  61. package/src/database/performance.ts +528 -0
  62. package/src/database/replicas.ts +534 -0
  63. package/src/database/users.ts +494 -0
  64. package/src/dependency-graph.ts +143 -0
  65. package/src/deployment/ab-testing.ts +582 -0
  66. package/src/deployment/blue-green.ts +452 -0
  67. package/src/deployment/canary.ts +500 -0
  68. package/src/deployment/deployment.test.ts +526 -0
  69. package/src/deployment/index.ts +61 -0
  70. package/src/deployment/progressive.ts +62 -0
  71. package/src/dns/dns.test.ts +641 -0
  72. package/src/dns/dnssec.ts +315 -0
  73. package/src/dns/index.ts +8 -0
  74. package/src/dns/resolver.ts +496 -0
  75. package/src/dns/routing.ts +593 -0
  76. package/src/email/advanced/analytics.ts +445 -0
  77. package/src/email/advanced/index.ts +11 -0
  78. package/src/email/advanced/rules.ts +465 -0
  79. package/src/email/advanced/scheduling.ts +352 -0
  80. package/src/email/advanced/search.ts +412 -0
  81. package/src/email/advanced/shared-mailboxes.ts +404 -0
  82. package/src/email/advanced/templates.ts +455 -0
  83. package/src/email/advanced/threading.ts +281 -0
  84. package/src/email/analytics.ts +467 -0
  85. package/src/email/bounce-handling.ts +425 -0
  86. package/src/email/email.test.ts +431 -0
  87. package/src/email/handlers/__tests__/inbound.test.ts +38 -0
  88. package/src/email/handlers/__tests__/outbound.test.ts +37 -0
  89. package/src/email/handlers/converter.ts +227 -0
  90. package/src/email/handlers/feedback.ts +228 -0
  91. package/src/email/handlers/inbound.ts +169 -0
  92. package/src/email/handlers/outbound.ts +178 -0
  93. package/src/email/index.ts +15 -0
  94. package/src/email/reputation.ts +303 -0
  95. package/src/email/templates.ts +352 -0
  96. package/src/errors/index.test.ts +434 -0
  97. package/src/errors/index.ts +416 -0
  98. package/src/health-checks/index.ts +40 -0
  99. package/src/index.ts +360 -0
  100. package/src/intrinsic-functions.ts +118 -0
  101. package/src/lambda/concurrency.ts +330 -0
  102. package/src/lambda/destinations.ts +345 -0
  103. package/src/lambda/dlq.ts +425 -0
  104. package/src/lambda/index.ts +11 -0
  105. package/src/lambda/lambda.test.ts +840 -0
  106. package/src/lambda/layers.ts +263 -0
  107. package/src/lambda/versions.ts +376 -0
  108. package/src/lambda/vpc.ts +399 -0
  109. package/src/local/config.ts +114 -0
  110. package/src/local/index.ts +6 -0
  111. package/src/local/mock-aws.ts +351 -0
  112. package/src/modules/ai.ts +340 -0
  113. package/src/modules/api.ts +478 -0
  114. package/src/modules/auth.ts +805 -0
  115. package/src/modules/cache.ts +417 -0
  116. package/src/modules/cdn.ts +1062 -0
  117. package/src/modules/communication.ts +1094 -0
  118. package/src/modules/compute.ts +3348 -0
  119. package/src/modules/database.ts +554 -0
  120. package/src/modules/deployment.ts +1079 -0
  121. package/src/modules/dns.ts +337 -0
  122. package/src/modules/email.ts +1538 -0
  123. package/src/modules/filesystem.ts +515 -0
  124. package/src/modules/index.ts +32 -0
  125. package/src/modules/messaging.ts +486 -0
  126. package/src/modules/monitoring.ts +2086 -0
  127. package/src/modules/network.ts +664 -0
  128. package/src/modules/parameter-store.ts +325 -0
  129. package/src/modules/permissions.ts +1081 -0
  130. package/src/modules/phone.ts +494 -0
  131. package/src/modules/queue.ts +1260 -0
  132. package/src/modules/redirects.ts +464 -0
  133. package/src/modules/registry.ts +699 -0
  134. package/src/modules/search.ts +401 -0
  135. package/src/modules/secrets.ts +416 -0
  136. package/src/modules/security.ts +731 -0
  137. package/src/modules/sms.ts +389 -0
  138. package/src/modules/storage.ts +1120 -0
  139. package/src/modules/workflow.ts +680 -0
  140. package/src/multi-account/config.ts +521 -0
  141. package/src/multi-account/index.ts +7 -0
  142. package/src/multi-account/manager.ts +427 -0
  143. package/src/multi-region/cross-region.ts +410 -0
  144. package/src/multi-region/index.ts +8 -0
  145. package/src/multi-region/manager.ts +483 -0
  146. package/src/multi-region/regions.ts +435 -0
  147. package/src/network-security/index.ts +48 -0
  148. package/src/observability/index.ts +9 -0
  149. package/src/observability/logs.ts +522 -0
  150. package/src/observability/metrics.ts +460 -0
  151. package/src/observability/observability.test.ts +782 -0
  152. package/src/observability/synthetics.ts +568 -0
  153. package/src/observability/xray.ts +358 -0
  154. package/src/phone/advanced/analytics.ts +349 -0
  155. package/src/phone/advanced/callbacks.ts +428 -0
  156. package/src/phone/advanced/index.ts +8 -0
  157. package/src/phone/advanced/ivr-builder.ts +504 -0
  158. package/src/phone/advanced/recording.ts +310 -0
  159. package/src/phone/handlers/__tests__/incoming-call.test.ts +40 -0
  160. package/src/phone/handlers/incoming-call.ts +117 -0
  161. package/src/phone/handlers/missed-call.ts +116 -0
  162. package/src/phone/handlers/voicemail.ts +179 -0
  163. package/src/phone/index.ts +9 -0
  164. package/src/presets/api-backend.ts +134 -0
  165. package/src/presets/data-pipeline.ts +204 -0
  166. package/src/presets/extend.test.ts +295 -0
  167. package/src/presets/extend.ts +297 -0
  168. package/src/presets/fullstack-app.ts +144 -0
  169. package/src/presets/index.ts +27 -0
  170. package/src/presets/jamstack.ts +135 -0
  171. package/src/presets/microservices.ts +167 -0
  172. package/src/presets/ml-api.ts +208 -0
  173. package/src/presets/nodejs-server.ts +104 -0
  174. package/src/presets/nodejs-serverless.ts +114 -0
  175. package/src/presets/realtime-app.ts +184 -0
  176. package/src/presets/static-site.ts +64 -0
  177. package/src/presets/traditional-web-app.ts +339 -0
  178. package/src/presets/wordpress.ts +138 -0
  179. package/src/preview/github.test.ts +249 -0
  180. package/src/preview/github.ts +297 -0
  181. package/src/preview/index.ts +37 -0
  182. package/src/preview/manager.test.ts +440 -0
  183. package/src/preview/manager.ts +326 -0
  184. package/src/preview/notifications.test.ts +582 -0
  185. package/src/preview/notifications.ts +341 -0
  186. package/src/queue/batch-processing.ts +402 -0
  187. package/src/queue/dlq-monitoring.ts +402 -0
  188. package/src/queue/fifo.ts +342 -0
  189. package/src/queue/index.ts +9 -0
  190. package/src/queue/management.ts +428 -0
  191. package/src/queue/queue.test.ts +429 -0
  192. package/src/resource-mgmt/index.ts +39 -0
  193. package/src/resource-naming.ts +62 -0
  194. package/src/s3/index.ts +523 -0
  195. package/src/schema/cloud-config.schema.json +554 -0
  196. package/src/schema/index.ts +68 -0
  197. package/src/security/certificate-manager.ts +492 -0
  198. package/src/security/index.ts +9 -0
  199. package/src/security/scanning.ts +545 -0
  200. package/src/security/secrets-manager.ts +476 -0
  201. package/src/security/secrets-rotation.ts +456 -0
  202. package/src/security/security.test.ts +738 -0
  203. package/src/sms/advanced/ab-testing.ts +389 -0
  204. package/src/sms/advanced/analytics.ts +336 -0
  205. package/src/sms/advanced/campaigns.ts +523 -0
  206. package/src/sms/advanced/chatbot.ts +224 -0
  207. package/src/sms/advanced/index.ts +10 -0
  208. package/src/sms/advanced/link-tracking.ts +248 -0
  209. package/src/sms/advanced/mms.ts +308 -0
  210. package/src/sms/handlers/__tests__/send.test.ts +40 -0
  211. package/src/sms/handlers/delivery-status.ts +133 -0
  212. package/src/sms/handlers/receive.ts +162 -0
  213. package/src/sms/handlers/send.ts +174 -0
  214. package/src/sms/index.ts +9 -0
  215. package/src/stack-diff.ts +389 -0
  216. package/src/static-site/index.ts +85 -0
  217. package/src/template-builder.ts +110 -0
  218. package/src/template-validator.ts +574 -0
  219. package/src/utils/cache.ts +291 -0
  220. package/src/utils/diff.ts +269 -0
  221. package/src/utils/hash.ts +227 -0
  222. package/src/utils/index.ts +8 -0
  223. package/src/utils/parallel.ts +294 -0
  224. package/src/validators/credentials.test.ts +274 -0
  225. package/src/validators/credentials.ts +233 -0
  226. package/src/validators/quotas.test.ts +434 -0
  227. package/src/validators/quotas.ts +217 -0
  228. package/test/ai.test.ts +327 -0
  229. package/test/api.test.ts +511 -0
  230. package/test/auth.test.ts +632 -0
  231. package/test/cache.test.ts +406 -0
  232. package/test/cdn.test.ts +247 -0
  233. package/test/compute.test.ts +861 -0
  234. package/test/database.test.ts +523 -0
  235. package/test/deployment.test.ts +499 -0
  236. package/test/dns.test.ts +270 -0
  237. package/test/email.test.ts +439 -0
  238. package/test/filesystem.test.ts +382 -0
  239. package/test/integration.test.ts +350 -0
  240. package/test/messaging.test.ts +514 -0
  241. package/test/monitoring.test.ts +634 -0
  242. package/test/network.test.ts +425 -0
  243. package/test/permissions.test.ts +488 -0
  244. package/test/queue.test.ts +484 -0
  245. package/test/registry.test.ts +306 -0
  246. package/test/security.test.ts +462 -0
  247. package/test/storage.test.ts +463 -0
  248. package/test/template-validator.test.ts +559 -0
  249. package/test/workflow.test.ts +592 -0
  250. package/tsconfig.json +16 -0
  251. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Database Advanced Features Module
3
+ * Migration management, replicas, performance monitoring, and user management
4
+ */
5
+
6
+ export * from './migrations'
7
+ export * from './replicas'
8
+ export * from './performance'
9
+ export * from './users'
@@ -0,0 +1,444 @@
1
+ /**
2
+ * Database Migration Management
3
+ * Version-controlled schema changes with rollback support
4
+ */
5
+
6
+ export interface Migration {
7
+ id: string
8
+ version: string
9
+ name: string
10
+ description?: string
11
+ up: string // SQL for applying migration
12
+ down: string // SQL for rolling back migration
13
+ checksum: string // For integrity verification
14
+ appliedAt?: Date
15
+ rolledBackAt?: Date
16
+ executionTimeMs?: number
17
+ }
18
+
19
+ export interface MigrationPlan {
20
+ id: string
21
+ name: string
22
+ database: DatabaseTarget
23
+ migrations: Migration[]
24
+ autoApply?: boolean
25
+ backupBeforeMigration?: boolean
26
+ testMigrations?: boolean
27
+ validateRollback?: boolean
28
+ }
29
+
30
+ export interface DatabaseTarget {
31
+ type: 'rds' | 'aurora' | 'dynamodb'
32
+ identifier: string
33
+ engine?: 'postgres' | 'mysql' | 'mariadb'
34
+ endpoint?: string
35
+ database?: string
36
+ }
37
+
38
+ export interface MigrationResult {
39
+ success: boolean
40
+ version: string
41
+ appliedMigrations: string[]
42
+ failedMigrations: string[]
43
+ executionTimeMs: number
44
+ error?: string
45
+ rollbackPerformed?: boolean
46
+ }
47
+
48
+ export interface MigrationStatus {
49
+ currentVersion: string
50
+ pendingMigrations: Migration[]
51
+ appliedMigrations: Migration[]
52
+ lastMigration?: Migration
53
+ }
54
+
55
+ /**
56
+ * Migration manager
57
+ */
58
+ export class MigrationManager {
59
+ private plans: Map<string, MigrationPlan> = new Map()
60
+ private migrations: Map<string, Migration> = new Map()
61
+ private planCounter = 0
62
+ private migrationCounter = 0
63
+
64
+ /**
65
+ * Create migration plan
66
+ */
67
+ createPlan(plan: Omit<MigrationPlan, 'id'>): MigrationPlan {
68
+ const id = `migration-plan-${Date.now()}-${this.planCounter++}`
69
+
70
+ const migrationPlan: MigrationPlan = {
71
+ id,
72
+ ...plan,
73
+ }
74
+
75
+ this.plans.set(id, migrationPlan)
76
+
77
+ return migrationPlan
78
+ }
79
+
80
+ /**
81
+ * Create migration
82
+ */
83
+ createMigration(migration: Omit<Migration, 'id' | 'checksum'>): Migration {
84
+ const id = `migration-${Date.now()}-${this.migrationCounter++}`
85
+
86
+ // Generate checksum from up and down SQL
87
+ const checksum = this.generateChecksum(migration.up + migration.down)
88
+
89
+ const newMigration: Migration = {
90
+ id,
91
+ checksum,
92
+ ...migration,
93
+ }
94
+
95
+ this.migrations.set(id, newMigration)
96
+
97
+ return newMigration
98
+ }
99
+
100
+ /**
101
+ * Create schema change migration
102
+ */
103
+ createSchemaMigration(options: {
104
+ version: string
105
+ name: string
106
+ tableName: string
107
+ changes: SchemaChange[]
108
+ engine?: 'postgres' | 'mysql'
109
+ }): Migration {
110
+ const { up, down } = this.generateSchemaSQL(options.changes, options.tableName, options.engine)
111
+
112
+ return this.createMigration({
113
+ version: options.version,
114
+ name: options.name,
115
+ description: `Schema changes for ${options.tableName}`,
116
+ up,
117
+ down,
118
+ })
119
+ }
120
+
121
+ /**
122
+ * Create data migration
123
+ */
124
+ createDataMigration(options: {
125
+ version: string
126
+ name: string
127
+ description?: string
128
+ upSQL: string
129
+ downSQL: string
130
+ }): Migration {
131
+ return this.createMigration({
132
+ version: options.version,
133
+ name: options.name,
134
+ description: options.description,
135
+ up: options.upSQL,
136
+ down: options.downSQL,
137
+ })
138
+ }
139
+
140
+ /**
141
+ * Add migration to plan
142
+ */
143
+ addMigrationToPlan(planId: string, migration: Migration): void {
144
+ const plan = this.plans.get(planId)
145
+
146
+ if (!plan) {
147
+ throw new Error(`Migration plan not found: ${planId}`)
148
+ }
149
+
150
+ plan.migrations.push(migration)
151
+ }
152
+
153
+ /**
154
+ * Execute migration plan
155
+ */
156
+ async executePlan(planId: string, dryRun: boolean = false): Promise<MigrationResult> {
157
+ const plan = this.plans.get(planId)
158
+
159
+ if (!plan) {
160
+ throw new Error(`Migration plan not found: ${planId}`)
161
+ }
162
+
163
+ const startTime = Date.now()
164
+ const appliedMigrations: string[] = []
165
+ const failedMigrations: string[] = []
166
+
167
+ console.log(`${dryRun ? '[DRY RUN] ' : ''}Executing migration plan: ${plan.name}`)
168
+ console.log(`Database: ${plan.database.type} - ${plan.database.identifier}`)
169
+ console.log(`Migrations to apply: ${plan.migrations.length}\n`)
170
+
171
+ if (plan.backupBeforeMigration && !dryRun) {
172
+ console.log('Creating database backup before migration...')
173
+ // Backup logic would go here
174
+ }
175
+
176
+ for (const migration of plan.migrations) {
177
+ try {
178
+ console.log(`Applying migration: ${migration.version} - ${migration.name}`)
179
+
180
+ if (!dryRun) {
181
+ // Verify checksum
182
+ const currentChecksum = this.generateChecksum(migration.up + migration.down)
183
+ if (currentChecksum !== migration.checksum) {
184
+ throw new Error('Migration checksum mismatch - migration has been modified')
185
+ }
186
+
187
+ // Execute migration
188
+ const migrationStart = Date.now()
189
+ // Actual SQL execution would go here
190
+ migration.appliedAt = new Date()
191
+ migration.executionTimeMs = Date.now() - migrationStart
192
+
193
+ console.log(`✓ Applied in ${migration.executionTimeMs}ms\n`)
194
+ } else {
195
+ console.log(`[SKIPPED - DRY RUN]\n`)
196
+ }
197
+
198
+ appliedMigrations.push(migration.version)
199
+ } catch (error) {
200
+ console.error(`✗ Failed: ${error instanceof Error ? error.message : String(error)}\n`)
201
+ failedMigrations.push(migration.version)
202
+
203
+ if (!dryRun) {
204
+ // Rollback previously applied migrations
205
+ console.log('Rolling back previously applied migrations...')
206
+ await this.rollbackMigrations(appliedMigrations.reverse(), plan)
207
+
208
+ return {
209
+ success: false,
210
+ version: migration.version,
211
+ appliedMigrations: [],
212
+ failedMigrations,
213
+ executionTimeMs: Date.now() - startTime,
214
+ error: error instanceof Error ? error.message : String(error),
215
+ rollbackPerformed: true,
216
+ }
217
+ }
218
+ }
219
+ }
220
+
221
+ const executionTimeMs = Date.now() - startTime
222
+
223
+ console.log(`${dryRun ? '[DRY RUN] ' : ''}Migration plan completed successfully`)
224
+ console.log(`Total time: ${executionTimeMs}ms`)
225
+
226
+ return {
227
+ success: true,
228
+ version: plan.migrations[plan.migrations.length - 1]?.version || 'unknown',
229
+ appliedMigrations,
230
+ failedMigrations,
231
+ executionTimeMs,
232
+ }
233
+ }
234
+
235
+ /**
236
+ * Rollback migrations
237
+ */
238
+ private async rollbackMigrations(versions: string[], plan: MigrationPlan): Promise<void> {
239
+ for (const version of versions) {
240
+ const migration = plan.migrations.find(m => m.version === version)
241
+ if (migration) {
242
+ console.log(`Rolling back: ${migration.version} - ${migration.name}`)
243
+ // Execute down SQL
244
+ migration.rolledBackAt = new Date()
245
+ console.log('✓ Rolled back\n')
246
+ }
247
+ }
248
+ }
249
+
250
+ /**
251
+ * Get migration status
252
+ */
253
+ getMigrationStatus(planId: string): MigrationStatus {
254
+ const plan = this.plans.get(planId)
255
+
256
+ if (!plan) {
257
+ throw new Error(`Migration plan not found: ${planId}`)
258
+ }
259
+
260
+ const appliedMigrations = plan.migrations.filter(m => m.appliedAt && !m.rolledBackAt)
261
+ const pendingMigrations = plan.migrations.filter(m => !m.appliedAt)
262
+
263
+ return {
264
+ currentVersion: appliedMigrations[appliedMigrations.length - 1]?.version || '0.0.0',
265
+ pendingMigrations,
266
+ appliedMigrations,
267
+ lastMigration: appliedMigrations[appliedMigrations.length - 1],
268
+ }
269
+ }
270
+
271
+ /**
272
+ * Generate schema SQL from changes
273
+ */
274
+ private generateSchemaSQL(
275
+ changes: SchemaChange[],
276
+ tableName: string,
277
+ engine: 'postgres' | 'mysql' = 'postgres'
278
+ ): { up: string; down: string } {
279
+ const upStatements: string[] = []
280
+ const downStatements: string[] = []
281
+
282
+ for (const change of changes) {
283
+ switch (change.type) {
284
+ case 'add_column':
285
+ upStatements.push(
286
+ `ALTER TABLE ${tableName} ADD COLUMN ${change.columnName} ${change.columnType}${
287
+ change.nullable === false ? ' NOT NULL' : ''
288
+ }${change.defaultValue ? ` DEFAULT ${change.defaultValue}` : ''};`
289
+ )
290
+ downStatements.push(`ALTER TABLE ${tableName} DROP COLUMN ${change.columnName};`)
291
+ break
292
+
293
+ case 'drop_column':
294
+ upStatements.push(`ALTER TABLE ${tableName} DROP COLUMN ${change.columnName};`)
295
+ // Note: Cannot restore dropped column without backup
296
+ downStatements.push(`-- Cannot restore dropped column ${change.columnName}`)
297
+ break
298
+
299
+ case 'modify_column':
300
+ if (engine === 'postgres') {
301
+ upStatements.push(
302
+ `ALTER TABLE ${tableName} ALTER COLUMN ${change.columnName} TYPE ${change.newType};`
303
+ )
304
+ } else {
305
+ upStatements.push(
306
+ `ALTER TABLE ${tableName} MODIFY COLUMN ${change.columnName} ${change.newType};`
307
+ )
308
+ }
309
+ downStatements.push(`-- Reverting ${change.columnName} type change requires manual intervention`)
310
+ break
311
+
312
+ case 'add_index':
313
+ upStatements.push(
314
+ `CREATE INDEX ${change.indexName} ON ${tableName} (${(change.columns ?? []).join(', ')});`
315
+ )
316
+ downStatements.push(`DROP INDEX ${change.indexName};`)
317
+ break
318
+
319
+ case 'drop_index':
320
+ upStatements.push(`DROP INDEX ${change.indexName};`)
321
+ downStatements.push(`-- Cannot restore index ${change.indexName} without schema details`)
322
+ break
323
+ }
324
+ }
325
+
326
+ return {
327
+ up: upStatements.join('\n'),
328
+ down: downStatements.reverse().join('\n'),
329
+ }
330
+ }
331
+
332
+ /**
333
+ * Generate checksum for migration
334
+ */
335
+ private generateChecksum(content: string): string {
336
+ // Simple checksum implementation (in production, use crypto hash)
337
+ let hash = 0
338
+ for (let i = 0; i < content.length; i++) {
339
+ const char = content.charCodeAt(i)
340
+ hash = (hash << 5) - hash + char
341
+ hash = hash & hash // Convert to 32-bit integer
342
+ }
343
+ return hash.toString(16)
344
+ }
345
+
346
+ /**
347
+ * Validate migration plan
348
+ */
349
+ validatePlan(planId: string): { valid: boolean; errors: string[] } {
350
+ const plan = this.plans.get(planId)
351
+
352
+ if (!plan) {
353
+ return { valid: false, errors: ['Migration plan not found'] }
354
+ }
355
+
356
+ const errors: string[] = []
357
+
358
+ // Check for version conflicts
359
+ const versions = new Set<string>()
360
+ for (const migration of plan.migrations) {
361
+ if (versions.has(migration.version)) {
362
+ errors.push(`Duplicate migration version: ${migration.version}`)
363
+ }
364
+ versions.add(migration.version)
365
+ }
366
+
367
+ // Check for missing down migrations
368
+ for (const migration of plan.migrations) {
369
+ if (!migration.down || migration.down.trim() === '') {
370
+ errors.push(`Migration ${migration.version} is missing rollback SQL`)
371
+ }
372
+ }
373
+
374
+ // Check for checksum mismatches
375
+ for (const migration of plan.migrations) {
376
+ const currentChecksum = this.generateChecksum(migration.up + migration.down)
377
+ if (currentChecksum !== migration.checksum) {
378
+ errors.push(`Migration ${migration.version} has invalid checksum`)
379
+ }
380
+ }
381
+
382
+ return {
383
+ valid: errors.length === 0,
384
+ errors,
385
+ }
386
+ }
387
+
388
+ /**
389
+ * Get plan
390
+ */
391
+ getPlan(id: string): MigrationPlan | undefined {
392
+ return this.plans.get(id)
393
+ }
394
+
395
+ /**
396
+ * List plans
397
+ */
398
+ listPlans(): MigrationPlan[] {
399
+ return Array.from(this.plans.values())
400
+ }
401
+
402
+ /**
403
+ * Get migration
404
+ */
405
+ getMigration(id: string): Migration | undefined {
406
+ return this.migrations.get(id)
407
+ }
408
+
409
+ /**
410
+ * List migrations
411
+ */
412
+ listMigrations(): Migration[] {
413
+ return Array.from(this.migrations.values())
414
+ }
415
+
416
+ /**
417
+ * Clear all data
418
+ */
419
+ clear(): void {
420
+ this.plans.clear()
421
+ this.migrations.clear()
422
+ this.planCounter = 0
423
+ this.migrationCounter = 0
424
+ }
425
+ }
426
+
427
+ /**
428
+ * Schema change types
429
+ */
430
+ export interface SchemaChange {
431
+ type: 'add_column' | 'drop_column' | 'modify_column' | 'add_index' | 'drop_index'
432
+ columnName?: string
433
+ columnType?: string
434
+ newType?: string
435
+ nullable?: boolean
436
+ defaultValue?: string
437
+ indexName?: string
438
+ columns?: string[]
439
+ }
440
+
441
+ /**
442
+ * Global migration manager instance
443
+ */
444
+ export const migrationManager: MigrationManager = new MigrationManager()