aeo-ready 1.3.1 → 1.3.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.
- package/CHANGELOG.md +7 -0
- package/package.json +1 -2
- package/src/benchmark/agentic-seo.js +9 -4
- package/src/benchmark/cloudflare.js +3 -0
- package/src/benchmark/fern.js +1 -0
- package/src/scan.js +10 -5
- package/src/utils/fetch.js +0 -42
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.3.2
|
|
4
|
+
|
|
5
|
+
- Fix broken `afdocs` fix command — was calling `npx afdocs <url>` instead of `npx afdocs check <url>`
|
|
6
|
+
- Fix shell injection in `promptFix` — switched `execSync` to `execFileSync`
|
|
7
|
+
- Add test suite (`node --test`)
|
|
8
|
+
- Add GitHub Actions CI
|
|
9
|
+
|
|
3
10
|
## 1.3.1
|
|
4
11
|
|
|
5
12
|
- Add progress indicator during scan
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aeo-ready",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "AEO benchmark aggregator. One scan, every score. Collects agentic-seo, Cloudflare, and Fern in one report.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -37,7 +37,6 @@
|
|
|
37
37
|
"bin/",
|
|
38
38
|
"src/benchmark/",
|
|
39
39
|
"src/history/",
|
|
40
|
-
"src/utils/",
|
|
41
40
|
"src/index.js",
|
|
42
41
|
"src/scan.js",
|
|
43
42
|
"skills/",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execFileSync } from "child_process";
|
|
2
2
|
import { mkdtempSync, writeFileSync, mkdirSync, rmSync } from "fs";
|
|
3
3
|
import { tmpdir } from "os";
|
|
4
4
|
import { join, dirname } from "path";
|
|
@@ -21,7 +21,8 @@ async function fetchText(url) {
|
|
|
21
21
|
const res = await fetch(url, { redirect: "follow" });
|
|
22
22
|
if (!res.ok) return null;
|
|
23
23
|
return await res.text();
|
|
24
|
-
} catch {
|
|
24
|
+
} catch (err) {
|
|
25
|
+
console.warn(`Warning: failed to fetch ${url}: ${err.message}`);
|
|
25
26
|
return null;
|
|
26
27
|
}
|
|
27
28
|
}
|
|
@@ -102,7 +103,7 @@ export async function runBenchmark(target) {
|
|
|
102
103
|
scanDir = target || ".";
|
|
103
104
|
}
|
|
104
105
|
|
|
105
|
-
const output =
|
|
106
|
+
const output = execFileSync("npx", ["agentic-seo", scanDir, "--json"], {
|
|
106
107
|
timeout: 60000,
|
|
107
108
|
encoding: "utf8",
|
|
108
109
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -135,7 +136,11 @@ export async function runBenchmark(target) {
|
|
|
135
136
|
if (tempDir) {
|
|
136
137
|
try {
|
|
137
138
|
rmSync(tempDir, { recursive: true, force: true });
|
|
138
|
-
} catch {
|
|
139
|
+
} catch (cleanupErr) {
|
|
140
|
+
console.warn(
|
|
141
|
+
`Warning: failed to clean up temp dir ${tempDir}: ${cleanupErr.message}`,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
139
144
|
}
|
|
140
145
|
}
|
|
141
146
|
}
|
|
@@ -62,6 +62,9 @@ export async function runCloudflare(url) {
|
|
|
62
62
|
available: true,
|
|
63
63
|
};
|
|
64
64
|
} catch (err) {
|
|
65
|
+
console.warn(
|
|
66
|
+
`Warning: Cloudflare benchmark failed for ${url}: ${err.message}`,
|
|
67
|
+
);
|
|
65
68
|
return { available: false, reason: err.message?.slice(0, 100) };
|
|
66
69
|
}
|
|
67
70
|
}
|
package/src/benchmark/fern.js
CHANGED
package/src/scan.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { createInterface } from "readline";
|
|
3
|
-
import {
|
|
3
|
+
import { execFileSync } from "child_process";
|
|
4
4
|
import { runAllBenchmarks, printBenchmarks } from "./benchmark/index.js";
|
|
5
5
|
import { saveResult } from "./history/index.js";
|
|
6
6
|
|
|
@@ -100,7 +100,10 @@ function printNextSteps(result) {
|
|
|
100
100
|
(c) => c.status === "fail" || c.status === "warn",
|
|
101
101
|
) || [];
|
|
102
102
|
if (fernFails.length > 0) {
|
|
103
|
-
steps.push([
|
|
103
|
+
steps.push([
|
|
104
|
+
`npx afdocs check ${result.url}`,
|
|
105
|
+
`${fernFails.length} Fern issues`,
|
|
106
|
+
]);
|
|
104
107
|
}
|
|
105
108
|
|
|
106
109
|
steps.push([
|
|
@@ -138,7 +141,7 @@ async function promptFix(result, dir) {
|
|
|
138
141
|
|
|
139
142
|
console.log(chalk.dim(` Running: npx agentic-seo init ${targetDir}\n`));
|
|
140
143
|
try {
|
|
141
|
-
|
|
144
|
+
execFileSync("npx", ["agentic-seo", "init", targetDir], {
|
|
142
145
|
stdio: "inherit",
|
|
143
146
|
});
|
|
144
147
|
} catch (err) {
|
|
@@ -150,9 +153,11 @@ async function promptFix(result, dir) {
|
|
|
150
153
|
(c) => c.status === "fail" || c.status === "warn",
|
|
151
154
|
) || [];
|
|
152
155
|
if (fernFails.length > 0) {
|
|
153
|
-
console.log(chalk.dim(`\n Running: npx afdocs ${result.url}\n`));
|
|
156
|
+
console.log(chalk.dim(`\n Running: npx afdocs check ${result.url}\n`));
|
|
154
157
|
try {
|
|
155
|
-
|
|
158
|
+
execFileSync("npx", ["afdocs", "check", result.url], {
|
|
159
|
+
stdio: "inherit",
|
|
160
|
+
});
|
|
156
161
|
} catch (err) {
|
|
157
162
|
console.log(chalk.red(`\n afdocs failed: ${err.message}\n`));
|
|
158
163
|
}
|
package/src/utils/fetch.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
const DEFAULT_TIMEOUT = 10000;
|
|
2
|
-
const USER_AGENT = "aeo-ready/1.3 (AEO benchmark aggregator)";
|
|
3
|
-
|
|
4
|
-
export async function fetchUrl(url, opts = {}) {
|
|
5
|
-
const controller = new AbortController();
|
|
6
|
-
const timeout = setTimeout(
|
|
7
|
-
() => controller.abort(),
|
|
8
|
-
opts.timeout || DEFAULT_TIMEOUT,
|
|
9
|
-
);
|
|
10
|
-
|
|
11
|
-
try {
|
|
12
|
-
const res = await fetch(url, {
|
|
13
|
-
signal: controller.signal,
|
|
14
|
-
headers: {
|
|
15
|
-
"User-Agent": USER_AGENT,
|
|
16
|
-
...opts.headers,
|
|
17
|
-
},
|
|
18
|
-
redirect: "follow",
|
|
19
|
-
});
|
|
20
|
-
const text = await res.text();
|
|
21
|
-
return {
|
|
22
|
-
status: res.status,
|
|
23
|
-
text,
|
|
24
|
-
headers: Object.fromEntries(res.headers),
|
|
25
|
-
};
|
|
26
|
-
} catch (err) {
|
|
27
|
-
if (err.name === "AbortError") {
|
|
28
|
-
return { status: 0, text: "", headers: {}, error: "timeout" };
|
|
29
|
-
}
|
|
30
|
-
return { status: 0, text: "", headers: {}, error: err.message };
|
|
31
|
-
} finally {
|
|
32
|
-
clearTimeout(timeout);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function resolveUrl(base, path) {
|
|
37
|
-
try {
|
|
38
|
-
return new URL(path, base).href;
|
|
39
|
-
} catch {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
}
|