@actuate-media/cli 0.4.1 → 0.4.2

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 (77) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-test.log +21 -10
  3. package/CHANGELOG.md +28 -0
  4. package/dist/__tests__/deployment-diagnostics.test.js.map +1 -1
  5. package/dist/__tests__/init.test.js.map +1 -1
  6. package/dist/__tests__/schema-fragment.test.js +1 -1
  7. package/dist/__tests__/schema-fragment.test.js.map +1 -1
  8. package/dist/__tests__/seed.test.js.map +1 -1
  9. package/dist/commands/db-init.d.ts +2 -2
  10. package/dist/commands/db-init.d.ts.map +1 -1
  11. package/dist/commands/db-init.js +32 -32
  12. package/dist/commands/db-init.js.map +1 -1
  13. package/dist/commands/db-status.d.ts +1 -1
  14. package/dist/commands/db-status.d.ts.map +1 -1
  15. package/dist/commands/db-status.js +33 -33
  16. package/dist/commands/db-status.js.map +1 -1
  17. package/dist/commands/doctor.d.ts +1 -1
  18. package/dist/commands/doctor.d.ts.map +1 -1
  19. package/dist/commands/doctor.js +48 -41
  20. package/dist/commands/doctor.js.map +1 -1
  21. package/dist/commands/export.d.ts +1 -1
  22. package/dist/commands/export.d.ts.map +1 -1
  23. package/dist/commands/export.js +32 -32
  24. package/dist/commands/export.js.map +1 -1
  25. package/dist/commands/generate.d.ts +1 -1
  26. package/dist/commands/generate.d.ts.map +1 -1
  27. package/dist/commands/generate.js +8 -8
  28. package/dist/commands/generate.js.map +1 -1
  29. package/dist/commands/import.d.ts +1 -1
  30. package/dist/commands/import.d.ts.map +1 -1
  31. package/dist/commands/import.js +55 -58
  32. package/dist/commands/import.js.map +1 -1
  33. package/dist/commands/init.d.ts.map +1 -1
  34. package/dist/commands/init.js.map +1 -1
  35. package/dist/commands/migrate.d.ts +1 -1
  36. package/dist/commands/migrate.d.ts.map +1 -1
  37. package/dist/commands/migrate.js +18 -24
  38. package/dist/commands/migrate.js.map +1 -1
  39. package/dist/commands/seed.d.ts +1 -1
  40. package/dist/commands/seed.d.ts.map +1 -1
  41. package/dist/commands/seed.js +156 -157
  42. package/dist/commands/seed.js.map +1 -1
  43. package/dist/commands/update-check.d.ts +1 -1
  44. package/dist/commands/update-check.d.ts.map +1 -1
  45. package/dist/commands/update-check.js +34 -27
  46. package/dist/commands/update-check.js.map +1 -1
  47. package/dist/commands/upgrade.d.ts +1 -1
  48. package/dist/commands/upgrade.d.ts.map +1 -1
  49. package/dist/commands/upgrade.js +41 -34
  50. package/dist/commands/upgrade.js.map +1 -1
  51. package/dist/deployment/diagnostics.d.ts.map +1 -1
  52. package/dist/deployment/diagnostics.js +7 -2
  53. package/dist/deployment/diagnostics.js.map +1 -1
  54. package/dist/index.js +15 -15
  55. package/dist/index.js.map +1 -1
  56. package/dist/utils/logger.d.ts.map +1 -1
  57. package/dist/utils/logger.js +5 -5
  58. package/dist/utils/logger.js.map +1 -1
  59. package/package.json +3 -3
  60. package/src/__tests__/deployment-diagnostics.test.ts +68 -60
  61. package/src/__tests__/init.test.ts +17 -17
  62. package/src/__tests__/schema-fragment.test.ts +29 -25
  63. package/src/__tests__/seed.test.ts +25 -25
  64. package/src/commands/db-init.ts +59 -59
  65. package/src/commands/db-status.ts +70 -68
  66. package/src/commands/doctor.ts +102 -88
  67. package/src/commands/export.ts +65 -75
  68. package/src/commands/generate.ts +14 -16
  69. package/src/commands/import.ts +125 -140
  70. package/src/commands/init.ts +14 -14
  71. package/src/commands/migrate.ts +29 -35
  72. package/src/commands/seed.ts +294 -300
  73. package/src/commands/update-check.ts +77 -72
  74. package/src/commands/upgrade.ts +92 -85
  75. package/src/deployment/diagnostics.ts +86 -72
  76. package/src/index.ts +30 -30
  77. package/src/utils/logger.ts +10 -10
