@ainyc/canonry 1.29.0 → 1.31.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/assets/assets/index-DmFB_uXa.js +246 -0
- package/assets/assets/{index-DwPC0zVy.css → index-r6biprHB.css} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-IWUQVYU3.js → chunk-YW4IZ34Z.js} +1362 -565
- package/dist/cli.js +379 -16
- package/dist/index.js +1 -1
- package/package.json +9 -9
- package/assets/assets/index-D1pCtUfW.js +0 -246
package/dist/cli.js
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
setGoogleAuthConfig,
|
|
22
22
|
showFirstRunNotice,
|
|
23
23
|
trackEvent
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-YW4IZ34Z.js";
|
|
25
25
|
|
|
26
26
|
// src/cli.ts
|
|
27
27
|
import { pathToFileURL } from "url";
|
|
@@ -510,6 +510,9 @@ var ApiClient = class {
|
|
|
510
510
|
async wordpressSetMeta(project, body) {
|
|
511
511
|
return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/page/meta`, body);
|
|
512
512
|
}
|
|
513
|
+
async wordpressBulkSetMeta(project, body) {
|
|
514
|
+
return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/pages/meta/bulk`, body);
|
|
515
|
+
}
|
|
513
516
|
async wordpressSchema(project, slug, env) {
|
|
514
517
|
const params = new URLSearchParams({ slug });
|
|
515
518
|
if (env) params.set("env", env);
|
|
@@ -518,6 +521,18 @@ var ApiClient = class {
|
|
|
518
521
|
async wordpressSetSchema(project, body) {
|
|
519
522
|
return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/schema/manual`, body);
|
|
520
523
|
}
|
|
524
|
+
async wordpressSchemaDeploy(project, body) {
|
|
525
|
+
return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/schema/deploy`, body);
|
|
526
|
+
}
|
|
527
|
+
async wordpressSchemaStatus(project, env) {
|
|
528
|
+
const params = new URLSearchParams();
|
|
529
|
+
if (env) params.set("env", env);
|
|
530
|
+
const qs = params.toString();
|
|
531
|
+
return this.request("GET", `/projects/${encodeURIComponent(project)}/wordpress/schema/status${qs ? `?${qs}` : ""}`);
|
|
532
|
+
}
|
|
533
|
+
async wordpressOnboard(project, body) {
|
|
534
|
+
return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/onboard`, body);
|
|
535
|
+
}
|
|
521
536
|
async wordpressLlmsTxt(project, env) {
|
|
522
537
|
const qs = env ? `?env=${encodeURIComponent(env)}` : "";
|
|
523
538
|
return this.request("GET", `/projects/${encodeURIComponent(project)}/wordpress/llms-txt${qs}`);
|
|
@@ -1342,7 +1357,8 @@ async function gaSync(project, opts) {
|
|
|
1342
1357
|
return;
|
|
1343
1358
|
}
|
|
1344
1359
|
console.log(`GA4 sync complete for "${project}".`);
|
|
1345
|
-
console.log(`
|
|
1360
|
+
console.log(` Page rows: ${result.rowCount}`);
|
|
1361
|
+
console.log(` AI rows: ${result.aiReferralCount}`);
|
|
1346
1362
|
console.log(` Period: ${result.days} days`);
|
|
1347
1363
|
console.log(` Synced at: ${result.syncedAt}`);
|
|
1348
1364
|
}
|
|
@@ -1355,7 +1371,7 @@ async function gaTraffic(project, opts) {
|
|
|
1355
1371
|
console.log(JSON.stringify(result, null, 2));
|
|
1356
1372
|
return;
|
|
1357
1373
|
}
|
|
1358
|
-
if (result.topPages.length === 0) {
|
|
1374
|
+
if (result.topPages.length === 0 && result.aiReferrals.length === 0) {
|
|
1359
1375
|
console.log('No GA4 traffic data. Run "canonry ga sync <project>" first.');
|
|
1360
1376
|
return;
|
|
1361
1377
|
}
|
|
@@ -1365,14 +1381,28 @@ async function gaTraffic(project, opts) {
|
|
|
1365
1381
|
console.log(` Organic Sessions: ${result.totalOrganicSessions}`);
|
|
1366
1382
|
console.log(` Total Users: ${result.totalUsers}`);
|
|
1367
1383
|
console.log();
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
const
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1384
|
+
if (result.aiReferrals.length > 0) {
|
|
1385
|
+
console.log(" AI REFERRAL SOURCES");
|
|
1386
|
+
console.log(` ${"SOURCE".padEnd(25)} ${"MEDIUM".padEnd(15)} ${"SESSIONS".padEnd(10)}${"USERS".padEnd(8)}`);
|
|
1387
|
+
console.log(` ${"\u2500".repeat(25)} ${"\u2500".repeat(15)} ${"\u2500".repeat(10)}${"\u2500".repeat(8)}`);
|
|
1388
|
+
for (const ref of result.aiReferrals) {
|
|
1389
|
+
console.log(
|
|
1390
|
+
` ${ref.source.padEnd(25)} ${ref.medium.padEnd(15)} ${String(ref.sessions).padEnd(10)}${String(ref.users).padEnd(8)}`
|
|
1391
|
+
);
|
|
1392
|
+
}
|
|
1393
|
+
console.log();
|
|
1394
|
+
}
|
|
1395
|
+
if (result.topPages.length > 0) {
|
|
1396
|
+
const pageWidth = Math.min(60, Math.max(15, ...result.topPages.map((r) => r.landingPage.length)));
|
|
1397
|
+
console.log(` TOP LANDING PAGES`);
|
|
1398
|
+
console.log(` ${"PAGE".padEnd(pageWidth)} ${"SESSIONS".padEnd(10)}${"ORGANIC".padEnd(10)}${"USERS".padEnd(8)}`);
|
|
1399
|
+
console.log(` ${"\u2500".repeat(pageWidth)} ${"\u2500".repeat(10)}${"\u2500".repeat(10)}${"\u2500".repeat(8)}`);
|
|
1400
|
+
for (const row of result.topPages) {
|
|
1401
|
+
const page = row.landingPage.length > pageWidth ? row.landingPage.slice(0, pageWidth - 3) + "..." : row.landingPage;
|
|
1402
|
+
console.log(
|
|
1403
|
+
` ${page.padEnd(pageWidth)} ${String(row.sessions).padEnd(10)}${String(row.organicSessions).padEnd(10)}${String(row.users).padEnd(8)}`
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1376
1406
|
}
|
|
1377
1407
|
if (result.lastSyncedAt) {
|
|
1378
1408
|
console.log(`
|
|
@@ -3762,11 +3792,10 @@ function printRunDetail(run) {
|
|
|
3762
3792
|
if (run.finishedAt) console.log(` Finished: ${run.finishedAt}`);
|
|
3763
3793
|
if (run.createdAt) console.log(` Created: ${run.createdAt}`);
|
|
3764
3794
|
if (run.error) console.log(` Error: ${run.error}`);
|
|
3765
|
-
|
|
3766
|
-
if (snapshots && snapshots.length > 0) {
|
|
3795
|
+
if (run.snapshots && run.snapshots.length > 0) {
|
|
3767
3796
|
console.log(`
|
|
3768
|
-
Snapshots: ${snapshots.length}`);
|
|
3769
|
-
for (const s of snapshots) {
|
|
3797
|
+
Snapshots: ${run.snapshots.length}`);
|
|
3798
|
+
for (const s of run.snapshots) {
|
|
3770
3799
|
const state = s.citationState === "cited" ? " cited " : " not-cited";
|
|
3771
3800
|
const modelLabel = s.model ? ` (${s.model})` : "";
|
|
3772
3801
|
console.log(` ${state} ${s.provider}${modelLabel} ${s.keyword}`);
|
|
@@ -5810,6 +5839,88 @@ async function wordpressSetMeta(project, body) {
|
|
|
5810
5839
|
`);
|
|
5811
5840
|
printPageDetail(result);
|
|
5812
5841
|
}
|
|
5842
|
+
async function wordpressBulkSetMeta(project, opts) {
|
|
5843
|
+
const fs7 = await import("fs/promises");
|
|
5844
|
+
const path5 = await import("path");
|
|
5845
|
+
const filePath = path5.resolve(opts.from);
|
|
5846
|
+
let raw;
|
|
5847
|
+
try {
|
|
5848
|
+
raw = await fs7.readFile(filePath, "utf8");
|
|
5849
|
+
} catch {
|
|
5850
|
+
throw new CliError({
|
|
5851
|
+
code: "FILE_READ_ERROR",
|
|
5852
|
+
message: `Cannot read file: ${filePath}`,
|
|
5853
|
+
displayMessage: `Error: cannot read file "${opts.from}". Check the path and permissions.`,
|
|
5854
|
+
details: { path: filePath }
|
|
5855
|
+
});
|
|
5856
|
+
}
|
|
5857
|
+
let parsed;
|
|
5858
|
+
try {
|
|
5859
|
+
parsed = JSON.parse(raw);
|
|
5860
|
+
} catch {
|
|
5861
|
+
throw new CliError({
|
|
5862
|
+
code: "INVALID_JSON",
|
|
5863
|
+
message: `File is not valid JSON: ${filePath}`,
|
|
5864
|
+
displayMessage: `Error: "${opts.from}" is not valid JSON.`,
|
|
5865
|
+
details: { path: filePath }
|
|
5866
|
+
});
|
|
5867
|
+
}
|
|
5868
|
+
const entries = Object.entries(parsed).map(([slug, meta]) => ({
|
|
5869
|
+
slug,
|
|
5870
|
+
title: meta.title,
|
|
5871
|
+
description: meta.description,
|
|
5872
|
+
noindex: meta.noindex
|
|
5873
|
+
}));
|
|
5874
|
+
if (entries.length === 0) {
|
|
5875
|
+
throw new CliError({
|
|
5876
|
+
code: "EMPTY_META_FILE",
|
|
5877
|
+
message: "Meta file contains no entries",
|
|
5878
|
+
displayMessage: `Error: "${opts.from}" contains no entries. Expected JSON object keyed by slug.`,
|
|
5879
|
+
details: { path: filePath }
|
|
5880
|
+
});
|
|
5881
|
+
}
|
|
5882
|
+
const client = getClient17();
|
|
5883
|
+
const result = await client.wordpressBulkSetMeta(project, { entries, env: opts.env });
|
|
5884
|
+
if (opts.format === "json") {
|
|
5885
|
+
printJson(result);
|
|
5886
|
+
return;
|
|
5887
|
+
}
|
|
5888
|
+
const applied = result.results.filter((r) => r.status === "applied");
|
|
5889
|
+
const skipped = result.results.filter((r) => r.status === "skipped");
|
|
5890
|
+
const manual = result.results.filter((r) => r.status === "manual");
|
|
5891
|
+
console.log(`Bulk SEO meta update (${result.env}, strategy: ${result.strategy}):
|
|
5892
|
+
`);
|
|
5893
|
+
if (applied.length > 0) {
|
|
5894
|
+
console.log(` Applied (${applied.length}):`);
|
|
5895
|
+
for (const r of applied) {
|
|
5896
|
+
console.log(` ${r.slug}`);
|
|
5897
|
+
}
|
|
5898
|
+
}
|
|
5899
|
+
if (skipped.length > 0) {
|
|
5900
|
+
console.log(`
|
|
5901
|
+
Skipped (${skipped.length}):`);
|
|
5902
|
+
for (const r of skipped) {
|
|
5903
|
+
console.log(` ${r.slug}: ${r.error ?? "unknown reason"}`);
|
|
5904
|
+
}
|
|
5905
|
+
}
|
|
5906
|
+
if (manual.length > 0) {
|
|
5907
|
+
console.log(`
|
|
5908
|
+
Manual action required (${manual.length}):`);
|
|
5909
|
+
console.log(" No SEO plugin with REST-writable meta fields was detected.");
|
|
5910
|
+
console.log(" Install Yoast SEO, Rank Math, or AIOSEO, or update these pages manually:\n");
|
|
5911
|
+
for (const r of manual) {
|
|
5912
|
+
if (r.manualAssist) {
|
|
5913
|
+
console.log(` ${r.slug}:`);
|
|
5914
|
+
console.log(` Admin: ${r.manualAssist.adminUrl ?? "-"}`);
|
|
5915
|
+
console.log(` Values: ${r.manualAssist.content}`);
|
|
5916
|
+
} else {
|
|
5917
|
+
console.log(` ${r.slug}`);
|
|
5918
|
+
}
|
|
5919
|
+
}
|
|
5920
|
+
}
|
|
5921
|
+
console.log(`
|
|
5922
|
+
Total: ${applied.length} applied, ${skipped.length} skipped, ${manual.length} manual`);
|
|
5923
|
+
}
|
|
5813
5924
|
async function wordpressSchema(project, slug, opts) {
|
|
5814
5925
|
const client = getClient17();
|
|
5815
5926
|
const result = await client.wordpressSchema(project, slug, opts.env);
|
|
@@ -5830,6 +5941,168 @@ async function wordpressSetSchema(project, body) {
|
|
|
5830
5941
|
}
|
|
5831
5942
|
printManualAssist(`Schema update for "${body.slug}"`, result);
|
|
5832
5943
|
}
|
|
5944
|
+
async function wordpressSchemaDeploy(project, opts) {
|
|
5945
|
+
const fs7 = await import("fs/promises");
|
|
5946
|
+
const path5 = await import("path");
|
|
5947
|
+
const yaml = await import("yaml").catch(() => null);
|
|
5948
|
+
const filePath = path5.resolve(opts.profile);
|
|
5949
|
+
let raw;
|
|
5950
|
+
try {
|
|
5951
|
+
raw = await fs7.readFile(filePath, "utf8");
|
|
5952
|
+
} catch {
|
|
5953
|
+
throw new CliError({
|
|
5954
|
+
code: "FILE_READ_ERROR",
|
|
5955
|
+
message: `Cannot read file: ${filePath}`,
|
|
5956
|
+
displayMessage: `Error: cannot read file "${opts.profile}". Check the path and permissions.`,
|
|
5957
|
+
details: { path: filePath }
|
|
5958
|
+
});
|
|
5959
|
+
}
|
|
5960
|
+
let parsed;
|
|
5961
|
+
try {
|
|
5962
|
+
if (yaml?.parse) {
|
|
5963
|
+
parsed = yaml.parse(raw);
|
|
5964
|
+
} else {
|
|
5965
|
+
parsed = JSON.parse(raw);
|
|
5966
|
+
}
|
|
5967
|
+
} catch {
|
|
5968
|
+
throw new CliError({
|
|
5969
|
+
code: "INVALID_PROFILE",
|
|
5970
|
+
message: `File is not valid YAML or JSON: ${filePath}`,
|
|
5971
|
+
displayMessage: `Error: "${opts.profile}" is not valid YAML or JSON.`,
|
|
5972
|
+
details: { path: filePath }
|
|
5973
|
+
});
|
|
5974
|
+
}
|
|
5975
|
+
const profile = parsed;
|
|
5976
|
+
if (!profile?.business?.name || !profile?.pages || Object.keys(profile.pages).length === 0) {
|
|
5977
|
+
throw new CliError({
|
|
5978
|
+
code: "INVALID_PROFILE",
|
|
5979
|
+
message: "Profile must have business.name and non-empty pages",
|
|
5980
|
+
displayMessage: "Error: profile file must contain business.name and at least one page entry.",
|
|
5981
|
+
details: { path: filePath }
|
|
5982
|
+
});
|
|
5983
|
+
}
|
|
5984
|
+
const client = getClient17();
|
|
5985
|
+
const result = await client.wordpressSchemaDeploy(project, { profile: parsed, env: opts.env });
|
|
5986
|
+
if (opts.format === "json") {
|
|
5987
|
+
printJson(result);
|
|
5988
|
+
return;
|
|
5989
|
+
}
|
|
5990
|
+
console.log(`Schema deploy (${result.env}):
|
|
5991
|
+
`);
|
|
5992
|
+
for (const r of result.results) {
|
|
5993
|
+
const types = r.schemasInjected?.join(", ") ?? "";
|
|
5994
|
+
switch (r.status) {
|
|
5995
|
+
case "deployed":
|
|
5996
|
+
console.log(` ${r.slug}: deployed (${types})`);
|
|
5997
|
+
break;
|
|
5998
|
+
case "stripped":
|
|
5999
|
+
console.log(` ${r.slug}: STRIPPED \u2014 WordPress removed <script> tags. Manual action required.`);
|
|
6000
|
+
if (r.manualAssist) {
|
|
6001
|
+
console.log(` Admin: ${r.manualAssist.adminUrl ?? "-"}`);
|
|
6002
|
+
for (const step of r.manualAssist.nextSteps) {
|
|
6003
|
+
console.log(` - ${step}`);
|
|
6004
|
+
}
|
|
6005
|
+
}
|
|
6006
|
+
break;
|
|
6007
|
+
case "skipped":
|
|
6008
|
+
console.log(` ${r.slug}: skipped \u2014 ${r.error ?? "unknown"}`);
|
|
6009
|
+
break;
|
|
6010
|
+
case "failed":
|
|
6011
|
+
console.log(` ${r.slug}: FAILED \u2014 ${r.error ?? "unknown"}`);
|
|
6012
|
+
break;
|
|
6013
|
+
}
|
|
6014
|
+
}
|
|
6015
|
+
const deployed = result.results.filter((r) => r.status === "deployed").length;
|
|
6016
|
+
const stripped = result.results.filter((r) => r.status === "stripped").length;
|
|
6017
|
+
const skipped = result.results.filter((r) => r.status === "skipped").length;
|
|
6018
|
+
const failed = result.results.filter((r) => r.status === "failed").length;
|
|
6019
|
+
console.log(`
|
|
6020
|
+
Total: ${deployed} deployed, ${stripped} stripped, ${skipped} skipped, ${failed} failed`);
|
|
6021
|
+
}
|
|
6022
|
+
async function wordpressSchemaStatus(project, opts) {
|
|
6023
|
+
const client = getClient17();
|
|
6024
|
+
const result = await client.wordpressSchemaStatus(project, opts.env);
|
|
6025
|
+
if (opts.format === "json") {
|
|
6026
|
+
printJson(result);
|
|
6027
|
+
return;
|
|
6028
|
+
}
|
|
6029
|
+
console.log(`Schema status (${result.env}):
|
|
6030
|
+
`);
|
|
6031
|
+
if (result.pages.length === 0) {
|
|
6032
|
+
console.log(" No pages found.");
|
|
6033
|
+
return;
|
|
6034
|
+
}
|
|
6035
|
+
const slugWidth = Math.max(4, ...result.pages.map((p) => p.slug.length));
|
|
6036
|
+
console.log(` ${"SLUG".padEnd(slugWidth)} CANONRY THIRD-PARTY`);
|
|
6037
|
+
console.log(` ${"\u2500".repeat(slugWidth)} ${"\u2500".repeat(17)} ${"\u2500".repeat(20)}`);
|
|
6038
|
+
for (const page of result.pages) {
|
|
6039
|
+
const canonry = page.canonrySchemas.length > 0 ? page.canonrySchemas.join(", ") : "-";
|
|
6040
|
+
const thirdParty = page.thirdPartySchemas.length > 0 ? page.thirdPartySchemas.join(", ") : "-";
|
|
6041
|
+
console.log(` ${page.slug.padEnd(slugWidth)} ${canonry.padEnd(17)} ${thirdParty}`);
|
|
6042
|
+
}
|
|
6043
|
+
}
|
|
6044
|
+
async function wordpressOnboard(project, opts) {
|
|
6045
|
+
const appPassword = opts.appPassword ?? await promptForAppPassword();
|
|
6046
|
+
if (!appPassword) {
|
|
6047
|
+
throw new CliError({
|
|
6048
|
+
code: "WORDPRESS_APP_PASSWORD_REQUIRED",
|
|
6049
|
+
message: "WordPress Application Password is required",
|
|
6050
|
+
displayMessage: "Error: WordPress Application Password is required (pass --app-password or enter interactively).",
|
|
6051
|
+
details: { project }
|
|
6052
|
+
});
|
|
6053
|
+
}
|
|
6054
|
+
let profileData;
|
|
6055
|
+
if (opts.profile) {
|
|
6056
|
+
const fs7 = await import("fs/promises");
|
|
6057
|
+
const path5 = await import("path");
|
|
6058
|
+
const yaml = await import("yaml").catch(() => null);
|
|
6059
|
+
const filePath = path5.resolve(opts.profile);
|
|
6060
|
+
let raw;
|
|
6061
|
+
try {
|
|
6062
|
+
raw = await fs7.readFile(filePath, "utf8");
|
|
6063
|
+
} catch {
|
|
6064
|
+
throw new CliError({
|
|
6065
|
+
code: "FILE_READ_ERROR",
|
|
6066
|
+
message: `Cannot read file: ${filePath}`,
|
|
6067
|
+
displayMessage: `Error: cannot read file "${opts.profile}".`,
|
|
6068
|
+
details: { path: filePath }
|
|
6069
|
+
});
|
|
6070
|
+
}
|
|
6071
|
+
try {
|
|
6072
|
+
profileData = yaml?.parse ? yaml.parse(raw) : JSON.parse(raw);
|
|
6073
|
+
} catch {
|
|
6074
|
+
throw new CliError({
|
|
6075
|
+
code: "INVALID_PROFILE",
|
|
6076
|
+
message: `File is not valid YAML or JSON: ${filePath}`,
|
|
6077
|
+
displayMessage: `Error: "${opts.profile}" is not valid YAML or JSON.`,
|
|
6078
|
+
details: { path: filePath }
|
|
6079
|
+
});
|
|
6080
|
+
}
|
|
6081
|
+
}
|
|
6082
|
+
const client = getClient17();
|
|
6083
|
+
const result = await client.wordpressOnboard(project, {
|
|
6084
|
+
url: opts.url,
|
|
6085
|
+
username: opts.user,
|
|
6086
|
+
appPassword,
|
|
6087
|
+
stagingUrl: opts.stagingUrl,
|
|
6088
|
+
defaultEnv: opts.defaultEnv,
|
|
6089
|
+
profile: profileData,
|
|
6090
|
+
skipSchema: opts.skipSchema,
|
|
6091
|
+
skipSubmit: opts.skipSubmit
|
|
6092
|
+
});
|
|
6093
|
+
if (opts.format === "json") {
|
|
6094
|
+
printJson(result);
|
|
6095
|
+
return;
|
|
6096
|
+
}
|
|
6097
|
+
console.log(`WordPress onboarding for "${project}":
|
|
6098
|
+
`);
|
|
6099
|
+
for (const step of result.steps) {
|
|
6100
|
+
const icon = step.status === "completed" ? "+" : step.status === "skipped" ? "-" : "x";
|
|
6101
|
+
console.log(` [${icon}] ${step.name}: ${step.status}`);
|
|
6102
|
+
if (step.summary) console.log(` ${step.summary}`);
|
|
6103
|
+
if (step.error) console.log(` Error: ${step.error}`);
|
|
6104
|
+
}
|
|
6105
|
+
}
|
|
5833
6106
|
async function wordpressLlmsTxt(project, opts) {
|
|
5834
6107
|
const client = getClient17();
|
|
5835
6108
|
const result = await client.wordpressLlmsTxt(project, opts.env);
|
|
@@ -6107,15 +6380,27 @@ var WORDPRESS_CLI_COMMANDS = [
|
|
|
6107
6380
|
},
|
|
6108
6381
|
{
|
|
6109
6382
|
path: ["wordpress", "set-meta"],
|
|
6110
|
-
usage: "canonry wordpress set-meta <project> <slug> [--title <title>] [--description <text>] [--noindex|--index] [--live|--staging] [--format json]",
|
|
6383
|
+
usage: "canonry wordpress set-meta <project> <slug> [--title <title>] [--description <text>] [--noindex|--index] [--from <file>] [--live|--staging] [--format json]",
|
|
6111
6384
|
options: {
|
|
6112
6385
|
title: stringOption(),
|
|
6113
6386
|
description: stringOption(),
|
|
6114
6387
|
noindex: { type: "boolean", default: false },
|
|
6115
6388
|
index: { type: "boolean", default: false },
|
|
6389
|
+
from: stringOption(),
|
|
6116
6390
|
...envOptions
|
|
6117
6391
|
},
|
|
6118
6392
|
run: async (input) => {
|
|
6393
|
+
const fromFile = getString(input.values, "from");
|
|
6394
|
+
if (fromFile) {
|
|
6395
|
+
const usage2 = "canonry wordpress set-meta <project> --from <file> [--live|--staging] [--format json]";
|
|
6396
|
+
const project2 = requireProject(input, "wordpress.set-meta", usage2);
|
|
6397
|
+
await wordpressBulkSetMeta(project2, {
|
|
6398
|
+
from: fromFile,
|
|
6399
|
+
env: resolveEnv(input, "wordpress.set-meta", usage2),
|
|
6400
|
+
format: input.format
|
|
6401
|
+
});
|
|
6402
|
+
return;
|
|
6403
|
+
}
|
|
6119
6404
|
const usage = "canonry wordpress set-meta <project> <slug> [--title <title>] [--description <text>] [--noindex|--index] [--live|--staging] [--format json]";
|
|
6120
6405
|
const project = requireProject(input, "wordpress.set-meta", usage);
|
|
6121
6406
|
const slug = requirePositional(input, 1, {
|
|
@@ -6133,6 +6418,41 @@ var WORDPRESS_CLI_COMMANDS = [
|
|
|
6133
6418
|
});
|
|
6134
6419
|
}
|
|
6135
6420
|
},
|
|
6421
|
+
{
|
|
6422
|
+
path: ["wordpress", "schema", "deploy"],
|
|
6423
|
+
usage: "canonry wordpress schema deploy <project> --profile <file> [--live|--staging] [--format json]",
|
|
6424
|
+
options: {
|
|
6425
|
+
profile: stringOption(),
|
|
6426
|
+
...envOptions
|
|
6427
|
+
},
|
|
6428
|
+
run: async (input) => {
|
|
6429
|
+
const usage = "canonry wordpress schema deploy <project> --profile <file> [--live|--staging] [--format json]";
|
|
6430
|
+
const project = requireProject(input, "wordpress.schema.deploy", usage);
|
|
6431
|
+
const profile = requireStringOption(input, "profile", {
|
|
6432
|
+
message: "--profile is required",
|
|
6433
|
+
command: "wordpress.schema.deploy",
|
|
6434
|
+
usage
|
|
6435
|
+
});
|
|
6436
|
+
await wordpressSchemaDeploy(project, {
|
|
6437
|
+
profile,
|
|
6438
|
+
env: resolveEnv(input, "wordpress.schema.deploy", usage),
|
|
6439
|
+
format: input.format
|
|
6440
|
+
});
|
|
6441
|
+
}
|
|
6442
|
+
},
|
|
6443
|
+
{
|
|
6444
|
+
path: ["wordpress", "schema", "status"],
|
|
6445
|
+
usage: "canonry wordpress schema status <project> [--live|--staging] [--format json]",
|
|
6446
|
+
options: envOptions,
|
|
6447
|
+
run: async (input) => {
|
|
6448
|
+
const usage = "canonry wordpress schema status <project> [--live|--staging] [--format json]";
|
|
6449
|
+
const project = requireProject(input, "wordpress.schema.status", usage);
|
|
6450
|
+
await wordpressSchemaStatus(project, {
|
|
6451
|
+
env: resolveEnv(input, "wordpress.schema.status", usage),
|
|
6452
|
+
format: input.format
|
|
6453
|
+
});
|
|
6454
|
+
}
|
|
6455
|
+
},
|
|
6136
6456
|
{
|
|
6137
6457
|
path: ["wordpress", "schema"],
|
|
6138
6458
|
usage: "canonry wordpress schema <project> <slug> [--live|--staging] [--format json]",
|
|
@@ -6214,6 +6534,45 @@ var WORDPRESS_CLI_COMMANDS = [
|
|
|
6214
6534
|
});
|
|
6215
6535
|
}
|
|
6216
6536
|
},
|
|
6537
|
+
{
|
|
6538
|
+
path: ["wordpress", "onboard"],
|
|
6539
|
+
usage: "canonry wordpress onboard <project> --url <url> --user <user> [--app-password <pw>] [--profile <file>] [--skip-schema] [--skip-submit] [--live|--staging] [--format json]",
|
|
6540
|
+
options: {
|
|
6541
|
+
url: stringOption(),
|
|
6542
|
+
user: stringOption(),
|
|
6543
|
+
"app-password": stringOption(),
|
|
6544
|
+
"staging-url": stringOption(),
|
|
6545
|
+
profile: stringOption(),
|
|
6546
|
+
"skip-schema": { type: "boolean", default: false },
|
|
6547
|
+
"skip-submit": { type: "boolean", default: false },
|
|
6548
|
+
...envOptions
|
|
6549
|
+
},
|
|
6550
|
+
run: async (input) => {
|
|
6551
|
+
const usage = "canonry wordpress onboard <project> --url <url> --user <user> [--app-password <pw>] [--profile <file>] [--format json]";
|
|
6552
|
+
const project = requireProject(input, "wordpress.onboard", usage);
|
|
6553
|
+
const url = requireStringOption(input, "url", {
|
|
6554
|
+
message: "--url is required",
|
|
6555
|
+
command: "wordpress.onboard",
|
|
6556
|
+
usage
|
|
6557
|
+
});
|
|
6558
|
+
const user = requireStringOption(input, "user", {
|
|
6559
|
+
message: "--user is required",
|
|
6560
|
+
command: "wordpress.onboard",
|
|
6561
|
+
usage
|
|
6562
|
+
});
|
|
6563
|
+
await wordpressOnboard(project, {
|
|
6564
|
+
url,
|
|
6565
|
+
user,
|
|
6566
|
+
appPassword: getString(input.values, "app-password"),
|
|
6567
|
+
stagingUrl: getString(input.values, "staging-url"),
|
|
6568
|
+
defaultEnv: resolveEnv(input, "wordpress.onboard", usage),
|
|
6569
|
+
profile: getString(input.values, "profile"),
|
|
6570
|
+
skipSchema: getBoolean(input.values, "skip-schema"),
|
|
6571
|
+
skipSubmit: getBoolean(input.values, "skip-submit"),
|
|
6572
|
+
format: input.format
|
|
6573
|
+
});
|
|
6574
|
+
}
|
|
6575
|
+
},
|
|
6217
6576
|
{
|
|
6218
6577
|
path: ["wordpress", "audit"],
|
|
6219
6578
|
usage: "canonry wordpress audit <project> [--live|--staging] [--format json]",
|
|
@@ -6392,8 +6751,12 @@ Usage:
|
|
|
6392
6751
|
canonry wordpress create-page <project> Create a WordPress page (--title, --slug, --content/--content-file)
|
|
6393
6752
|
canonry wordpress update-page <project> <slug> Update a WordPress page (--content/--content-file)
|
|
6394
6753
|
canonry wordpress set-meta <project> <slug> Update REST-exposed SEO meta
|
|
6754
|
+
canonry wordpress set-meta <project> --from <file> Bulk update SEO meta from JSON file
|
|
6395
6755
|
canonry wordpress schema <project> <slug> Read rendered JSON-LD schema
|
|
6756
|
+
canonry wordpress schema deploy <project> --profile <file> Deploy JSON-LD schema to pages
|
|
6757
|
+
canonry wordpress schema status <project> Show schema status per page
|
|
6396
6758
|
canonry wordpress set-schema <project> <slug> Generate manual schema handoff
|
|
6759
|
+
canonry wordpress onboard <project> --url <url> --user <user> Full onboarding workflow
|
|
6397
6760
|
canonry wordpress llms-txt <project> Read /llms.txt
|
|
6398
6761
|
canonry wordpress set-llms-txt <project> Generate manual llms.txt handoff
|
|
6399
6762
|
canonry wordpress audit <project> Audit WordPress pages for SEO/content issues
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainyc/canonry",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.31.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The ultimate open-source AEO monitoring tool - track how answer engines cite your domain",
|
|
6
6
|
"license": "FSL-1.1-ALv2",
|
|
@@ -54,19 +54,19 @@
|
|
|
54
54
|
"@types/node-cron": "^3.0.11",
|
|
55
55
|
"tsup": "^8.5.1",
|
|
56
56
|
"tsx": "^4.19.0",
|
|
57
|
-
"@ainyc/canonry-config": "0.0.0",
|
|
58
|
-
"@ainyc/canonry-contracts": "0.0.0",
|
|
59
57
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
60
|
-
"@ainyc/canonry-
|
|
61
|
-
"@ainyc/canonry-
|
|
62
|
-
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
58
|
+
"@ainyc/canonry-contracts": "0.0.0",
|
|
59
|
+
"@ainyc/canonry-config": "0.0.0",
|
|
63
60
|
"@ainyc/canonry-db": "0.0.0",
|
|
61
|
+
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
62
|
+
"@ainyc/canonry-integration-google": "0.0.0",
|
|
64
63
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
64
|
+
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
65
65
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
66
|
-
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
67
66
|
"@ainyc/canonry-provider-local": "0.0.0",
|
|
68
|
-
"@ainyc/canonry-provider-
|
|
69
|
-
"@ainyc/canonry-provider-openai": "0.0.0"
|
|
67
|
+
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
68
|
+
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
69
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0"
|
|
70
70
|
},
|
|
71
71
|
"scripts": {
|
|
72
72
|
"build": "tsup && tsx build-web.ts",
|