@xyleapp/cli 0.6.0 → 0.7.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.
package/bin/xyle.mjs CHANGED
@@ -8,7 +8,7 @@ const program = new Command();
8
8
  program
9
9
  .name("xyle")
10
10
  .description("SEO Intelligence Engine CLI")
11
- .version("0.5.0");
11
+ .version("0.7.0");
12
12
 
13
13
  registerCommands(program);
14
14
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xyleapp/cli",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "CLI for the Xyle SEO Intelligence Engine",
5
5
  "type": "module",
6
6
  "bin": {
package/src/commands.mjs CHANGED
@@ -4,6 +4,9 @@
4
4
  */
5
5
 
6
6
  import { createRequire } from "node:module";
7
+ import { existsSync } from "node:fs";
8
+ import { resolve } from "node:path";
9
+ import { execSync } from "node:child_process";
7
10
  import { printJson, printTable } from "./formatting.mjs";
8
11
  import {
9
12
  checkHealth,
@@ -135,12 +138,24 @@ export function registerCommands(program) {
135
138
  } else {
136
139
  const score = data.score || 0;
137
140
  const color = score >= 0.7 ? "\x1b[32m" : "\x1b[33m";
138
- console.log(`${color}Score: ${Math.round(score * 100)}%\x1b[0m`);
141
+ console.log(`${color}SEO Score: ${Math.round(score * 100)}%\x1b[0m`);
139
142
  console.log(`Summary: ${data.summary || ""}`);
140
143
  const missing = data.missing_topics || [];
141
144
  if (missing.length) {
142
145
  console.log(`Missing topics: ${missing.join(", ")}`);
143
146
  }
147
+ // AEO Score + Recommendations
148
+ if (data.aeo_score != null) {
149
+ const aeoColor = data.aeo_score >= 0.7 ? "\x1b[32m" : "\x1b[33m";
150
+ console.log(`${aeoColor}AEO Score: ${Math.round(data.aeo_score * 100)}%\x1b[0m`);
151
+ }
152
+ const recs = data.aeo_recommendations || [];
153
+ if (recs.length) {
154
+ console.log("AEO Recommendations:");
155
+ for (const rec of recs) {
156
+ console.log(` \x1b[36m\u2192\x1b[0m ${rec}`);
157
+ }
158
+ }
144
159
  }
145
160
  } catch (e) {
146
161
  handleError(e);
@@ -194,6 +209,27 @@ export function registerCommands(program) {
194
209
  console.log(` ${h}`);
195
210
  }
196
211
  }
212
+ // AEO Signals
213
+ const aeo = data.aeo_signals;
214
+ if (aeo) {
215
+ console.log("AEO Signals:");
216
+ const check = (v) => (v ? "\x1b[32m\u2713\x1b[0m" : "\x1b[31m\u2717\x1b[0m");
217
+ console.log(
218
+ ` ${check(aeo.has_article_schema)} Article Schema ${check(aeo.has_faq_schema)} FAQPage Schema ${check(aeo.has_howto_schema)} HowTo Schema`
219
+ );
220
+ console.log(
221
+ ` ${check(aeo.heading_hierarchy_valid)} Heading Hierarchy ${check(aeo.has_faq_content)} FAQ Content ${check(aeo.has_date_modified)} Date Modified`
222
+ );
223
+ console.log(
224
+ ` ${check(aeo.has_speakable_schema)} Speakable Schema`
225
+ );
226
+ console.log(
227
+ ` Lists: ${aeo.list_count} Tables: ${aeo.table_count} Concise answers: ${aeo.concise_answer_count} Definitions: ${aeo.definition_count} Citations: ${aeo.citation_count}`
228
+ );
229
+ if (aeo.avg_sentence_length > 0) {
230
+ console.log(` Avg sentence length: ${aeo.avg_sentence_length} words`);
231
+ }
232
+ }
197
233
  const wc = data.word_count || 0;
198
234
  if (wc > 0 && wc < 50) {
199
235
  console.log(
@@ -435,4 +471,38 @@ export function registerCommands(program) {
435
471
  );
436
472
  }
437
473
  });
474
+
475
+ // --- deploy ---
476
+ program
477
+ .command("deploy")
478
+ .description("Deploy Xyle services (API, frontend, trigger.dev)")
479
+ .option("--api", "Deploy API to Cloud Run")
480
+ .option("--frontend", "Deploy frontend to Vercel")
481
+ .option("--trigger", "Deploy Trigger.dev tasks")
482
+ .option("--dir <path>", "Project root directory", process.cwd())
483
+ .action(async (opts) => {
484
+ const scriptPath = resolve(opts.dir, "scripts", "deploy.sh");
485
+ if (!existsSync(scriptPath)) {
486
+ process.stderr.write(
487
+ `\x1b[31mDeploy script not found: ${scriptPath}\x1b[0m\n` +
488
+ `\x1b[2mRun this command from the project root or use --dir <path>\x1b[0m\n`
489
+ );
490
+ process.exit(1);
491
+ }
492
+
493
+ const flags = [];
494
+ if (opts.api) flags.push("--api");
495
+ if (opts.frontend) flags.push("--frontend");
496
+ if (opts.trigger) flags.push("--trigger");
497
+ // No flags = deploy all (script's default behavior)
498
+
499
+ const cmd = `bash "${scriptPath}" ${flags.join(" ")}`;
500
+ console.log(`\x1b[36mRunning:\x1b[0m ${cmd}\n`);
501
+ try {
502
+ execSync(cmd, { stdio: "inherit", cwd: opts.dir });
503
+ } catch (e) {
504
+ process.stderr.write(`\x1b[31mDeploy failed.\x1b[0m\n`);
505
+ process.exit(e.status || 1);
506
+ }
507
+ });
438
508
  }