@@ -1,120 +1,122 @@
1
- import { Command } from "commander";
2
- import { execSync } from "node:child_process";
3
- import { readFile, access } from "node:fs/promises";
4
- import { resolve } from "node:path";
5
- import ora from "ora";
6
- import chalk from "chalk";
7
- import { logger } from "../utils/logger.js";
8
- import { REQUIRED_CMS_MODELS } from "../deployment/diagnostics.js";
1
+ import { Command } from 'commander'
2
+ import { execSync } from 'node:child_process'
3
+ import { readFile, access } from 'node:fs/promises'
4
+ import { resolve } from 'node:path'
5
+ import ora from 'ora'
6
+ import chalk from 'chalk'
7
+ import { logger } from '../utils/logger.js'
8
+ import { REQUIRED_CMS_MODELS } from '../deployment/diagnostics.js'
9
9
 
10
- const CMS_SCHEMA_MARKER = "// ── Actuate CMS models";
10
+ const CMS_SCHEMA_MARKER = '// ── Actuate CMS models'
11
11
 
12
12
  async function fileExists(filePath: string): Promise<boolean> {
13
13
  try {
14
- await access(filePath);
15
- return true;
14
+ await access(filePath)
15
+ return true
16
16
  } catch {
17
- return false;
17
+ return false
18
18
  }
19
19
  }
20
20
 
