careervivid 1.12.2 → 1.12.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmM1D"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAqM1D"}
@@ -10,7 +10,7 @@
10
10
  import chalk from "chalk";
11
11
  import ora from "ora";
12
12
  import boxen from "boxen";
13
- import { CONFIG_FILE, loadConfig, setConfigValue } from "../config.js";
13
+ import { CONFIG_FILE, loadConfig, setConfigValue, stampSession } from "../config.js";
14
14
  import { verifyKey, isApiError } from "../api.js";
15
15
  import { getApiKey } from "../config.js";
16
16
  import { printError, printInfo } from "../output.js";
@@ -66,6 +66,7 @@ export function registerAuthCommand(program) {
66
66
  process.exit(1);
67
67
  }
68
68
  setConfigValue("apiKey", apiKey);
69
+ stampSession(); // start 90-day session clock
69
70
  if (!jsonMode) {
70
71
  console.log(boxen(`${chalk.bold.green("✔ Key saved successfully!")}\n\n` +
71
72
  `${chalk.dim("Name: ")} ${chalk.white(result.name)}${adminBadge(result.isAdmin)}\n` +
@@ -174,6 +175,7 @@ export function registerAuthCommand(program) {
174
175
  return;
175
176
  }
176
177
  delete config.apiKey;
178
+ delete config.sessionCreatedAt;
177
179
  const { saveConfig } = await import("../config.js");
178
180
  saveConfig(config);
179
181
  if (jsonMode) {
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function registerLogoutCommand(program: Command): void;
3
+ //# sourceMappingURL=logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,QAkCrD"}
@@ -0,0 +1,36 @@
1
+ import chalk from "chalk";
2
+ import { clearSession, loadConfig } from "../config.js";
3
+ export function registerLogoutCommand(program) {
4
+ program
5
+ .command("logout")
6
+ .description("Log out and clear your saved CareerVivid credentials")
7
+ .option("--json", "Machine-readable output")
8
+ .action((options) => {
9
+ const cfg = loadConfig();
10
+ if (!cfg.apiKey) {
11
+ const msg = "You are not currently logged in.";
12
+ if (options.json) {
13
+ console.log(JSON.stringify({ status: "not_logged_in", message: msg }));
14
+ }
15
+ else {
16
+ console.log(chalk.yellow(`\n ⚠ ${msg}\n`));
17
+ }
18
+ return;
19
+ }
20
+ clearSession();
21
+ if (options.json) {
22
+ console.log(JSON.stringify({ status: "logged_out" }));
23
+ }
24
+ else {
25
+ console.log(`
26
+ ${chalk.green("✔")} Logged out of CareerVivid.
27
+
28
+ ${chalk.dim("Your LLM provider settings and config have been preserved.")}
29
+ ${chalk.dim("Credentials cleared: apiKey, sessionCreatedAt")}
30
+
31
+ To log back in:
32
+ ${chalk.cyan("cv login")}
33
+ `);
34
+ }
35
+ });
36
+ }
package/dist/config.d.ts CHANGED
@@ -11,8 +11,11 @@ export type LLMProvider = 'careervivid' | 'gemini' | 'openai' | 'anthropic' | 'o
11
11
  export interface CareerVividConfig {
12
12
  apiKey?: string;
13
13
  apiUrl?: string;
14
+ /** @internal — CareerVivid platform key, never exposed to users */
14
15
  geminiKey?: string;
15
16
  targetCompanies?: string;
17
+ /** ISO timestamp of when the CLI session was created */
18
+ sessionCreatedAt?: string;
16
19
  /** BYO LLM provider preference */
17
20
  llmProvider?: LLMProvider;
18
21
  /** BYO model identifier (e.g. "gpt-4o", "claude-opus-4-5", "gemini-2.5-pro") */
@@ -35,6 +38,14 @@ export declare function getApiKey(): string | undefined;
35
38
  export declare function getGeminiKey(): string | undefined;
36
39
  export declare function getApiUrl(): string;
37
40
  export declare function setConfigValue(key: keyof CareerVividConfig, value: string): void;
41
+ /** How long a CLI session stays valid (90 days in ms) */
42
+ export declare const SESSION_TTL_MS: number;
43
+ /** Returns true if the stored session is still valid */
44
+ export declare function isSessionValid(): boolean;
45
+ /** Call when user successfully authenticates — stamps the session creation time */
46
+ export declare function stampSession(): void;
47
+ /** Clear all auth credentials (logout) */
48
+ export declare function clearSession(): void;
38
49
  /**
39
50
  * Returns the active LLM config, with env var overrides.
40
51
  * Priority: CLI flags (passed in) > env vars > config file > defaults.
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,eAAO,MAAM,WAAW,QAAyC,CAAC;AAElE,eAAO,MAAM,eAAe,gCAAgC,CAAC;AAE7D,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEtG,MAAM,WAAW,iBAAiB;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kCAAkC;IAClC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0FAA0F;IAC1F,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACtB,QAAQ,EAAE,WAAW,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,IAAI,iBAAiB,CAQ9C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAE1D;AAED,wBAAgB,SAAS,IAAI,MAAM,GAAG,SAAS,CAG9C;AAED,iGAAiG;AACjG,wBAAgB,YAAY,IAAI,MAAM,GAAG,SAAS,CAEjD;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,iBAAiB,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAIhF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,CAAC,EAAE;IACrC,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,SAAS,CA6BZ"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,eAAO,MAAM,WAAW,QAAyC,CAAC;AAElE,eAAO,MAAM,eAAe,gCAAgC,CAAC;AAE7D,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEtG,MAAM,WAAW,iBAAiB;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wDAAwD;IACxD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kCAAkC;IAClC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0FAA0F;IAC1F,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACtB,QAAQ,EAAE,WAAW,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,IAAI,iBAAiB,CAQ9C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAE1D;AAED,wBAAgB,SAAS,IAAI,MAAM,GAAG,SAAS,CAG9C;AAED,iGAAiG;AACjG,wBAAgB,YAAY,IAAI,MAAM,GAAG,SAAS,CAEjD;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,iBAAiB,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAIhF;AAID,yDAAyD;AACzD,eAAO,MAAM,cAAc,QAA2B,CAAC;AAEvD,wDAAwD;AACxD,wBAAgB,cAAc,IAAI,OAAO,CAMxC;AAED,mFAAmF;AACnF,wBAAgB,YAAY,IAAI,IAAI,CAInC;AAED,0CAA0C;AAC1C,wBAAgB,YAAY,IAAI,IAAI,CAMnC;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,CAAC,EAAE;IACrC,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,SAAS,CA6BZ"}
package/dist/config.js CHANGED
@@ -40,6 +40,33 @@ export function setConfigValue(key, value) {
40
40
  current[key] = value;
41
41
  saveConfig(current);
42
42
  }
43
+ // ── Session / re-auth ────────────────────────────────────────────────────────
44
+ /** How long a CLI session stays valid (90 days in ms) */
45
+ export const SESSION_TTL_MS = 90 * 24 * 60 * 60 * 1000;
46
+ /** Returns true if the stored session is still valid */
47
+ export function isSessionValid() {
48
+ const cfg = loadConfig();
49
+ if (!cfg.apiKey)
50
+ return false;
51
+ if (!cfg.sessionCreatedAt)
52
+ return true; // legacy key with no timestamp → still valid
53
+ const age = Date.now() - new Date(cfg.sessionCreatedAt).getTime();
54
+ return age < SESSION_TTL_MS;
55
+ }
56
+ /** Call when user successfully authenticates — stamps the session creation time */
57
+ export function stampSession() {
58
+ const cfg = loadConfig();
59
+ cfg.sessionCreatedAt = new Date().toISOString();
60
+ saveConfig(cfg);
61
+ }
62
+ /** Clear all auth credentials (logout) */
63
+ export function clearSession() {
64
+ const cfg = loadConfig();
65
+ delete cfg.apiKey;
66
+ delete cfg.sessionCreatedAt;
67
+ // preserve geminiKey (internal) and user preferences
68
+ saveConfig(cfg);
69
+ }
43
70
  /**
44
71
  * Returns the active LLM config, with env var overrides.
45
72
  * Priority: CLI flags (passed in) > env vars > config file > defaults.
package/dist/index.js CHANGED
@@ -25,9 +25,11 @@ import chalk from "chalk";
25
25
  import { join, dirname } from "path";
26
26
  import { fileURLToPath } from "url";
27
27
  import { CONFIG_FILE } from "./config.js";
28
+ import { isSessionValid } from "./config.js";
28
29
  import { getHelpHeader, printWelcome } from "./branding.js";
29
30
  import { registerAuthCommand } from "./commands/auth.js";
30
31
  import { registerLoginCommand } from "./commands/login.js";
32
+ import { registerLogoutCommand } from "./commands/logout.js";
31
33
  import { registerPublishCommand } from "./commands/publish.js";
32
34
  import { registerConfigCommand } from "./commands/config.js";
33
35
  import { registerUpdateCommand } from "./commands/update.js";
@@ -50,6 +52,7 @@ program
50
52
  .helpOption("-h, --help", "Show help");
51
53
  registerAuthCommand(program);
52
54
  registerLoginCommand(program);
55
+ registerLogoutCommand(program);
53
56
  registerPublishCommand(program);
54
57
  registerConfigCommand(program);
55
58
  registerUpdateCommand(program);
@@ -74,6 +77,35 @@ async function main() {
74
77
  `);
75
78
  return;
76
79
  }
80
+ // ── Session expiry check (firebase-cli style) ──────────────────────────────
81
+ // Skip for auth/login/logout/config/help commands — they don’t need a live session
82
+ const SESSION_EXEMPT = ["login", "logout", "auth", "config", "upgrade", "-v", "--version", "-h", "--help", "help"];
83
+ const subcommand = process.argv[2] ?? "";
84
+ const isExempt = SESSION_EXEMPT.some((c) => subcommand === c || subcommand.startsWith(c));
85
+ if (!isExempt && !process.env.CV_API_KEY && !isSessionValid()) {
86
+ const { loadConfig } = await import("./config.js");
87
+ const hasKey = !!loadConfig().apiKey;
88
+ if (hasKey) {
89
+ // Session expired
90
+ console.error(`
91
+ ${chalk.yellow("⚠")} ${chalk.bold("Your CareerVivid session has expired.")} (90-day limit)
92
+
93
+ Please re-authenticate:
94
+ ${chalk.cyan("cv login")}
95
+
96
+ Or visit: ${chalk.underline.blue("https://careervivid.app/developer")}
97
+ `);
98
+ }
99
+ else {
100
+ // No key at all
101
+ console.error(`
102
+ ${chalk.red("✖")} ${chalk.bold("Not logged in to CareerVivid.")}
103
+
104
+ ${chalk.cyan("cv login")}
105
+ `);
106
+ }
107
+ process.exit(1);
108
+ }
77
109
  try {
78
110
  await program.parseAsync(process.argv);
79
111
  // Check for updates asynchronously after command execution
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "careervivid",
3
- "version": "1.12.2",
3
+ "version": "1.12.3",
4
4
  "description": "Official CLI for CareerVivid — publish articles, diagrams, and portfolio updates from your terminal or AI agent",
5
5
  "type": "module",
6
6
  "bin": {