create-manifest 1.3.1 → 1.3.3

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.
@@ -1,6 +1,6 @@
1
1
  import { Args, Command, Flags } from '@oclif/core';
2
2
  import axios from 'axios';
3
- import { exec as execCp } from 'node:child_process';
3
+ import { exec as execCp, spawn } from 'node:child_process';
4
4
  import * as fs from 'node:fs';
5
5
  import * as crypto from 'node:crypto';
6
6
  import * as path from 'node:path';
@@ -18,6 +18,42 @@ import { input } from '@inquirer/prompts';
18
18
  import { slugify } from '../utils/helpers.js';
19
19
  import chalk from 'chalk';
20
20
  const exec = promisify(execCp);
21
+ /**
22
+ * Execute a command in a specific directory with cross-platform support
23
+ * @param command - The command to execute
24
+ * @param cwd - The working directory
25
+ * @returns Promise with stdout and stderr
26
+ */
27
+ async function execInDirectory(command, cwd) {
28
+ return exec(command, { cwd });
29
+ }
30
+ /**
31
+ * Spawn a command in a specific directory that runs in the background
32
+ * @param command - The command to execute
33
+ * @param args - The command arguments
34
+ * @param cwd - The working directory
35
+ * @returns ChildProcess
36
+ */
37
+ function spawnInDirectory(command, args, cwd) {
38
+ const isWindows = process.platform === 'win32';
39
+ if (isWindows) {
40
+ // On Windows, use shell to resolve npm command
41
+ return spawn(command, args, {
42
+ cwd,
43
+ stdio: 'pipe',
44
+ detached: false,
45
+ shell: true
46
+ });
47
+ }
48
+ else {
49
+ // On Unix systems, spawn directly
50
+ return spawn(command, args, {
51
+ cwd,
52
+ stdio: 'pipe',
53
+ detached: false
54
+ });
55
+ }
56
+ }
21
57
  export default class CreateManifest extends Command {
22
58
  static description = 'Create a new Manifest project with the default files and folders.';
23
59
  static args = {
@@ -194,7 +230,7 @@ export default class CreateManifest extends Command {
194
230
  fileContent: settingsJson,
195
231
  settings: {
196
232
  'yaml.schemas': {
197
- 'https://schema.manifest.build/schema.json': '**/manifest/**.yml'
233
+ 'https://schema.manifest.build/schema.json': '**/manifest.yml'
198
234
  }
199
235
  }
200
236
  }));
@@ -298,7 +334,7 @@ export default class CreateManifest extends Command {
298
334
  spinner.start('Installing dependencies...');
299
335
  // Install deps.
300
336
  try {
301
- await exec(`cd ${projectName} && npm install --silent`);
337
+ await execInDirectory(`npm install --silent`, projectName);
302
338
  }
303
339
  catch (error) {
304
340
  spinner.fail(`Execution error: ${error}`);
@@ -322,19 +358,30 @@ export default class CreateManifest extends Command {
322
358
  fs.writeFileSync(envFilePath, envContent);
323
359
  spinner.succeed();
324
360
  spinner.start('Building the database...');
325
- let serveTask = null;
361
+ let serverProcess = null;
326
362
  try {
327
- // We run the manifest script to build the database.
328
- serveTask = exec(`cd ${projectName} && npm run start`);
363
+ // We run the manifest script to build the database in the background
364
+ serverProcess = spawnInDirectory('npm', ['run', 'start'], projectName);
365
+ // Wait for the server to be ready
329
366
  await this.waitForServerToBeReady();
330
367
  spinner.succeed();
331
368
  }
332
369
  catch (error) {
333
370
  spinner.fail(`Execution error: ${error}`);
371
+ // If server failed to start, try to kill it
372
+ if (serverProcess && serverProcess.pid) {
373
+ try {
374
+ await this.silentKill(serverProcess.pid);
375
+ }
376
+ catch {
377
+ // Ignore errors when killing the process
378
+ }
379
+ }
380
+ throw error;
334
381
  }
335
382
  spinner.start('Seeding initial data...');
336
383
  try {
337
- await exec(`cd ${projectName} && npm run seed`);
384
+ await execInDirectory(`npm run seed`, projectName);
338
385
  }
339
386
  catch (error) {
340
387
  spinner.fail(`Execution error: ${error}`);
@@ -348,7 +395,15 @@ export default class CreateManifest extends Command {
348
395
  console.log(chalk.bold(` cd ${projectName}`));
349
396
  console.log(chalk.bold(' npm run start'));
350
397
  console.log();
351
- await this.silentKill(serveTask?.child?.pid || 0);
398
+ // Kill the background server process if it exists
399
+ if (serverProcess && serverProcess.pid) {
400
+ try {
401
+ await this.silentKill(serverProcess.pid);
402
+ }
403
+ catch {
404
+ // Ignore errors when killing the process
405
+ }
406
+ }
352
407
  process.exit();
353
408
  }
354
409
  /**
@@ -358,10 +413,16 @@ export default class CreateManifest extends Command {
358
413
  *
359
414
  **/
360
415
  async isServerReady() {
361
- return axios
362
- .get('http://localhost:1111/api/health')
363
- .then(() => true)
364
- .catch(() => false);
416
+ try {
417
+ const response = await axios.get('http://localhost:1111/api/health', {
418
+ timeout: 5000 // 5 second timeout
419
+ });
420
+ return response.status === 200;
421
+ }
422
+ catch {
423
+ // Server is not ready yet
424
+ return false;
425
+ }
365
426
  }
366
427
  /**
367
428
  * Wait for the server to be ready.
@@ -371,12 +432,18 @@ export default class CreateManifest extends Command {
371
432
  **/
372
433
  async waitForServerToBeReady() {
373
434
  let serverReady = false;
374
- while (!serverReady) {
435
+ let attempts = 0;
436
+ const maxAttempts = 30; // 30 seconds timeout
437
+ while (!serverReady && attempts < maxAttempts) {
375
438
  serverReady = await this.isServerReady();
376
439
  if (!serverReady) {
440
+ attempts++;
377
441
  await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait 1s before retrying
378
442
  }
379
443
  }
444
+ if (!serverReady) {
445
+ throw new Error('Server failed to start within 30 seconds');
446
+ }
380
447
  }
381
448
  /**
382
449
  * Transform a JSON with comments to a JSON without comments.
@@ -43,5 +43,5 @@
43
43
  "enableJsonFlag": false
44
44
  }
45
45
  },
46
- "version": "1.3.1"
46
+ "version": "1.3.3"
47
47
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-manifest",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "author": "Manifest",
5
5
  "description": "Create a new Manifest backend",
6
6
  "homepage": "https://manifest.build",