21
21
  export function registerDbStatusCommand(program: Command): void {
22
22
  program
23
- .command("db:status")
24
- .description("Check which Actuate CMS models are present in your Prisma schema")
25
- .option("--schema <path>", "Path to schema.prisma", "prisma/schema.prisma")
23
+ .command('db:status')
24
+ .description('Check which Actuate CMS models are present in your Prisma schema')
25
+ .option('--schema <path>', 'Path to schema.prisma', 'prisma/schema.prisma')
26
26
  .action(async (opts: { schema: string }) => {
27
- const schemaPath = resolve(process.cwd(), opts.schema);
27
+ const schemaPath = resolve(process.cwd(), opts.schema)
28
28
 
29
29
  if (!(await fileExists(schemaPath))) {
30
- logger.error(`Schema file not found at ${schemaPath}`);
31
- logger.info("Run `npx prisma init` first, or specify --schema <path>.");
32
- process.exitCode = 1;
33
- return;
30
+ logger.error(`Schema file not found at ${schemaPath}`)
31
+ logger.info('Run `npx prisma init` first, or specify --schema <path>.')
32
+ process.exitCode = 1
33
+ return
34
34
  }
35
35
 
36
- const spinner = ora("Checking schema...").start();
36
+ const spinner = ora('Checking schema...').start()
37
37
 
38
- let content: string;
38
+ let content: string
39
39
  try {
40
- content = await readFile(schemaPath, "utf-8");
40
+ content = await readFile(schemaPath, 'utf-8')
41
41
  } catch (err) {
42
- spinner.fail("Failed to read schema file.");
43
- logger.error(err instanceof Error ? err.message : String(err));
44
- process.exitCode = 1;
45
- return;
42
+ spinner.fail('Failed to read schema file.')
43
+ logger.error(err instanceof Error ? err.message : String(err))
44
+ process.exitCode = 1
45
+ return
46
46
  }
47
47
 
48
- spinner.stop();
48
+ spinner.stop()
49
49
 
50
- const hasMarker = content.includes(CMS_SCHEMA_MARKER);
51
- const modelRegex = /^model\s+(\w+)\s*\{/gm;
52
- const schemaModels = new Set<string>();
53
- let match;
50
+ const hasMarker = content.includes(CMS_SCHEMA_MARKER)
51
+ const modelRegex = /^model\s+(\w+)\s*\{/gm
52
+ const schemaModels = new Set<string>()
53
+ let match
54
54
  while ((match = modelRegex.exec(content)) !== null) {
55
- schemaModels.add(match[1]!);
55
+ schemaModels.add(match[1]!)
56
56
  }
57
57
 
58
- console.log();
59
- console.log(chalk.bold(" Actuate CMS Model Status"));
60
- console.log(chalk.dim(" ─────────────────────────────────"));
61
- console.log();
58
+ console.log()
59
+ console.log(chalk.bold(' Actuate CMS Model Status'))
60
+ console.log(chalk.dim(' ─────────────────────────────────'))
61
+ console.log()
62
62
 
63
- let present = 0;
64
- let missing = 0;
63
+ let present = 0
64
+ let missing = 0
65
65
 
66
66
  for (const model of REQUIRED_CMS_MODELS) {
67
67
  if (schemaModels.has(model)) {
68
- console.log(` ${chalk.green("")} ${model}`);
69
- present++;
68
+ console.log(` ${chalk.green('')} ${model}`)
69
+ present++
70
70
  } else {
71
- console.log(` ${chalk.red("")} ${model} ${chalk.dim("— missing")}`);
72
- missing++;
71
+ console.log(` ${chalk.red('')} ${model} ${chalk.dim('— missing')}`)
72
+ missing++
73
73
  }
74
74
  }
75
75
 
76
- console.log();
77
- console.log(chalk.dim(" ─────────────────────────────────"));
78
- console.log(` ${chalk.green(present)} present, ${missing > 0 ? chalk.red(missing) : chalk.green(missing)} missing`);
76
+ console.log()
77
+ console.log(chalk.dim(' ─────────────────────────────────'))
78
+ console.log(
79
+ ` ${chalk.green(present)} present, ${missing > 0 ? chalk.red(missing) : chalk.green(missing)} missing`,
80
+ )
79
81
 
80
82
  if (!hasMarker) {
81
- console.log();
82
- logger.warn("CMS schema marker not found. Models may have been added manually.");
83
- logger.info("Run `actuate db:init` to add CMS models with proper markers.");
83
+ console.log()
84
+ logger.warn('CMS schema marker not found. Models may have been added manually.')
85
+ logger.info('Run `actuate db:init` to add CMS models with proper markers.')
84
86
  }
85
87
 
86
88
  if (missing > 0) {
87
- console.log();
88
- logger.info("Run `actuate db:init` to add missing models.");
89
+ console.log()
90
+ logger.info('Run `actuate db:init` to add missing models.')
89
91
  }
90
92
 
91
- let dbConnected = false;
93
+ let dbConnected = false
92
94
  try {
93
- spinner.start("Checking database connection...");
94
- execSync("npx prisma db execute --stdin --schema " + JSON.stringify(schemaPath), {
95
- input: "SELECT 1;",
96
- stdio: ["pipe", "pipe", "pipe"],
95
+ spinner.start('Checking database connection...')
96
+ execSync('npx prisma db execute --stdin --schema ' + JSON.stringify(schemaPath), {
97
+ input: 'SELECT 1;',
98
+ stdio: ['pipe', 'pipe', 'pipe'],
97
99
  cwd: process.cwd(),
98
- });
99
- spinner.succeed("Database connection OK.");
100
- dbConnected = true;
100
+ })
101
+ spinner.succeed('Database connection OK.')
102
+ dbConnected = true
101
103
  } catch {
102
- spinner.warn("Could not connect to database. Check DATABASE_URL.");
104
+ spinner.warn('Could not connect to database. Check DATABASE_URL.')
103
105
  }
104
106
 
105
107
  if (dbConnected && missing === 0) {
106
108
  try {
107
- spinner.start("Checking migration status...");
108
- spinner.stop();
109
- execSync("npx prisma migrate status", {
110
- stdio: "inherit",
109
+ spinner.start('Checking migration status...')
110
+ spinner.stop()
111
+ execSync('npx prisma migrate status', {
112
+ stdio: 'inherit',
111
113
  cwd: process.cwd(),
112
- });
114
+ })
113
115
  } catch {
114
- logger.warn("Could not check migration status.");
116
+ logger.warn('Could not check migration status.')
115
117
  }
116
118
  }
117
119
 
118
- console.log();
119
- });
120
+ console.log()
121
+ })
120
122
  }
