@citeme/cli 0.1.1 → 0.2.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.
Files changed (2) hide show
  1. package/dist/index.js +215 -45
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -12,6 +12,31 @@ import axios from "axios";
12
12
 
13
13
  // src/utils/config.ts
14
14
  import Conf from "conf";
15
+ import { readFileSync } from "fs";
16
+ import { fileURLToPath } from "url";
17
+ import { dirname, join } from "path";
18
+ var __filename = fileURLToPath(import.meta.url);
19
+ var __dirname = dirname(__filename);
20
+ var possiblePaths = [
21
+ join(__dirname, "..", "package.json"),
22
+ // From dist/
23
+ join(__dirname, "..", "..", "package.json")
24
+ // From src/utils/
25
+ ];
26
+ var packageVersion = "0.0.0";
27
+ for (const path of possiblePaths) {
28
+ try {
29
+ const packageJson = JSON.parse(readFileSync(path, "utf-8"));
30
+ if (packageJson.name === "@citeme/cli" && packageJson.version) {
31
+ packageVersion = packageJson.version;
32
+ break;
33
+ }
34
+ } catch {
35
+ }
36
+ }
37
+ if (packageVersion === "0.0.0") {
38
+ packageVersion = "0.2.0";
39
+ }
15
40
  var config = new Conf({
16
41
  projectName: "citeme",
17
42
  schema: {
@@ -51,6 +76,9 @@ function isAuthenticated() {
51
76
  function getConfigPath() {
52
77
  return config.path;
53
78
  }
79
+ function getVersion() {
80
+ return packageVersion;
81
+ }
54
82
 
55
83
  // src/services/api.ts
56
84
  var ApiService = class {
@@ -284,13 +312,13 @@ async function loginCommand() {
284
312
  }
285
313
  }
286
314
  );
287
- const spinner2 = p.spinner();
288
- spinner2.start("Authenticating...");
315
+ const spinner3 = p.spinner();
316
+ spinner3.start("Authenticating...");
289
317
  try {
290
318
  const response = await api.authenticate(credentials.email, credentials.password);
291
319
  setApiKey(response.apiKey);
292
320
  setEmail(response.email);
293
- spinner2.stop(renderSuccess("Authentication successful!"));
321
+ spinner3.stop(renderSuccess("Authentication successful!"));
294
322
  p.note(
295
323
  [
296
324
  `Logged in as: ${chalk2.cyan(response.email)}`,
@@ -302,7 +330,7 @@ async function loginCommand() {
302
330
  );
303
331
  p.outro(chalk2.green("You are now authenticated!"));
304
332
  } catch (error) {
305
- spinner2.stop(renderError("Authentication failed"));
333
+ spinner3.stop(renderError("Authentication failed"));
306
334
  if (error instanceof ApiError) {
307
335
  if (error.statusCode === 401) {
308
336
  p.log.error("Invalid email or password. Please try again.");
@@ -324,10 +352,10 @@ async function logoutCommand() {
324
352
  return;
325
353
  }
326
354
  const email = getEmail();
327
- const confirm3 = await p.confirm({
355
+ const confirm4 = await p.confirm({
328
356
  message: `Are you sure you want to log out from ${chalk2.cyan(email)}?`
329
357
  });
330
- if (p.isCancel(confirm3) || !confirm3) {
358
+ if (p.isCancel(confirm4) || !confirm4) {
331
359
  p.outro(chalk2.gray("Logout cancelled."));
332
360
  return;
333
361
  }
@@ -340,20 +368,20 @@ async function whoamiCommand() {
340
368
  p.log.warn("Not logged in. Run `citeme login` to authenticate.");
341
369
  return;
342
370
  }
343
- const spinner2 = p.spinner();
344
- spinner2.start("Validating session...");
371
+ const spinner3 = p.spinner();
372
+ spinner3.start("Validating session...");
345
373
  try {
346
374
  const { valid, email } = await api.validateApiKey();
347
375
  if (valid) {
348
- spinner2.stop(renderSuccess("Session valid"));
376
+ spinner3.stop(renderSuccess("Session valid"));
349
377
  p.log.info(`Logged in as: ${chalk2.cyan(email || getEmail())}`);
350
378
  p.log.info(`Config location: ${chalk2.gray(getConfigPath())}`);
351
379
  } else {
352
- spinner2.stop(renderError("Session expired"));
380
+ spinner3.stop(renderError("Session expired"));
353
381
  p.log.warn("Your session has expired. Please run `citeme login` again.");
354
382
  }
355
383
  } catch {
356
- spinner2.stop(renderError("Could not validate session"));
384
+ spinner3.stop(renderError("Could not validate session"));
357
385
  p.log.error("Failed to connect to CiteMe. Please check your internet connection.");
358
386
  }
359
387
  }
@@ -846,13 +874,13 @@ async function applyAllPatches(patches) {
846
874
  };
847
875
  console.log(renderWarning("Applying all patches without confirmation...\n"));
848
876
  for (const patch of patches) {
849
- const spinner2 = ora2({
877
+ const spinner3 = ora2({
850
878
  text: `Applying: ${patch.file}`,
851
879
  color: "magenta"
852
880
  }).start();
853
881
  const patchResult = await applyPatch(patch.file, patch.original, patch.patched);
854
882
  if (patchResult.success) {
855
- spinner2.succeed(chalk5.green(patch.file));
883
+ spinner3.succeed(chalk5.green(patch.file));
856
884
  result.applied++;
857
885
  if (patchResult.backupPath) {
858
886
  result.backups.set(patch.file, patchResult.backupPath);
@@ -862,7 +890,7 @@ async function applyAllPatches(patches) {
862
890
  } catch {
863
891
  }
864
892
  } else {
865
- spinner2.fail(chalk5.red(`${patch.file}: ${patchResult.error}`));
893
+ spinner3.fail(chalk5.red(`${patch.file}: ${patchResult.error}`));
866
894
  result.failed++;
867
895
  }
868
896
  }
@@ -915,21 +943,21 @@ async function generateSuggestionsCommand(options) {
915
943
  p4.intro(chalk6.hex("#8B5CF6")("Generate Suggestions"));
916
944
  let auditId = options.auditId;
917
945
  if (!auditId) {
918
- const spinner2 = ora3({
946
+ const spinner3 = ora3({
919
947
  text: "Fetching latest audit...",
920
948
  color: "magenta"
921
949
  }).start();
922
950
  try {
923
951
  const latestAudit = await api.getLatestAudit();
924
952
  if (!latestAudit) {
925
- spinner2.fail("No audit found");
953
+ spinner3.fail("No audit found");
926
954
  p4.log.warn("No audit found. Run `citeme audit` first.");
927
955
  process.exit(1);
928
956
  }
929
957
  auditId = latestAudit.id;
930
- spinner2.succeed(`Using audit ${chalk6.gray(auditId.slice(0, 8))}... (score: ${latestAudit.score})`);
958
+ spinner3.succeed(`Using audit ${chalk6.gray(auditId.slice(0, 8))}... (score: ${latestAudit.score})`);
931
959
  } catch (error) {
932
- spinner2.fail("Failed to fetch audit");
960
+ spinner3.fail("Failed to fetch audit");
933
961
  if (error instanceof ApiError) {
934
962
  p4.log.error(error.message);
935
963
  }
@@ -994,7 +1022,7 @@ async function listSuggestionsCommand(options) {
994
1022
  if (!options.json) {
995
1023
  p4.intro(chalk6.hex("#8B5CF6")("Suggestions"));
996
1024
  }
997
- const spinner2 = ora3({
1025
+ const spinner3 = ora3({
998
1026
  text: "Fetching suggestions...",
999
1027
  color: "magenta"
1000
1028
  }).start();
@@ -1004,7 +1032,7 @@ async function listSuggestionsCommand(options) {
1004
1032
  type: options.type,
1005
1033
  limit: options.limit || 20
1006
1034
  });
1007
- spinner2.stop();
1035
+ spinner3.stop();
1008
1036
  if (options.json) {
1009
1037
  console.log(JSON.stringify(suggestions2, null, 2));
1010
1038
  return;
@@ -1051,7 +1079,7 @@ async function listSuggestionsCommand(options) {
1051
1079
  );
1052
1080
  p4.outro(chalk6.gray("Use `citeme suggestions view <id>` to see full content."));
1053
1081
  } catch (error) {
1054
- spinner2.fail("Failed to fetch suggestions");
1082
+ spinner3.fail("Failed to fetch suggestions");
1055
1083
  if (error instanceof ApiError) {
1056
1084
  if (options.json) {
1057
1085
  console.log(JSON.stringify({ error: error.message }));
@@ -1074,13 +1102,13 @@ async function viewSuggestionCommand(suggestionId) {
1074
1102
  p4.log.info("Usage: citeme suggestions view <id>");
1075
1103
  process.exit(1);
1076
1104
  }
1077
- const spinner2 = ora3({
1105
+ const spinner3 = ora3({
1078
1106
  text: "Fetching suggestion...",
1079
1107
  color: "magenta"
1080
1108
  }).start();
1081
1109
  try {
1082
1110
  const suggestion = await api.getSuggestion(suggestionId);
1083
- spinner2.stop();
1111
+ spinner3.stop();
1084
1112
  const typeColor = getTypeColor(suggestion.type);
1085
1113
  const statusIcon = getStatusIcon(suggestion.status);
1086
1114
  console.log("");
@@ -1110,7 +1138,7 @@ async function viewSuggestionCommand(suggestionId) {
1110
1138
  "Actions"
1111
1139
  );
1112
1140
  } catch (error) {
1113
- spinner2.fail("Failed to fetch suggestion");
1141
+ spinner3.fail("Failed to fetch suggestion");
1114
1142
  if (error instanceof ApiError) {
1115
1143
  if (error.statusCode === 404) {
1116
1144
  p4.log.error("Suggestion not found. Check the ID and try again.");
@@ -1158,10 +1186,150 @@ function getStatusIcon(status) {
1158
1186
  }
1159
1187
  }
1160
1188
 
1161
- // src/index.ts
1189
+ // src/commands/update.ts
1190
+ import * as p5 from "@clack/prompts";
1162
1191
  import chalk7 from "chalk";
1192
+ import { exec } from "child_process";
1193
+ import { promisify } from "util";
1194
+ var execAsync = promisify(exec);
1195
+ function compareVersions(current, latest) {
1196
+ const currentParts = current.split(".").map(Number);
1197
+ const latestParts = latest.split(".").map(Number);
1198
+ for (let i = 0; i < 3; i++) {
1199
+ const c = currentParts[i] || 0;
1200
+ const l = latestParts[i] || 0;
1201
+ if (c > l) return 1;
1202
+ if (c < l) return -1;
1203
+ }
1204
+ return 0;
1205
+ }
1206
+ async function checkForUpdates() {
1207
+ const currentVersion = getVersion();
1208
+ try {
1209
+ const { stdout } = await execAsync("npm view @citeme/cli version");
1210
+ const latestVersion = stdout.trim();
1211
+ const comparison = compareVersions(currentVersion, latestVersion);
1212
+ return {
1213
+ latest: latestVersion,
1214
+ current: currentVersion,
1215
+ isOutdated: comparison < 0,
1216
+ // Current is older
1217
+ isDevelopment: comparison > 0
1218
+ // Current is newer (dev build)
1219
+ };
1220
+ } catch {
1221
+ return {
1222
+ latest: currentVersion,
1223
+ current: currentVersion,
1224
+ isOutdated: false,
1225
+ isDevelopment: false
1226
+ };
1227
+ }
1228
+ }
1229
+ async function performUpdate() {
1230
+ try {
1231
+ const { stdout: npmRoot } = await execAsync("npm root -g");
1232
+ const isGlobal = npmRoot.trim().length > 0;
1233
+ await execAsync("npm install -g @citeme/cli@latest");
1234
+ return true;
1235
+ } catch (error) {
1236
+ if (process.platform !== "win32") {
1237
+ try {
1238
+ await execAsync("sudo npm install -g @citeme/cli@latest");
1239
+ return true;
1240
+ } catch {
1241
+ return false;
1242
+ }
1243
+ }
1244
+ return false;
1245
+ }
1246
+ }
1247
+ async function updateCommand(options) {
1248
+ console.log(renderHeader());
1249
+ const spinner3 = p5.spinner();
1250
+ spinner3.start("Checking for updates...");
1251
+ const versionInfo = await checkForUpdates();
1252
+ if (versionInfo.isDevelopment) {
1253
+ spinner3.stop(renderSuccess("Running development version"));
1254
+ p5.note(
1255
+ [
1256
+ `Current version: ${chalk7.cyan(`v${versionInfo.current}`)} ${chalk7.yellow("(dev)")}`,
1257
+ `Published version: ${chalk7.gray(`v${versionInfo.latest}`)}`
1258
+ ].join("\n"),
1259
+ "Version Info"
1260
+ );
1261
+ return;
1262
+ }
1263
+ if (!versionInfo.isOutdated) {
1264
+ spinner3.stop(renderSuccess("Already up to date!"));
1265
+ p5.note(
1266
+ `Current version: ${chalk7.cyan(`v${versionInfo.current}`)}`,
1267
+ "Version Info"
1268
+ );
1269
+ return;
1270
+ }
1271
+ spinner3.stop("Update available!");
1272
+ p5.note(
1273
+ [
1274
+ `Current version: ${chalk7.gray(`v${versionInfo.current}`)}`,
1275
+ `Latest version: ${chalk7.green(`v${versionInfo.latest}`)}`
1276
+ ].join("\n"),
1277
+ "Update Available"
1278
+ );
1279
+ if (options.check) {
1280
+ p5.log.info(`Run ${chalk7.cyan("citeme update")} to install the latest version.`);
1281
+ return;
1282
+ }
1283
+ const confirm4 = await p5.confirm({
1284
+ message: `Update to v${versionInfo.latest}?`
1285
+ });
1286
+ if (p5.isCancel(confirm4) || !confirm4) {
1287
+ p5.outro(chalk7.gray("Update cancelled."));
1288
+ return;
1289
+ }
1290
+ spinner3.start("Installing update...");
1291
+ const success = await performUpdate();
1292
+ if (success) {
1293
+ spinner3.stop(renderSuccess("Update complete!"));
1294
+ p5.note(
1295
+ [
1296
+ `Updated to ${chalk7.green(`v${versionInfo.latest}`)}`,
1297
+ "",
1298
+ "Restart your terminal to use the new version."
1299
+ ].join("\n"),
1300
+ "Success"
1301
+ );
1302
+ p5.outro(chalk7.green("CiteMe CLI has been updated!"));
1303
+ } else {
1304
+ spinner3.stop(renderError("Update failed"));
1305
+ p5.log.error("Could not update automatically.");
1306
+ p5.note(
1307
+ [
1308
+ "Try updating manually:",
1309
+ "",
1310
+ chalk7.cyan(" npm install -g @citeme/cli@latest"),
1311
+ "",
1312
+ "Or with sudo (macOS/Linux):",
1313
+ "",
1314
+ chalk7.cyan(" sudo npm install -g @citeme/cli@latest")
1315
+ ].join("\n"),
1316
+ "Manual Update"
1317
+ );
1318
+ process.exit(1);
1319
+ }
1320
+ }
1321
+
1322
+ // src/index.ts
1323
+ import chalk8 from "chalk";
1163
1324
  var program = new Command();
1164
- program.name("citeme").description("CiteMe CLI - Audit your GEO score and apply optimizations").version("0.1.0", "-v, --version", "Display CLI version").helpOption("-h, --help", "Display help for command");
1325
+ var version = getVersion();
1326
+ program.name("citeme").description("CiteMe CLI - Audit your GEO score and apply optimizations").version(version, "-v, --version", "Display CLI version").helpOption("-h, --help", "Display help for command").configureOutput({
1327
+ outputError: () => {
1328
+ }
1329
+ // Suppress default error output
1330
+ }).action(() => {
1331
+ showCustomHelp();
1332
+ });
1165
1333
  program.command("login").description("Authenticate with your CiteMe account").action(loginCommand);
1166
1334
  program.command("logout").description("Log out and remove stored credentials").action(logoutCommand);
1167
1335
  program.command("whoami").description("Display current user information").action(whoamiCommand);
@@ -1178,13 +1346,13 @@ suggestions.command("list").description("List all suggestions").option("-s, --st
1178
1346
  }));
1179
1347
  suggestions.command("view <id>").description("View a specific suggestion").action((id) => viewSuggestionCommand(id));
1180
1348
  program.command("status").description("Show CLI status and configuration").action(() => {
1181
- console.log("\n" + chalk7.bold("CiteMe CLI Status") + "\n");
1349
+ console.log("\n" + chalk8.bold("CiteMe CLI Status") + "\n");
1182
1350
  if (isAuthenticated()) {
1183
- console.log(chalk7.green("\u2714") + " Authenticated as: " + chalk7.cyan(getEmail()));
1351
+ console.log(chalk8.green("\u2714") + " Authenticated as: " + chalk8.cyan(getEmail()));
1184
1352
  } else {
1185
- console.log(chalk7.yellow("\u25CB") + " Not authenticated");
1353
+ console.log(chalk8.yellow("\u25CB") + " Not authenticated");
1186
1354
  }
1187
- console.log(chalk7.gray(" Config: ") + getConfigPath());
1355
+ console.log(chalk8.gray(" Config: ") + getConfigPath());
1188
1356
  console.log("");
1189
1357
  });
1190
1358
  program.command("config").description("Show configuration file path").action(() => {
@@ -1196,33 +1364,33 @@ program.command("help [command]").description("Display help for a command").acti
1196
1364
  if (cmd) {
1197
1365
  cmd.outputHelp();
1198
1366
  } else {
1199
- console.error(chalk7.red(`Unknown command: ${command}`));
1200
- console.log(`Run ${chalk7.cyan("citeme help")} for available commands.`);
1367
+ console.error(chalk8.red(`Unknown command: ${command}`));
1368
+ console.log(`Run ${chalk8.cyan("citeme help")} for available commands.`);
1201
1369
  }
1202
1370
  } else {
1203
1371
  program.outputHelp();
1204
1372
  }
1205
1373
  });
1206
1374
  program.command("version").description("Display CLI version").action(() => {
1207
- console.log(`${chalk7.hex("#8B5CF6").bold("CiteMe CLI")} v${program.version()}`);
1375
+ console.log(`${chalk8.hex("#8B5CF6").bold("CiteMe CLI")} v${version}`);
1208
1376
  });
1377
+ program.command("update").description("Update CiteMe CLI to the latest version").option("-c, --check", "Check for updates without installing").action((options) => updateCommand(options));
1209
1378
  program.on("command:*", () => {
1210
- console.error(chalk7.red(`Unknown command: ${program.args.join(" ")}`));
1211
- console.log(`Run ${chalk7.cyan("citeme --help")} for usage information.`);
1379
+ console.error(chalk8.red(`Unknown command: ${program.args.join(" ")}`));
1380
+ console.log(`Run ${chalk8.cyan("citeme --help")} for usage information.`);
1212
1381
  process.exit(1);
1213
1382
  });
1214
- program.parse(process.argv);
1215
- if (!process.argv.slice(2).length) {
1383
+ function showCustomHelp() {
1216
1384
  console.log(`
1217
- ${chalk7.hex("#8B5CF6").bold("CiteMe CLI")} - GEO Optimization Tool
1385
+ ${chalk8.hex("#8B5CF6").bold("CiteMe CLI")} - GEO Optimization Tool ${chalk8.gray(`v${version}`)}
1218
1386
 
1219
- ${chalk7.bold("Quick Start:")}
1220
- ${chalk7.cyan("citeme login")} Authenticate with your account
1221
- ${chalk7.cyan("citeme audit")} Analyze your project
1222
- ${chalk7.cyan("citeme suggestions generate")} Generate content suggestions
1223
- ${chalk7.cyan("citeme apply")} Apply technical suggestions
1387
+ ${chalk8.bold("Quick Start:")}
1388
+ ${chalk8.cyan("citeme login")} Authenticate with your account
1389
+ ${chalk8.cyan("citeme audit")} Analyze your project
1390
+ ${chalk8.cyan("citeme suggestions generate")} Generate content suggestions
1391
+ ${chalk8.cyan("citeme apply")} Apply technical suggestions
1224
1392
 
1225
- ${chalk7.bold("Commands:")}
1393
+ ${chalk8.bold("Commands:")}
1226
1394
  login Log in to your CiteMe account
1227
1395
  logout Log out and clear credentials
1228
1396
  whoami Show current user
@@ -1233,7 +1401,9 @@ if (!process.argv.slice(2).length) {
1233
1401
  apply Apply approved technical patches
1234
1402
  status Show CLI status
1235
1403
  config Show config file path
1404
+ update Update CLI to latest version
1236
1405
 
1237
- ${chalk7.gray("Run `citeme <command> --help` for more information.")}
1406
+ ${chalk8.gray("Run `citeme <command> --help` for more information.")}
1238
1407
  `);
1239
1408
  }
1409
+ program.parse(process.argv);
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@citeme/cli",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "CiteMe CLI - Audit your GEO score and apply optimizations directly in your codebase",
5
5
  "author": "CiteMe <contact@citeme.io>",
6
6
  "license": "MIT",
7
7
  "type": "module",
8
8
  "bin": {
9
- "citeme": "dist/index.js"
9
+ "citeme": "./dist/index.js"
10
10
  },
11
11
  "main": "./dist/index.js",
12
12
  "files": [
@@ -50,7 +50,7 @@
50
50
  "url": "https://github.com/maevo-app/citeme-saas.git",
51
51
  "directory": "packages/cli"
52
52
  },
53
- "homepage": "https://citeme.fr",
53
+ "homepage": "https://citeme.io",
54
54
  "bugs": {
55
55
  "url": "https://github.com/maevo-app/citeme-saas/issues"
56
56
  }