bitcompass 0.4.0 → 0.4.1

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.
@@ -7,3 +7,5 @@ export declare const loadCredentials: () => StoredCredentials | null;
7
7
  export declare const saveCredentials: (creds: StoredCredentials) => void;
8
8
  export declare const clearCredentials: () => void;
9
9
  export declare const isLoggedIn: () => boolean;
10
+ /** Returns the current user email if logged in, otherwise null. Reused by whoami and init. */
11
+ export declare const getCurrentUserEmail: () => string | null;
@@ -79,3 +79,10 @@ export const isLoggedIn = () => {
79
79
  const creds = loadCredentials();
80
80
  return Boolean(creds?.access_token);
81
81
  };
82
+ /** Returns the current user email if logged in, otherwise null. Reused by whoami and init. */
83
+ export const getCurrentUserEmail = () => {
84
+ const creds = loadCredentials();
85
+ if (!creds?.access_token)
86
+ return null;
87
+ return creds.user?.email ?? null;
88
+ };
@@ -3,6 +3,11 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
3
3
  import inquirer from 'inquirer';
4
4
  import { join } from 'path';
5
5
  import { getEditorDefaultPath, getProjectConfigDir, loadProjectConfig, saveProjectConfig, } from '../auth/project-config.js';
6
+ import { getCurrentUserEmail, isLoggedIn } from '../auth/config.js';
7
+ import { gradient, printBanner } from '../lib/banner.js';
8
+ const cyan = [0, 212, 255];
9
+ const magenta = [255, 64, 200];
10
+ const INDENT = ' ';
6
11
  const EDITOR_CHOICES = [
7
12
  { name: 'VSCode', value: 'vscode' },
8
13
  { name: 'Cursor', value: 'cursor' },
@@ -26,6 +31,7 @@ const ensureGitignoreEntry = () => {
26
31
  writeFileSync(gitignorePath, `${trimmed}${suffix}\n${GITIGNORE_ENTRY}\n`, 'utf-8');
27
32
  };
28
33
  export const runInit = async () => {
34
+ await printBanner();
29
35
  const existing = loadProjectConfig();
30
36
  const answers = await inquirer.prompt([
31
37
  {
@@ -196,10 +202,21 @@ Use these commands when you need to interact with BitCompass from the terminal:
196
202
  5. **Global vs project:** Use \`--global\` flag when you want a rule available across all projects, otherwise use project-specific rules
197
203
  `;
198
204
  writeFileSync(rulePath, ruleContent, 'utf-8');
199
- console.log(chalk.green('Project configured.'));
200
- console.log(chalk.dim('Config:'), join(getProjectConfigDir(), 'config.json'));
201
- console.log(chalk.dim('Editor:'), config.editor);
202
- console.log(chalk.dim('Output path:'), config.outputPath);
203
- console.log(chalk.dim('.gitignore:'), GITIGNORE_ENTRY, 'added or already present.');
204
- console.log(chalk.green('Rule created:'), rulePath);
205
+ console.log(gradient('Project configured.', cyan, magenta));
206
+ console.log(INDENT + chalk.bold('Config:'), join(getProjectConfigDir(), 'config.json'));
207
+ console.log(INDENT + chalk.bold('Editor:'), config.editor);
208
+ console.log(INDENT + chalk.bold('Output path:'), config.outputPath);
209
+ console.log(INDENT + chalk.bold('.gitignore:'), GITIGNORE_ENTRY, 'added or already present.');
210
+ console.log(INDENT + chalk.bold('Rule created:'), rulePath);
211
+ const email = getCurrentUserEmail();
212
+ const loggedIn = isLoggedIn();
213
+ console.log('');
214
+ if (loggedIn) {
215
+ console.log(email
216
+ ? 'You are ready to go ' + chalk.bold(email) + '!'
217
+ : 'You are ready to go!');
218
+ }
219
+ else {
220
+ console.log(chalk.dim('Run ') + chalk.cyan('bitcompass login') + chalk.dim(' to sign in.'));
221
+ }
205
222
  };
@@ -1,4 +1,4 @@
1
- import { loadCredentials } from '../auth/config.js';
1
+ import { getCurrentUserEmail, loadCredentials } from '../auth/config.js';
2
2
  import chalk from 'chalk';
3
3
  export const runWhoami = () => {
4
4
  const creds = loadCredentials();
@@ -6,7 +6,7 @@ export const runWhoami = () => {
6
6
  console.error(chalk.red('Not logged in. Run bitcompass login.'));
7
7
  process.exit(1);
8
8
  }
9
- const email = creds.user?.email;
9
+ const email = getCurrentUserEmail();
10
10
  if (email) {
11
11
  console.log(email);
12
12
  }
package/dist/index.js CHANGED
@@ -5,18 +5,18 @@ import { Command } from 'commander';
5
5
  import { readFileSync } from 'fs';
6
6
  import { dirname, join } from 'path';
7
7
  import { fileURLToPath } from 'url';
8
+ import { runCommandsList, runCommandsPull, runCommandsPush, runCommandsSearch } from './commands/commands.js';
8
9
  import { runConfigGet, runConfigList, runConfigSet } from './commands/config-cmd.js';
10
+ import { runGlossary } from './commands/glossary.js';
9
11
  import { runInit } from './commands/init.js';
12
+ import { runLog, ValidationError } from './commands/log.js';
10
13
  import { runLogin } from './commands/login.js';
11
14
  import { runLogout } from './commands/logout.js';
12
15
  import { runMcpStart, runMcpStatus } from './commands/mcp.js';
13
- import { runLog, ValidationError } from './commands/log.js';
14
16
  import { runRulesList, runRulesPull, runRulesPush, runRulesSearch } from './commands/rules.js';
15
- import { runSolutionsList, runSolutionsPull, runSolutionsPush, runSolutionsSearch } from './commands/solutions.js';
16
- import { runSkillsList, runSkillsPull, runSkillsPush, runSkillsSearch } from './commands/skills.js';
17
- import { runCommandsList, runCommandsPull, runCommandsPush, runCommandsSearch } from './commands/commands.js';
18
- import { runGlossary } from './commands/glossary.js';
19
17
  import { runSharePush } from './commands/share.js';
18
+ import { runSkillsList, runSkillsPull, runSkillsPush, runSkillsSearch } from './commands/skills.js';
19
+ import { runSolutionsList, runSolutionsPull, runSolutionsPush, runSolutionsSearch } from './commands/solutions.js';
20
20
  import { runWhoami } from './commands/whoami.js';
21
21
  // Disable chalk colors when NO_COLOR is set or --no-color is passed (must run before any command)
22
22
  if (process.env.NO_COLOR !== undefined || process.argv.includes('--no-color')) {
@@ -0,0 +1,15 @@
1
+ type Rgb = [number, number, number];
2
+ /**
3
+ * Renders text with a gradient between two RGB colors.
4
+ */
5
+ export declare const gradient: (text: string, start: Rgb, end: Rgb) => string;
6
+ /**
7
+ * Glow effect: gradient that peaks in the middle (bright center, dimmer edges).
8
+ */
9
+ export declare const glow: (text: string, baseColor: Rgb) => string;
10
+ /**
11
+ * Prints the same version + "made by" banner as postinstall (for bitcompass init).
12
+ * Reads version from package.json next to dist/.
13
+ */
14
+ export declare const printBanner: () => Promise<void>;
15
+ export {};
@@ -0,0 +1,82 @@
1
+ import chalk from 'chalk';
2
+ import { readFileSync } from 'fs';
3
+ import { dirname, join } from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ /**
6
+ * Renders text with a gradient between two RGB colors.
7
+ */
8
+ export const gradient = (text, start, end) => [...text]
9
+ .map((char, i) => {
10
+ const t = text.length > 1 ? i / (text.length - 1) : 1;
11
+ const [r1, g1, b1] = start;
12
+ const [r2, g2, b2] = end;
13
+ const r = Math.round(r1 + (r2 - r1) * t);
14
+ const g = Math.round(g1 + (g2 - g1) * t);
15
+ const b = Math.round(b1 + (b2 - b1) * t);
16
+ return chalk.rgb(r, g, b)(char);
17
+ })
18
+ .join('');
19
+ /**
20
+ * Glow effect: gradient that peaks in the middle (bright center, dimmer edges).
21
+ */
22
+ export const glow = (text, baseColor) => [...text]
23
+ .map((char, i) => {
24
+ const t = text.length > 1 ? i / (text.length - 1) : 1;
25
+ const peak = 1 - 4 * (t - 0.5) * (t - 0.5);
26
+ const mult = 0.4 + 0.6 * Math.max(0, peak);
27
+ const [r, g, b] = baseColor;
28
+ const R = Math.round(r * mult);
29
+ const G = Math.round(g * mult);
30
+ const B = Math.round(b * mult);
31
+ return chalk.rgb(R, G, B)(char);
32
+ })
33
+ .join('');
34
+ const cyan = [0, 212, 255];
35
+ const magenta = [255, 64, 200];
36
+ const glowColor = [255, 120, 255];
37
+ const PREFIX = 'made by ';
38
+ const AUTHOR = '@davide97g';
39
+ const GITHUB_URL = 'https://github.com/davide97g/';
40
+ /** OSC 8 hyperlink for supported terminals. */
41
+ const link = (url, text) => `\x1b]8;;${url}\x1b\\${text}\x1b]8;;\x1b\\`;
42
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
43
+ /**
44
+ * Prints the same version + "made by" banner as postinstall (for bitcompass init).
45
+ * Reads version from package.json next to dist/.
46
+ */
47
+ export const printBanner = async () => {
48
+ const __dirname = dirname(fileURLToPath(import.meta.url));
49
+ const pkgPath = join(__dirname, '..', '..', 'package.json');
50
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
51
+ const version = pkg.version ?? '0.0.0';
52
+ const out = process.stdout;
53
+ const isTty = out.isTTY;
54
+ const frames = 6;
55
+ const frameMs = 80;
56
+ out.write('\n');
57
+ out.write(gradient(`version ${version}`, cyan, magenta) + '\n');
58
+ if (!isTty) {
59
+ out.write(PREFIX + link(GITHUB_URL, glow(AUTHOR, glowColor)) + '\n');
60
+ out.write('\n');
61
+ return;
62
+ }
63
+ for (let f = 0; f < frames; f++) {
64
+ const t = f / (frames - 1);
65
+ const brightness = 0.3 + 0.7 * (1 - Math.cos(t * Math.PI));
66
+ const styledAuthor = [...AUTHOR]
67
+ .map((char, i) => {
68
+ const ti = AUTHOR.length > 1 ? i / (AUTHOR.length - 1) : 1;
69
+ const peak = 1 - 4 * (ti - 0.5) * (ti - 0.5);
70
+ const mult = (0.4 + 0.6 * Math.max(0, peak)) * brightness;
71
+ const [r, g, b] = glowColor;
72
+ return chalk.rgb(Math.round(r * Math.min(1, mult)), Math.round(g * Math.min(1, mult)), Math.round(b * Math.min(1, mult)))(char);
73
+ })
74
+ .join('');
75
+ const line = PREFIX + link(GITHUB_URL, styledAuthor);
76
+ out.write('\r\x1b[K' + line);
77
+ await sleep(frameMs);
78
+ }
79
+ const finalLine = PREFIX + link(GITHUB_URL, glow(AUTHOR, glowColor));
80
+ out.write('\r\x1b[K' + finalLine + '\n');
81
+ out.write('\n');
82
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bitcompass",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "BitCompass CLI - rules, solutions, and MCP server",
5
5
  "type": "module",
6
6
  "bin": {
@@ -65,25 +65,29 @@ const glowWithBrightness = (text, [r, g, b], brightness) =>
65
65
 
66
66
  const cyan = [0, 212, 255];
67
67
  const magenta = [255, 64, 200];
68
- const amber = [255, 190, 50];
69
68
  const glowColor = [255, 120, 255];
70
69
 
71
70
  const PREFIX = "made by ";
72
- const AUTHOR = "davide97g";
71
+ const AUTHOR = "@davide97g";
73
72
  const GITHUB_URL = "https://github.com/davide97g/";
73
+ const INIT_TIP =
74
+ chalk.dim("Run ") + chalk.cyan("bitcompass init") + chalk.dim(" in your project to configure.");
74
75
 
75
76
  /** Wraps text in OSC 8 hyperlink so it's clickable in supported terminals (VS Code, iTerm2, Windows Terminal). */
76
77
  const link = (url, text) => `\x1b]8;;${url}\x1b\\${text}\x1b]8;;\x1b\\`;
77
78
 
78
79
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
79
80
 
81
+ /** npm v7+ runs lifecycle scripts in background and suppresses stdout. Write to stderr so the message is visible during `npm i bitcompass -g`. */
82
+ const out = process.stderr;
83
+
80
84
  const animateAuthorLine = async () => {
81
- const isTty = process.stdout.isTTY;
85
+ const isTty = out.isTTY;
82
86
  const frames = 6;
83
87
  const frameMs = 80;
84
88
 
85
89
  if (!isTty) {
86
- console.log(PREFIX + link(GITHUB_URL, glow(AUTHOR, glowColor)));
90
+ out.write(PREFIX + link(GITHUB_URL, glow(AUTHOR, glowColor)) + "\n");
87
91
  return;
88
92
  }
89
93
 
@@ -92,14 +96,15 @@ const animateAuthorLine = async () => {
92
96
  const brightness = 0.3 + 0.7 * (1 - Math.cos(t * Math.PI));
93
97
  const styledAuthor = glowWithBrightness(AUTHOR, glowColor, brightness);
94
98
  const line = PREFIX + link(GITHUB_URL, styledAuthor);
95
- process.stdout.write("\r\x1b[K" + line);
99
+ out.write("\r\x1b[K" + line);
96
100
  await sleep(frameMs);
97
101
  }
98
102
  const finalLine = PREFIX + link(GITHUB_URL, glow(AUTHOR, glowColor));
99
- process.stdout.write("\r\x1b[K" + finalLine + "\n");
103
+ out.write("\r\x1b[K" + finalLine + "\n");
100
104
  };
101
105
 
102
- console.log("");
103
- console.log(gradient(`version ${version}`, cyan, magenta));
106
+ out.write("\n");
107
+ out.write(gradient(`version ${version}`, cyan, magenta) + "\n");
104
108
  await animateAuthorLine();
105
- console.log("");
109
+ out.write(INIT_TIP + "\n");
110
+ out.write("\n");