@@ -1,74 +1,83 @@
1
- import { Command } from "commander";
2
- import { access, readdir, readFile } from "node:fs/promises";
3
- import { resolve } from "node:path";
4
- import chalk from "chalk";
1
+ import { Command } from 'commander'
2
+ import { access, readdir, readFile } from 'node:fs/promises'
3
+ import { resolve } from 'node:path'
4
+ import chalk from 'chalk'
5
5
  import {
6
6
  buildDeploymentManifest,
7
7
  createDiagnosticReport,
8
8
  detectPackageManager,
9
9
  type DiagnosticReport,
10
- } from "../deployment/diagnostics.js";
10
+ } from '../deployment/diagnostics.js'
11
11
 
12
12
  async function fileExists(path: string): Promise<boolean> {
13
13
  try {
14
- await access(path);
15
- return true;
14
+ await access(path)
15
+ return true
16
16
  } catch {
17
- return false;
17
+ return false
18
18
  }
19
19
  }
20
20
 
21
21
  async function readSchemaModels(schemaPath: string): Promise<Set<string>> {
22
- if (!(await fileExists(schemaPath))) return new Set();
23
- const schema = await readFile(schemaPath, "utf-8");
24
- const models = new Set<string>();
25
- const modelRegex = /^model\s+(\w+)\s*\{/gm;
26
- let match;
22
+ if (!(await fileExists(schemaPath))) return new Set()
23
+ const schema = await readFile(schemaPath, 'utf-8')
24
+ const models = new Set<string>()
25
+ const modelRegex = /^model\s+(\w+)\s*\{/gm
26
+ let match
27
27
  while ((match = modelRegex.exec(schema)) !== null) {
28
- models.add(match[1]!);
28
+ models.add(match[1]!)
29
29
  }
30
- return models;
30
+ return models
31
31
  }
32
32
 
33
33
  async function readSchemaContent(schemaPath: string): Promise<string> {
34
- if (!(await fileExists(schemaPath))) return "";
35
- return readFile(schemaPath, "utf-8");
34
+ if (!(await fileExists(schemaPath))) return ''
35
+ return readFile(schemaPath, 'utf-8')
36
36
  }
37
37
 
38
38
  async function readOptionalFile(path: string): Promise<string> {
39
- if (!(await fileExists(path))) return "";
40
- return readFile(path, "utf-8");
39
+ if (!(await fileExists(path))) return ''
40
+ return readFile(path, 'utf-8')
41
41
  }
42
42
 
43
43
  async function detectProjectPackageManager(): Promise<string> {
44
- const entries = new Set(await readdir(process.cwd()));
45
- return detectPackageManager(entries);
44
+ const entries = new Set(await readdir(process.cwd()))
45
+ return detectPackageManager(entries)
46
46
  }
47
47
 
48
48
  function printReport(title: string, report: DiagnosticReport): void {
49
- console.log();
50
- console.log(chalk.bold(title));
51
- console.log(chalk.dim("─────────────────────────────────"));
49
+ console.log()
50
+ console.log(chalk.bold(title))
51
+ console.log(chalk.dim('─────────────────────────────────'))
52
52
  for (const check of report.checks) {
53
- const icon = check.status === "pass" ? chalk.green("PASS") : check.status === "warn" ? chalk.yellow("WARN") : chalk.red("FAIL");
54
- console.log(`${icon} ${check.label}: ${check.message}`);
55
- if (check.fix) console.log(chalk.dim(` Fix: ${check.fix}`));
56
- if (check.docs) console.log(chalk.dim(` Docs: ${check.docs}`));
53
+ const icon =
54
+ check.status === 'pass'
55
+ ? chalk.green('PASS')
56
+ : check.status === 'warn'
57
+ ? chalk.yellow('WARN')
58
+ : chalk.red('FAIL')
59
+ console.log(`${icon} ${check.label}: ${check.message}`)
60
+ if (check.fix) console.log(chalk.dim(` Fix: ${check.fix}`))
61
+ if (check.docs) console.log(chalk.dim(` Docs: ${check.docs}`))
57
62
  }
58
- console.log(chalk.dim("─────────────────────────────────"));
59
- console.log(`Status: ${report.status.toUpperCase()}`);
60
- console.log();
63
+ console.log(chalk.dim('─────────────────────────────────'))
64
+ console.log(`Status: ${report.status.toUpperCase()}`)
65
+ console.log()
61
66
  }
62
67
 
63
- async function buildReport(schemaPath: string, configPath: string, mode: "doctor" | "deploy" = "doctor") {
64
- const resolvedSchema = resolve(process.cwd(), schemaPath);
65
- const resolvedConfig = resolve(process.cwd(), configPath);
68
+ async function buildReport(
69
+ schemaPath: string,
70
+ configPath: string,
71
+ mode: 'doctor' | 'deploy' = 'doctor',
72
+ ) {
73
+ const resolvedSchema = resolve(process.cwd(), schemaPath)
74
+ const resolvedConfig = resolve(process.cwd(), configPath)
66
75
  const [schemaModels, schemaContent, configContent, packageManager] = await Promise.all([
67
76
  readSchemaModels(resolvedSchema),
68
77
  readSchemaContent(resolvedSchema),
69
78
  readOptionalFile(resolvedConfig),
70
79
  detectProjectPackageManager(),
71
- ]);
80
+ ])
72
81
 
73
82
  return createDiagnosticReport({
74
83
  schemaModels,
@@ -78,92 +87,97 @@ async function buildReport(schemaPath: string, configPath: string, mode: "doctor
78
87
  packageManager,
79
88
  schemaPath,
80
89
  mode,
81
- });
90
+ })
82
91
  }
