bs9 1.5.5 → 1.5.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bs9",
3
- "version": "1.5.5",
3
+ "version": "1.5.7",
4
4
  "description": "Bun Sentinel 9 - High-performance, non-root process manager for Bun",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -110,6 +110,22 @@ async function handleMultiServiceStart(file: string, options: StartOptions): Pro
110
110
  async function handleSingleServiceStart(file: string, options: StartOptions): Promise<void> {
111
111
  const platformInfo = getPlatformInfo();
112
112
 
113
+ // First, try to start existing service without file
114
+ const serviceName = options.name || file;
115
+
116
+ const serviceExists = await checkServiceExists(serviceName, platformInfo);
117
+
118
+ if (serviceExists) {
119
+ console.log(`📋 Service '${serviceName}' already exists, starting...`);
120
+ try {
121
+ await startExistingService(serviceName, platformInfo);
122
+ return;
123
+ } catch (error) {
124
+ console.log(`⚠️ Failed to start existing service: ${error}`);
125
+ console.log(`📁 Looking for application file: ${file}`);
126
+ }
127
+ }
128
+
113
129
  // Security: Validate and sanitize file path
114
130
  const fullPath = resolve(file);
115
131
  if (!existsSync(fullPath)) {
@@ -127,7 +143,7 @@ async function handleSingleServiceStart(file: string, options: StartOptions): Pr
127
143
 
128
144
  // Security: Validate and sanitize service name
129
145
  const rawServiceName = options.name || basename(fullPath, fullPath.endsWith('.ts') ? '.ts' : '.js');
130
- const serviceName = rawServiceName.replace(/[^a-zA-Z0-9-_]/g, "_").replace(/^[^a-zA-Z]/, "_").substring(0, 64);
146
+ const finalServiceName = rawServiceName.replace(/[^a-zA-Z0-9-_]/g, "_").replace(/^[^a-zA-Z]/, "_").substring(0, 64);
131
147
 
132
148
  // Security: Validate port number
133
149
  const port = options.port || "3000";
@@ -170,7 +186,7 @@ async function handleSingleServiceStart(file: string, options: StartOptions): Pr
170
186
  const buildDir = join(dirname(fullPath), ".bs9-build");
171
187
  mkdirSync(buildDir, { recursive: true });
172
188
 
173
- const outputFile = join(buildDir, `${serviceName}.js`);
189
+ const outputFile = join(buildDir, `${finalServiceName}.js`);
174
190
  try {
175
191
  execSync(`bun build ${fullPath} --outdir ${buildDir} --target bun --minify --splitting`, { stdio: "inherit" });
176
192
  execPath = outputFile;
@@ -202,17 +218,61 @@ async function handleSingleServiceStart(file: string, options: StartOptions): Pr
202
218
 
203
219
  // Platform-specific service creation
204
220
  if (platformInfo.isLinux) {
205
- await createLinuxService(serviceName, execPath, host, port, protocol, options);
221
+ await createLinuxService(finalServiceName, execPath, host, port, protocol, options);
206
222
  } else if (platformInfo.isMacOS) {
207
- await createMacOSService(serviceName, execPath, host, port, protocol, options);
223
+ await createMacOSService(finalServiceName, execPath, host, port, protocol, options);
208
224
  } else if (platformInfo.isWindows) {
209
- await createWindowsService(serviceName, execPath, host, port, protocol, options);
225
+ await createWindowsService(finalServiceName, execPath, host, port, protocol, options);
210
226
  } else {
211
227
  console.error(`❌ Platform ${platformInfo.platform} is not supported`);
212
228
  process.exit(1);
213
229
  }
214
230
  }
215
231
 
232
+ async function checkServiceExists(serviceName: string, platformInfo: any): Promise<boolean> {
233
+ try {
234
+ if (platformInfo.isLinux) {
235
+ // Check if service exists in systemctl list-units
236
+ const listOutput = execSync("systemctl --user list-units --type=service --all --no-pager --no-legend", { encoding: "utf-8" });
237
+ const serviceExists = listOutput.includes(`${serviceName}.service`);
238
+ return serviceExists;
239
+ } else if (platformInfo.isMacOS) {
240
+ // Check if launchd service exists
241
+ const servicePath = join(platformInfo.serviceDir, `bs9.${serviceName}.plist`);
242
+ return existsSync(servicePath);
243
+ } else if (platformInfo.isWindows) {
244
+ // Check if Windows service exists
245
+ const { windowsCommand } = await import("../windows/service.js");
246
+ try {
247
+ await windowsCommand('show', { name: `BS9_${serviceName}` });
248
+ return true;
249
+ } catch {
250
+ return false;
251
+ }
252
+ }
253
+ return false;
254
+ } catch {
255
+ return false;
256
+ }
257
+ }
258
+
259
+ async function startExistingService(serviceName: string, platformInfo: any): Promise<void> {
260
+ try {
261
+ if (platformInfo.isLinux) {
262
+ execSync(`systemctl --user start ${serviceName}`, { stdio: "inherit" });
263
+ } else if (platformInfo.isMacOS) {
264
+ const { launchdCommand } = await import("../macos/launchd.js");
265
+ await launchdCommand('start', { name: `bs9.${serviceName}` });
266
+ } else if (platformInfo.isWindows) {
267
+ const { windowsCommand } = await import("../windows/service.js");
268
+ await windowsCommand('start', { name: `BS9_${serviceName}` });
269
+ }
270
+ console.log(`🚀 Service '${serviceName}' started successfully`);
271
+ } catch (error) {
272
+ throw error;
273
+ }
274
+ }
275
+
216
276
  function findServiceFile(serviceName: string): string | null {
217
277
  // Try to find the service file in common locations
218
278
  const possiblePaths = [
@@ -281,11 +341,21 @@ async function createLinuxService(serviceName: string, execPath: string, host: s
281
341
  }
282
342
 
283
343
  try {
284
- writeFileSync(unitPath, unitContent);
285
- console.log(`✅ Systemd user unit written to: ${unitPath}`);
344
+ // Check if service already exists
345
+ const serviceExists = existsSync(unitPath);
346
+
347
+ if (!serviceExists) {
348
+ // First time: Create service file
349
+ writeFileSync(unitPath, unitContent);
350
+ console.log(`✅ Systemd user unit written to: ${unitPath}`);
351
+ execSync("systemctl --user daemon-reload");
352
+ execSync(`systemctl --user enable ${serviceName}`);
353
+ console.log(`🔧 Service '${serviceName}' created and enabled`);
354
+ } else {
355
+ console.log(`📋 Service '${serviceName}' already exists, starting...`);
356
+ }
286
357
 
287
- execSync("systemctl --user daemon-reload");
288
- execSync(`systemctl --user enable ${serviceName}`);
358
+ // Always start the service
289
359
  execSync(`systemctl --user start ${serviceName}`);
290
360
 
291
361
  console.log(`🚀 Service '${serviceName}' started successfully`);