@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 +1 -1
- package/package.json +1 -1
- package/src/commands.mjs +71 -1
package/bin/xyle.mjs
CHANGED
package/package.json
CHANGED
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
|
}
|