83
92
 
84
93
  export function registerDoctorCommand(program: Command): void {
85
94
  program
86
- .command("doctor")
87
- .description("Run AI-friendly preflight checks for an Actuate CMS project")
88
- .option("--schema <path>", "Path to schema.prisma", "prisma/schema.prisma")
89
- .option("--config <path>", "Path to actuate.config.ts", "actuate.config.ts")
90
- .option("--json", "Print machine-readable JSON")
95
+ .command('doctor')
96
+ .description('Run AI-friendly preflight checks for an Actuate CMS project')
97
+ .option('--schema <path>', 'Path to schema.prisma', 'prisma/schema.prisma')
98
+ .option('--config <path>', 'Path to actuate.config.ts', 'actuate.config.ts')
99
+ .option('--json', 'Print machine-readable JSON')
91
100
  .action(async (opts: { schema: string; config: string; json?: boolean }) => {
92
- const report = await buildReport(opts.schema, opts.config, "doctor");
101
+ const report = await buildReport(opts.schema, opts.config, 'doctor')
93
102
  if (opts.json) {
94
- console.log(JSON.stringify(report, null, 2));
103
+ console.log(JSON.stringify(report, null, 2))
95
104
  } else {
96
- printReport("Actuate Doctor", report);
105
+ printReport('Actuate Doctor', report)
97
106
  }
98
- if (report.status === "fail") process.exitCode = 1;
99
- });
107
+ if (report.status === 'fail') process.exitCode = 1
108
+ })
100
109
  }
101
110
 
102
111
  export function registerDeployCheckCommand(program: Command): void {
103
112
  program
104
- .command("deploy:check")
105
- .description("Check production deployment readiness for Actuate CMS")
106
- .option("--schema <path>", "Path to schema.prisma", "prisma/schema.prisma")
107
- .option("--config <path>", "Path to actuate.config.ts", "actuate.config.ts")
108
- .option("--json", "Print machine-readable JSON")
113
+ .command('deploy:check')
114
+ .description('Check production deployment readiness for Actuate CMS')
115
+ .option('--schema <path>', 'Path to schema.prisma', 'prisma/schema.prisma')
116
+ .option('--config <path>', 'Path to actuate.config.ts', 'actuate.config.ts')
117
+ .option('--json', 'Print machine-readable JSON')
109
118
  .action(async (opts: { schema: string; config: string; json?: boolean }) => {
110
- const report = await buildReport(opts.schema, opts.config, "deploy");
119
+ const report = await buildReport(opts.schema, opts.config, 'deploy')
111
120
  if (opts.json) {
112
- console.log(JSON.stringify({ ...report, manifest: buildDeploymentManifest() }, null, 2));
121
+ console.log(JSON.stringify({ ...report, manifest: buildDeploymentManifest() }, null, 2))
113
122
  } else {
114
- printReport("Actuate Deploy Check", report);
115
- console.log(chalk.dim("Run `actuate verify --full` after deployment succeeds."));
123
+ printReport('Actuate Deploy Check', report)
124
+ console.log(chalk.dim('Run `actuate verify --full` after deployment succeeds.'))
116
125
  }
117
- if (report.status === "fail") process.exitCode = 1;
118
- });
126
+ if (report.status === 'fail') process.exitCode = 1
127
+ })
119
128
  }
