spindb 0.7.3 → 0.8.0

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.
@@ -8,16 +8,10 @@ import { promptContainerSelect } from '../ui/prompts'
8
8
  import { createSpinner } from '../ui/spinner'
9
9
  import { error, warning, success } from '../ui/theme'
10
10
 
11
- /**
12
- * Validate container name format
13
- */
14
11
  function isValidName(name: string): boolean {
15
12
  return /^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name)
16
13
  }
17
14
 
18
- /**
19
- * Prompt for what to edit when no options provided
20
- */
21
15
  async function promptEditAction(): Promise<'name' | 'port' | null> {
22
16
  const { action } = await inquirer.prompt<{ action: string }>([
23
17
  {
@@ -36,9 +30,6 @@ async function promptEditAction(): Promise<'name' | 'port' | null> {
36
30
  return action as 'name' | 'port'
37
31
  }
38
32
 
39
- /**
40
- * Prompt for new container name
41
- */
42
33
  async function promptNewName(currentName: string): Promise<string | null> {
43
34
  const { newName } = await inquirer.prompt<{ newName: string }>([
44
35
  {
@@ -64,9 +55,6 @@ async function promptNewName(currentName: string): Promise<string | null> {
64
55
  return newName
65
56
  }
66
57
 
67
- /**
68
- * Prompt for new port
69
- */
70
58
  async function promptNewPort(currentPort: number): Promise<number | null> {
71
59
  const { newPort } = await inquirer.prompt<{ newPort: number }>([
72
60
  {
@@ -90,7 +78,6 @@ async function promptNewPort(currentPort: number): Promise<number | null> {
90
78
  return null
91
79
  }
92
80
 
93
- // Double-check availability and warn (user already confirmed via validation)
94
81
  const portAvailable = await portManager.isPortAvailable(newPort)
95
82
  if (!portAvailable) {
96
83
  console.log(
@@ -116,7 +103,6 @@ export const editCommand = new Command('edit')
116
103
  try {
117
104
  let containerName = name
118
105
 
119
- // Interactive selection if no name provided
120
106
  if (!containerName) {
121
107
  const containers = await containerManager.list()
122
108
 
@@ -133,14 +119,12 @@ export const editCommand = new Command('edit')
133
119
  containerName = selected
134
120
  }
135
121
 
136
- // Get container config
137
122
  const config = await containerManager.getConfig(containerName)
138
123
  if (!config) {
139
124
  console.error(error(`Container "${containerName}" not found`))
140
125
  process.exit(1)
141
126
  }
142
127
 
143
- // If no options provided, prompt for what to edit
144
128
  if (options.name === undefined && options.port === undefined) {
145
129
  const action = await promptEditAction()
146
130
  if (!action) return
@@ -162,9 +146,7 @@ export const editCommand = new Command('edit')
162
146
  }
163
147
  }
164
148
 
165
- // Handle rename
166
149
  if (options.name) {
167
- // Validate new name
168
150
  if (!isValidName(options.name)) {
169
151
  console.error(
170
152
  error(
@@ -174,7 +156,6 @@ export const editCommand = new Command('edit')
174
156
  process.exit(1)
175
157
  }
176
158
 
177
- // Check if new name already exists
178
159
  const exists = await containerManager.exists(options.name, {
179
160
  engine: config.engine,
180
161
  })
@@ -183,7 +164,6 @@ export const editCommand = new Command('edit')
183
164
  process.exit(1)
184
165
  }
185
166
 
186
- // Check if container is running
187
167
  const running = await processManager.isRunning(containerName, {
188
168
  engine: config.engine,
189
169
  })
@@ -196,7 +176,6 @@ export const editCommand = new Command('edit')
196
176
  process.exit(1)
197
177
  }
198
178
 
199
- // Rename the container
200
179
  const spinner = createSpinner(
201
180
  `Renaming "${containerName}" to "${options.name}"...`,
202
181
  )
@@ -206,19 +185,15 @@ export const editCommand = new Command('edit')
206
185
 
207
186
  spinner.succeed(`Renamed "${containerName}" to "${options.name}"`)
208
187
 
209
- // Update containerName for subsequent operations
210
188
  containerName = options.name
211
189
  }
212
190
 
213
- // Handle port change
214
191
  if (options.port !== undefined) {
215
- // Validate port
216
192
  if (options.port < 1 || options.port > 65535) {
217
193
  console.error(error('Port must be between 1 and 65535'))
218
194
  process.exit(1)
219
195
  }
220
196
 
221
- // Check port availability (warning only)
222
197
  const portAvailable = await portManager.isPortAvailable(options.port)
223
198
  if (!portAvailable) {
224
199
  console.log(
@@ -228,7 +203,6 @@ export const editCommand = new Command('edit')
228
203
  )
229
204
  }
230
205
 
231
- // Update the config
232
206
  const spinner = createSpinner(`Changing port to ${options.port}...`)
233
207
  spinner.start()
234
208
 
@@ -9,17 +9,11 @@ import { error, info, header } from '../ui/theme'
9
9
  import { getEngineIcon } from '../constants'
10
10
  import type { ContainerConfig } from '../../types'
11
11
 
12
- /**
13
- * Format a date for display
14
- */
15
12
  function formatDate(dateString: string): string {
16
13
  const date = new Date(dateString)
17
14
  return date.toLocaleString()
18
15
  }
19
16
 
20
- /**
21
- * Get actual running status (not just config status)
22
- */
23
17
  async function getActualStatus(
24
18
  config: ContainerConfig,
25
19
  ): Promise<'running' | 'stopped'> {
@@ -29,9 +23,6 @@ async function getActualStatus(
29
23
  return running ? 'running' : 'stopped'
30
24
  }
31
25
 
32
- /**
33
- * Display info for a single container
34
- */
35
26
  async function displayContainerInfo(
36
27
  config: ContainerConfig,
37
28
  options: { json?: boolean },
@@ -109,15 +100,11 @@ async function displayContainerInfo(
109
100
  console.log()
110
101
  }
111
102
 
112
- /**
113
- * Display summary info for all containers
114
- */
115
103
  async function displayAllContainersInfo(
116
104
  containers: ContainerConfig[],
117
105
  options: { json?: boolean },
118
106
  ): Promise<void> {
119
107
  if (options.json) {
120
- // Get actual status for all containers
121
108
  const containersWithStatus = await Promise.all(
122
109
  containers.map(async (config) => {
123
110
  const actualStatus = await getActualStatus(config)
@@ -142,7 +129,6 @@ async function displayAllContainersInfo(
142
129
  console.log(header('All Containers'))
143
130
  console.log()
144
131
 
145
- // Table header
146
132
  console.log(
147
133
  chalk.gray(' ') +
148
134
  chalk.bold.white('NAME'.padEnd(18)) +
@@ -154,7 +140,6 @@ async function displayAllContainersInfo(
154
140
  )
155
141
  console.log(chalk.gray(' ' + '─'.repeat(78)))
156
142
 
157
- // Table rows
158
143
  for (const container of containers) {
159
144
  const actualStatus = await getActualStatus(container)
160
145
  const statusDisplay =
@@ -178,7 +163,6 @@ async function displayAllContainersInfo(
178
163
 
179
164
  console.log()
180
165
 
181
- // Summary
182
166
  const statusChecks = await Promise.all(
183
167
  containers.map((c) => getActualStatus(c)),
184
168
  )
@@ -192,7 +176,6 @@ async function displayAllContainersInfo(
192
176
  )
193
177
  console.log()
194
178
 
195
- // Connection strings
196
179
  console.log(chalk.bold.white(' Connection Strings:'))
197
180
  console.log(chalk.gray(' ' + '─'.repeat(78)))
198
181
  for (const container of containers) {
@@ -221,7 +204,6 @@ export const infoCommand = new Command('info')
221
204
  return
222
205
  }
223
206
 
224
- // If name provided, show single container
225
207
  if (name) {
226
208
  const config = await containerManager.getConfig(name)
227
209
  if (!config) {
@@ -232,7 +214,6 @@ export const infoCommand = new Command('info')
232
214
  return
233
215
  }
234
216
 
235
- // If running interactively without name, ask if they want all or specific
236
217
  if (!options.json && process.stdout.isTTY && containers.length > 1) {
237
218
  const { choice } = await inquirer.prompt<{
238
219
  choice: string
@@ -262,7 +243,6 @@ export const infoCommand = new Command('info')
262
243
  return
263
244
  }
264
245
 
265
- // Non-interactive or only one container: show all
266
246
  await displayAllContainersInfo(containers, options)
267
247
  } catch (err) {
268
248
  const e = err as Error
@@ -6,9 +6,6 @@ import { info, error, formatBytes } from '../ui/theme'
6
6
  import { getEngineIcon } from '../constants'
7
7
  import type { ContainerConfig } from '../../types'
8
8
 
9
- /**
10
- * Get database size for a container (only if running)
11
- */
12
9
  async function getContainerSize(
13
10
  container: ContainerConfig,
14
11
  ): Promise<number | null> {
@@ -32,7 +29,6 @@ export const listCommand = new Command('list')
32
29
  const containers = await containerManager.list()
33
30
 
34
31
  if (options.json) {
35
- // Include sizes in JSON output
36
32
  const containersWithSize = await Promise.all(
37
33
  containers.map(async (container) => ({
38
34
  ...container,
@@ -48,10 +44,8 @@ export const listCommand = new Command('list')
48
44
  return
49
45
  }
50
46
 
51
- // Fetch sizes for running containers in parallel
52
47
  const sizes = await Promise.all(containers.map(getContainerSize))
53
48
 
54
- // Table header
55
49
  console.log()
56
50
  console.log(
57
51
  chalk.gray(' ') +
@@ -64,7 +58,6 @@ export const listCommand = new Command('list')
64
58
  )
65
59
  console.log(chalk.gray(' ' + '─'.repeat(73)))
66
60
 
67
- // Table rows
68
61
  for (let i = 0; i < containers.length; i++) {
69
62
  const container = containers[i]
70
63
  const size = sizes[i]
@@ -77,7 +70,6 @@ export const listCommand = new Command('list')
77
70
  const engineIcon = getEngineIcon(container.engine)
78
71
  const engineDisplay = `${engineIcon} ${container.engine}`
79
72
 
80
- // Format size: show value if running, dash if stopped
81
73
  const sizeDisplay = size !== null ? formatBytes(size) : chalk.gray('—')
82
74
 
83
75
  console.log(
@@ -93,7 +85,6 @@ export const listCommand = new Command('list')
93
85
 
94
86
  console.log()
95
87
 
96
- // Summary
97
88
  const running = containers.filter((c) => c.status === 'running').length
98
89
  const stopped = containers.filter((c) => c.status !== 'running').length
99
90
  console.log(
@@ -7,12 +7,8 @@ import { paths } from '../../config/paths'
7
7
  import { promptContainerSelect } from '../ui/prompts'
8
8
  import { error, warning, info } from '../ui/theme'
9
9
 
10
- /**
11
- * Get the last N lines from a file content
12
- */
13
10
  function getLastNLines(content: string, n: number): string {
14
11
  const lines = content.split('\n')
15
- // Filter empty trailing line if present
16
12
  const nonEmptyLines =
17
13
  lines[lines.length - 1] === '' ? lines.slice(0, -1) : lines
18
14
  return nonEmptyLines.slice(-n).join('\n')
@@ -32,7 +28,6 @@ export const logsCommand = new Command('logs')
32
28
  try {
33
29
  let containerName = name
34
30
 
35
- // Interactive selection if no name provided
36
31
  if (!containerName) {
37
32
  const containers = await containerManager.list()
38
33
 
@@ -49,19 +44,16 @@ export const logsCommand = new Command('logs')
49
44
  containerName = selected
50
45
  }
51
46
 
52
- // Get container config
53
47
  const config = await containerManager.getConfig(containerName)
54
48
  if (!config) {
55
49
  console.error(error(`Container "${containerName}" not found`))
56
50
  process.exit(1)
57
51
  }
58
52
 
59
- // Get log file path
60
53
  const logPath = paths.getContainerLogPath(config.name, {
61
54
  engine: config.engine,
62
55
  })
63
56
 
64
- // Check if log file exists
65
57
  if (!existsSync(logPath)) {
66
58
  console.log(
67
59
  info(
@@ -71,7 +63,6 @@ export const logsCommand = new Command('logs')
71
63
  return
72
64
  }
73
65
 
74
- // Open in editor if requested
75
66
  if (options.editor) {
76
67
  const editorCmd = process.env.EDITOR || 'vi'
77
68
  const child = spawn(editorCmd, [logPath], {
@@ -91,14 +82,12 @@ export const logsCommand = new Command('logs')
91
82
  return
92
83
  }
93
84
 
94
- // Follow mode using tail -f
95
85
  if (options.follow) {
96
86
  const lineCount = parseInt(options.lines || '50', 10)
97
87
  const child = spawn('tail', ['-n', String(lineCount), '-f', logPath], {
98
88
  stdio: 'inherit',
99
89
  })
100
90
 
101
- // Handle SIGINT gracefully
102
91
  process.on('SIGINT', () => {
103
92
  child.kill('SIGTERM')
104
93
  process.exit(0)
@@ -110,7 +99,6 @@ export const logsCommand = new Command('logs')
110
99
  return
111
100
  }
112
101
 
113
- // Default: read and output last N lines
114
102
  const lineCount = parseInt(options.lines || '50', 10)
115
103
  const content = await readFile(logPath, 'utf-8')
116
104