@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,454 @@
1
+ /**
2
+ * Interactive REPL mode for ts-cloud CLI
3
+ * Provides a shell-like experience for running commands
4
+ */
5
+
6
+ export interface REPLOptions {
7
+ prompt?: string
8
+ welcome?: string
9
+ commands: Map<string, REPLCommand>
10
+ historyFile?: string
11
+ autocomplete?: boolean
12
+ }
13
+
14
+ export interface REPLCommand {
15
+ name: string
16
+ description: string
17
+ aliases?: string[]
18
+ handler: (args: string[]) => Promise<void> | void
19
+ autocomplete?: (partial: string) => string[]
20
+ }
21
+
22
+ export interface REPLHistory {
23
+ commands: string[]
24
+ maxSize: number
25
+ }
26
+
27
+ /**
28
+ * REPL session manager
29
+ */
30
+ export class REPL {
31
+ private options: REPLOptions
32
+ private running: boolean = false
33
+ private history: REPLHistory = {
34
+ commands: [],
35
+ maxSize: 1000,
36
+ }
37
+ private historyIndex: number = -1
38
+
39
+ constructor(options: REPLOptions) {
40
+ this.options = {
41
+ prompt: options.prompt || '> ',
42
+ welcome: options.welcome || 'Welcome to ts-cloud interactive mode. Type "help" for available commands.',
43
+ ...options,
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Start REPL session
49
+ */
50
+ async start(): Promise<void> {
51
+ this.running = true
52
+
53
+ // Print welcome message
54
+ if (this.options.welcome) {
55
+ console.log(this.options.welcome)
56
+ console.log('')
57
+ }
58
+
59
+ // Load history from file if specified
60
+ if (this.options.historyFile) {
61
+ await this.loadHistory()
62
+ }
63
+
64
+ // Main REPL loop
65
+ while (this.running) {
66
+ try {
67
+ const input = await this.readInput()
68
+
69
+ if (!input.trim()) continue
70
+
71
+ // Add to history
72
+ this.addToHistory(input)
73
+
74
+ // Parse and execute command
75
+ await this.executeCommand(input)
76
+ }
77
+ catch (error) {
78
+ if (error instanceof Error) {
79
+ console.error(`Error: ${error.message}`)
80
+ }
81
+ }
82
+ }
83
+
84
+ // Save history before exiting
85
+ if (this.options.historyFile) {
86
+ await this.saveHistory()
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Stop REPL session
92
+ */
93
+ stop(): void {
94
+ this.running = false
95
+ }
96
+
97
+ /**
98
+ * Read input from user
99
+ */
100
+ private async readInput(): Promise<string> {
101
+ // In a real implementation, this would use readline or similar
102
+ // For now, we'll return a mock implementation
103
+ return new Promise((resolve) => {
104
+ // Mock implementation - in real code, use readline
105
+ process.stdout.write(this.options.prompt || '> ')
106
+
107
+ // This is a simplified version - real implementation would handle:
108
+ // - Line editing
109
+ // - History navigation (up/down arrows)
110
+ // - Autocomplete (tab)
111
+ // - Ctrl+C handling
112
+ resolve('')
113
+ })
114
+ }
115
+
116
+ /**
117
+ * Execute command
118
+ */
119
+ private async executeCommand(input: string): Promise<void> {
120
+ const [commandName, ...args] = this.parseCommand(input)
121
+
122
+ // Check for built-in commands
123
+ if (commandName === 'exit' || commandName === 'quit') {
124
+ this.stop()
125
+ return
126
+ }
127
+
128
+ if (commandName === 'help') {
129
+ this.showHelp()
130
+ return
131
+ }
132
+
133
+ if (commandName === 'history') {
134
+ this.showHistory()
135
+ return
136
+ }
137
+
138
+ if (commandName === 'clear') {
139
+ console.clear()
140
+ return
141
+ }
142
+
143
+ // Find command (including aliases)
144
+ const command = this.findCommand(commandName)
145
+
146
+ if (!command) {
147
+ console.error(`Unknown command: ${commandName}`)
148
+ console.log('Type "help" to see available commands.')
149
+ return
150
+ }
151
+
152
+ // Execute command handler
153
+ try {
154
+ await command.handler(args)
155
+ }
156
+ catch (error) {
157
+ if (error instanceof Error) {
158
+ console.error(`Command failed: ${error.message}`)
159
+ }
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Parse command input
165
+ */
166
+ private parseCommand(input: string): string[] {
167
+ // Simple parser - could be enhanced to handle:
168
+ // - Quoted strings
169
+ // - Escaped characters
170
+ // - Variable substitution
171
+ return input.trim().split(/\s+/)
172
+ }
173
+
174
+ /**
175
+ * Find command by name or alias
176
+ */
177
+ private findCommand(name: string): REPLCommand | undefined {
178
+ for (const [_key, command] of this.options.commands) {
179
+ if (command.name === name || command.aliases?.includes(name)) {
180
+ return command
181
+ }
182
+ }
183
+ return undefined
184
+ }
185
+
186
+ /**
187
+ * Show help message
188
+ */
189
+ private showHelp(): void {
190
+ console.log('Available commands:')
191
+ console.log('')
192
+
193
+ const commands = Array.from(this.options.commands.values())
194
+
195
+ // Built-in commands
196
+ console.log(' help Show this help message')
197
+ console.log(' history Show command history')
198
+ console.log(' clear Clear screen')
199
+ console.log(' exit, quit Exit interactive mode')
200
+ console.log('')
201
+
202
+ // User commands
203
+ for (const command of commands) {
204
+ let line = ` ${command.name.padEnd(20)} ${command.description}`
205
+
206
+ if (command.aliases && command.aliases.length > 0) {
207
+ line += ` (aliases: ${command.aliases.join(', ')})`
208
+ }
209
+
210
+ console.log(line)
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Show command history
216
+ */
217
+ private showHistory(): void {
218
+ if (this.history.commands.length === 0) {
219
+ console.log('No command history')
220
+ return
221
+ }
222
+
223
+ console.log('Command history:')
224
+ this.history.commands.forEach((cmd, index) => {
225
+ console.log(` ${(index + 1).toString().padStart(4)} ${cmd}`)
226
+ })
227
+ }
228
+
229
+ /**
230
+ * Add command to history
231
+ */
232
+ private addToHistory(command: string): void {
233
+ // Don't add duplicates of the last command
234
+ if (this.history.commands[this.history.commands.length - 1] === command) {
235
+ return
236
+ }
237
+
238
+ this.history.commands.push(command)
239
+
240
+ // Trim history if it exceeds max size
241
+ if (this.history.commands.length > this.history.maxSize) {
242
+ this.history.commands = this.history.commands.slice(-this.history.maxSize)
243
+ }
244
+
245
+ this.historyIndex = this.history.commands.length
246
+ }
247
+
248
+ /**
249
+ * Navigate history (up arrow)
250
+ */
251
+ private historyBack(): string | undefined {
252
+ if (this.historyIndex > 0) {
253
+ this.historyIndex--
254
+ return this.history.commands[this.historyIndex]
255
+ }
256
+ return undefined
257
+ }
258
+
259
+ /**
260
+ * Navigate history (down arrow)
261
+ */
262
+ private historyForward(): string | undefined {
263
+ if (this.historyIndex < this.history.commands.length - 1) {
264
+ this.historyIndex++
265
+ return this.history.commands[this.historyIndex]
266
+ }
267
+ this.historyIndex = this.history.commands.length
268
+ return ''
269
+ }
270
+
271
+ /**
272
+ * Autocomplete command
273
+ */
274
+ private autocomplete(partial: string): string[] {
275
+ const suggestions: string[] = []
276
+
277
+ // Check built-in commands
278
+ const builtins = ['help', 'history', 'clear', 'exit', 'quit']
279
+ for (const builtin of builtins) {
280
+ if (builtin.startsWith(partial)) {
281
+ suggestions.push(builtin)
282
+ }
283
+ }
284
+
285
+ // Check user commands
286
+ for (const [_key, command] of this.options.commands) {
287
+ if (command.name.startsWith(partial)) {
288
+ suggestions.push(command.name)
289
+ }
290
+
291
+ if (command.aliases) {
292
+ for (const alias of command.aliases) {
293
+ if (alias.startsWith(partial)) {
294
+ suggestions.push(alias)
295
+ }
296
+ }
297
+ }
298
+ }
299
+
300
+ return suggestions
301
+ }
302
+
303
+ /**
304
+ * Load history from file
305
+ */
306
+ private async loadHistory(): Promise<void> {
307
+ if (!this.options.historyFile) return
308
+
309
+ try {
310
+ const fs = await import('node:fs/promises')
311
+ const data = await fs.readFile(this.options.historyFile, 'utf-8')
312
+ this.history.commands = data.split('\n').filter(line => line.trim())
313
+ this.historyIndex = this.history.commands.length
314
+ }
315
+ catch {
316
+ // File doesn't exist or can't be read - that's ok
317
+ }
318
+ }
319
+
320
+ /**
321
+ * Save history to file
322
+ */
323
+ private async saveHistory(): Promise<void> {
324
+ if (!this.options.historyFile) return
325
+
326
+ try {
327
+ const fs = await import('node:fs/promises')
328
+ await fs.writeFile(this.options.historyFile, this.history.commands.join('\n'))
329
+ }
330
+ catch (error) {
331
+ console.error(`Failed to save history: ${error}`)
332
+ }
333
+ }
334
+
335
+ /**
336
+ * Search history
337
+ */
338
+ searchHistory(query: string): string[] {
339
+ return this.history.commands.filter(cmd => cmd.includes(query))
340
+ }
341
+
342
+ /**
343
+ * Clear history
344
+ */
345
+ clearHistory(): void {
346
+ this.history.commands = []
347
+ this.historyIndex = 0
348
+ }
349
+ }
350
+
351
+ /**
352
+ * Context manager for REPL sessions
353
+ * Maintains state across commands
354
+ */
355
+ export class REPLContext {
356
+ private variables: Map<string, any> = new Map()
357
+ private workingDirectory: string = process.cwd()
358
+
359
+ /**
360
+ * Set variable
361
+ */
362
+ set(key: string, value: any): void {
363
+ this.variables.set(key, value)
364
+ }
365
+
366
+ /**
367
+ * Get variable
368
+ */
369
+ get(key: string): any {
370
+ return this.variables.get(key)
371
+ }
372
+
373
+ /**
374
+ * Check if variable exists
375
+ */
376
+ has(key: string): boolean {
377
+ return this.variables.has(key)
378
+ }
379
+
380
+ /**
381
+ * Delete variable
382
+ */
383
+ delete(key: string): void {
384
+ this.variables.delete(key)
385
+ }
386
+
387
+ /**
388
+ * Get all variables
389
+ */
390
+ getAll(): Record<string, any> {
391
+ return Object.fromEntries(this.variables)
392
+ }
393
+
394
+ /**
395
+ * Clear all variables
396
+ */
397
+ clear(): void {
398
+ this.variables.clear()
399
+ }
400
+
401
+ /**
402
+ * Set working directory
403
+ */
404
+ setWorkingDirectory(path: string): void {
405
+ this.workingDirectory = path
406
+ }
407
+
408
+ /**
409
+ * Get working directory
410
+ */
411
+ getWorkingDirectory(): string {
412
+ return this.workingDirectory
413
+ }
414
+ }
415
+
416
+ /**
417
+ * Command builder for creating REPL commands
418
+ */
419
+ export class REPLCommandBuilder {
420
+ private command: Partial<REPLCommand> = {}
421
+
422
+ name(name: string): this {
423
+ this.command.name = name
424
+ return this
425
+ }
426
+
427
+ description(description: string): this {
428
+ this.command.description = description
429
+ return this
430
+ }
431
+
432
+ aliases(...aliases: string[]): this {
433
+ this.command.aliases = aliases
434
+ return this
435
+ }
436
+
437
+ handler(handler: (args: string[]) => Promise<void> | void): this {
438
+ this.command.handler = handler
439
+ return this
440
+ }
441
+
442
+ autocomplete(fn: (partial: string) => string[]): this {
443
+ this.command.autocomplete = fn
444
+ return this
445
+ }
446
+
447
+ build(): REPLCommand {
448
+ if (!this.command.name || !this.command.description || !this.command.handler) {
449
+ throw new Error('Command must have name, description, and handler')
450
+ }
451
+
452
+ return this.command as REPLCommand
453
+ }
454
+ }