120
129
 
121
130
  export function registerVerifyCommand(program: Command): void {
122
131
  program
123
- .command("verify")
124
- .description("Verify an installed or deployed Actuate CMS project")
125
- .option("--full", "Run the full verification checklist")
126
- .option("--url <origin>", "Deployed site origin to verify, for example https://example.com")
127
- .option("--json", "Print the deployment manifest as JSON")
132
+ .command('verify')
133
+ .description('Verify an installed or deployed Actuate CMS project')
134
+ .option('--full', 'Run the full verification checklist')
135
+ .option('--url <origin>', 'Deployed site origin to verify, for example https://example.com')
136
+ .option('--json', 'Print the deployment manifest as JSON')
128
137
  .action(async (opts: { full?: boolean; url?: string; json?: boolean }) => {
129
- const manifest = buildDeploymentManifest();
138
+ const manifest = buildDeploymentManifest()
130
139
  if (opts.json) {
131
- console.log(JSON.stringify(manifest, null, 2));
132
- return;
140
+ console.log(JSON.stringify(manifest, null, 2))
141
+ return
133
142
  }
134
143
 
135
- console.log();
136
- console.log(chalk.bold(opts.full ? "Actuate Full Verification" : "Actuate Verification"));
137
- console.log(chalk.dim("─────────────────────────────────"));
138
- console.log(`PASS Manifest generated for ${manifest.packageScope} packages.`);
144
+ console.log()
145
+ console.log(chalk.bold(opts.full ? 'Actuate Full Verification' : 'Actuate Verification'))
146
+ console.log(chalk.dim('─────────────────────────────────'))
147
+ console.log(`PASS Manifest generated for ${manifest.packageScope} packages.`)
139
148
  if (!opts.url) {
140
- console.log("WARN No --url provided, so remote health/admin endpoints were not checked.");
141
- console.log(chalk.dim("Run `actuate verify --full --url https://your-site.com` after deployment."));
142
- console.log();
143
- return;
149
+ console.log('WARN No --url provided, so remote health/admin endpoints were not checked.')
150
+ console.log(
151
+ chalk.dim('Run `actuate verify --full --url https://your-site.com` after deployment.'),
152
+ )
153
+ console.log()
154
+ return
144
155
  }
145
156
 
146
- const origin = opts.url.replace(/\/$/, "");
147
- const healthUrl = `${origin}${manifest.routes.apiHealth}`;
148
- const adminUrl = `${origin}${manifest.routes.adminDefault}`;
149
- let failed = false;
157
+ const origin = opts.url.replace(/\/$/, '')
158
+ const healthUrl = `${origin}${manifest.routes.apiHealth}`
159
+ const adminUrl = `${origin}${manifest.routes.adminDefault}`
160
+ let failed = false
150
161
 
151
- for (const [label, url] of [['Health', healthUrl], ['Admin', adminUrl]] as const) {
162
+ for (const [label, url] of [
163
+ ['Health', healthUrl],
164
+ ['Admin', adminUrl],
165
+ ] as const) {
152
166
  try {
153
- const response = await fetch(url, { method: 'GET' });
167
+ const response = await fetch(url, { method: 'GET' })
154
168
  if (response.ok || response.status === 302 || response.status === 401) {
155
- console.log(`PASS ${label} route responded at ${url}.`);
169
+ console.log(`PASS ${label} route responded at ${url}.`)
156
170
  } else {
157
- failed = true;
158
- console.log(`FAIL ${label} route returned HTTP ${response.status} at ${url}.`);
171
+ failed = true
172
+ console.log(`FAIL ${label} route returned HTTP ${response.status} at ${url}.`)
159
173
  }
160
174
  } catch (error) {
161
- failed = true;
162
- const message = error instanceof Error ? error.message : String(error);
163
- console.log(`FAIL ${label} route could not be reached at ${url}: ${message}`);
175
+ failed = true
176
+ const message = error instanceof Error ? error.message : String(error)
177
+ console.log(`FAIL ${label} route could not be reached at ${url}: ${message}`)
164
178
  }
165
179
  }
166
- console.log();
167
- if (failed) process.exitCode = 1;
168
- });
180
+ console.log()
181
+ if (failed) process.exitCode = 1
182
+ })
169
183
  }