@contextium/cli 0.3.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 (86) hide show
  1. package/README.md +227 -0
  2. package/dist/commands/cat.d.ts +3 -0
  3. package/dist/commands/cat.d.ts.map +1 -0
  4. package/dist/commands/cat.js +153 -0
  5. package/dist/commands/cat.js.map +1 -0
  6. package/dist/commands/files.d.ts +3 -0
  7. package/dist/commands/files.d.ts.map +1 -0
  8. package/dist/commands/files.js +121 -0
  9. package/dist/commands/files.js.map +1 -0
  10. package/dist/commands/find.d.ts +3 -0
  11. package/dist/commands/find.d.ts.map +1 -0
  12. package/dist/commands/find.js +119 -0
  13. package/dist/commands/find.js.map +1 -0
  14. package/dist/commands/init.d.ts +3 -0
  15. package/dist/commands/init.d.ts.map +1 -0
  16. package/dist/commands/init.js +157 -0
  17. package/dist/commands/init.js.map +1 -0
  18. package/dist/commands/login.d.ts +3 -0
  19. package/dist/commands/login.d.ts.map +1 -0
  20. package/dist/commands/login.js +44 -0
  21. package/dist/commands/login.js.map +1 -0
  22. package/dist/commands/logout.d.ts +3 -0
  23. package/dist/commands/logout.d.ts.map +1 -0
  24. package/dist/commands/logout.js +22 -0
  25. package/dist/commands/logout.js.map +1 -0
  26. package/dist/commands/projects.d.ts +3 -0
  27. package/dist/commands/projects.d.ts.map +1 -0
  28. package/dist/commands/projects.js +64 -0
  29. package/dist/commands/projects.js.map +1 -0
  30. package/dist/commands/search.d.ts +3 -0
  31. package/dist/commands/search.d.ts.map +1 -0
  32. package/dist/commands/search.js +79 -0
  33. package/dist/commands/search.js.map +1 -0
  34. package/dist/commands/setup-claude.d.ts +3 -0
  35. package/dist/commands/setup-claude.d.ts.map +1 -0
  36. package/dist/commands/setup-claude.js +106 -0
  37. package/dist/commands/setup-claude.js.map +1 -0
  38. package/dist/commands/status.d.ts +3 -0
  39. package/dist/commands/status.d.ts.map +1 -0
  40. package/dist/commands/status.js +103 -0
  41. package/dist/commands/status.js.map +1 -0
  42. package/dist/commands/sync.d.ts +3 -0
  43. package/dist/commands/sync.d.ts.map +1 -0
  44. package/dist/commands/sync.js +118 -0
  45. package/dist/commands/sync.js.map +1 -0
  46. package/dist/commands/tags.d.ts +3 -0
  47. package/dist/commands/tags.d.ts.map +1 -0
  48. package/dist/commands/tags.js +312 -0
  49. package/dist/commands/tags.js.map +1 -0
  50. package/dist/commands/whoami.d.ts +3 -0
  51. package/dist/commands/whoami.d.ts.map +1 -0
  52. package/dist/commands/whoami.js +35 -0
  53. package/dist/commands/whoami.js.map +1 -0
  54. package/dist/commands/workspaces.d.ts +3 -0
  55. package/dist/commands/workspaces.d.ts.map +1 -0
  56. package/dist/commands/workspaces.js +48 -0
  57. package/dist/commands/workspaces.js.map +1 -0
  58. package/dist/index.d.ts +3 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +56 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/lib/api-client.d.ts +11 -0
  63. package/dist/lib/api-client.d.ts.map +1 -0
  64. package/dist/lib/api-client.js +61 -0
  65. package/dist/lib/api-client.js.map +1 -0
  66. package/dist/lib/cache.d.ts +20 -0
  67. package/dist/lib/cache.d.ts.map +1 -0
  68. package/dist/lib/cache.js +79 -0
  69. package/dist/lib/cache.js.map +1 -0
  70. package/dist/lib/config.d.ts +4 -0
  71. package/dist/lib/config.d.ts.map +1 -0
  72. package/dist/lib/config.js +40 -0
  73. package/dist/lib/config.js.map +1 -0
  74. package/dist/lib/msal.d.ts +25 -0
  75. package/dist/lib/msal.d.ts.map +1 -0
  76. package/dist/lib/msal.js +150 -0
  77. package/dist/lib/msal.js.map +1 -0
  78. package/dist/lib/output.d.ts +40 -0
  79. package/dist/lib/output.d.ts.map +1 -0
  80. package/dist/lib/output.js +70 -0
  81. package/dist/lib/output.js.map +1 -0
  82. package/dist/types/index.d.ts +58 -0
  83. package/dist/types/index.d.ts.map +1 -0
  84. package/dist/types/index.js +2 -0
  85. package/dist/types/index.js.map +1 -0
  86. package/package.json +58 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/commands/workspaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAKnC,eAAO,MAAM,iBAAiB,SAoD1B,CAAA"}
@@ -0,0 +1,48 @@
1
+ import { Command } from 'commander';
2
+ import { ApiClient } from '../lib/api-client.js';
3
+ import { loadConfig } from '../lib/config.js';
4
+ import { chalk, ora } from '../lib/output.js';
5
+ export const workspacesCommand = new Command('workspaces')
6
+ .description('List all workspaces with project counts')
7
+ .action(async () => {
8
+ const spinner = ora('Loading workspaces...').start();
9
+ try {
10
+ const config = await loadConfig();
11
+ const client = new ApiClient(config.api_key, config.api_url);
12
+ // Get all workspaces
13
+ const { data: workspacesData } = await client.get('/workspaces');
14
+ const workspaces = workspacesData.data || workspacesData;
15
+ if (!workspaces || workspaces.length === 0) {
16
+ spinner.stop();
17
+ console.log(chalk.yellow('No workspaces found'));
18
+ return;
19
+ }
20
+ // Get project counts for each workspace in parallel
21
+ const workspaceProjectCounts = await Promise.all(workspaces.map(async (workspace) => {
22
+ try {
23
+ const { data: projectsData } = await client.get(`/workspaces/${workspace.id}/projects`);
24
+ const projects = projectsData.data || projectsData;
25
+ return {
26
+ ...workspace,
27
+ projectCount: projects.filter((p) => !p.deletedAt).length
28
+ };
29
+ }
30
+ catch (error) {
31
+ return { ...workspace, projectCount: 0 };
32
+ }
33
+ }));
34
+ spinner.stop();
35
+ console.log(chalk.bold('\nYour Workspaces:\n'));
36
+ for (const workspace of workspaceProjectCounts) {
37
+ const projectText = workspace.projectCount === 1 ? 'project' : 'projects';
38
+ console.log(chalk.cyan(` ${workspace.name}`), chalk.dim(`(${workspace.projectCount} ${projectText})`));
39
+ console.log(chalk.gray(` slug: ${workspace.slug}`));
40
+ console.log();
41
+ }
42
+ }
43
+ catch (error) {
44
+ spinner.fail(`Failed to load workspaces: ${error.message}`);
45
+ process.exit(1);
46
+ }
47
+ });
48
+ //# sourceMappingURL=workspaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.js","sourceRoot":"","sources":["../../src/commands/workspaces.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { loginCommand } from './commands/login.js';
4
+ import { logoutCommand } from './commands/logout.js';
5
+ import { whoamiCommand } from './commands/whoami.js';
6
+ import { initCommand } from './commands/init.js';
7
+ import { syncCommand } from './commands/sync.js';
8
+ import { catCommand } from './commands/cat.js';
9
+ import { statusCommand } from './commands/status.js';
10
+ import { searchCommand } from './commands/search.js';
11
+ import { workspacesCommand } from './commands/workspaces.js';
12
+ import { projectsCommand } from './commands/projects.js';
13
+ import { filesCommand } from './commands/files.js';
14
+ import { findCommand } from './commands/find.js';
15
+ import { setupClaudeCommand } from './commands/setup-claude.js';
16
+ import { tagsCommand } from './commands/tags.js';
17
+ const program = new Command();
18
+ program
19
+ .name('contextium')
20
+ .description('Contextium CLI — sync documentation and pipe to AI coding assistants')
21
+ .version('0.3.0')
22
+ .addHelpText('after', `
23
+ Claude Code Skill:
24
+ This CLI includes a built-in Claude Code skill. When Claude Code runs
25
+ "contextium --help", it learns all available commands automatically.
26
+
27
+ To grant Claude Code permission to run contextium commands:
28
+ contextium setup-claude
29
+
30
+ Example Claude Code prompts:
31
+ "Search my Contextium docs for authentication guides"
32
+ "List all workspaces and show me the files in the dev project"
33
+ "Sync my docs and output everything tagged foundation-context"
34
+
35
+ Skill location: .claude/skills/contextium/SKILL.md
36
+ `);
37
+ // Auth commands
38
+ program.addCommand(loginCommand);
39
+ program.addCommand(logoutCommand);
40
+ program.addCommand(whoamiCommand);
41
+ // Setup commands
42
+ program.addCommand(initCommand);
43
+ program.addCommand(setupClaudeCommand);
44
+ // Data commands
45
+ program.addCommand(workspacesCommand);
46
+ program.addCommand(projectsCommand);
47
+ program.addCommand(filesCommand);
48
+ program.addCommand(findCommand);
49
+ program.addCommand(syncCommand);
50
+ program.addCommand(catCommand);
51
+ program.addCommand(statusCommand);
52
+ program.addCommand(searchCommand);
53
+ program.addCommand(tagsCommand);
54
+ // Parse command line
55
+ program.parse();
56
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;AAE7B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,sEAAsE,CAAC;KACnF,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,OAAO,EAAE;;;;;;;;;;;;;;CAcvB,CAAC,CAAA;AAEF,gBAAgB;AAChB,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAA;AAChC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAA;AACjC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAA;AAEjC,iBAAiB;AACjB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;AAC/B,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAA;AAEtC,gBAAgB;AAChB,OAAO,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAA;AACrC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAA;AACnC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAA;AAChC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;AAC/B,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;AAC/B,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAA;AAC9B,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAA;AACjC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAA;AACjC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;AAE/B,qBAAqB;AACrB,OAAO,CAAC,KAAK,EAAE,CAAA"}
@@ -0,0 +1,11 @@
1
+ import { AxiosRequestConfig } from 'axios';
2
+ export declare class ApiClient {
3
+ private client;
4
+ private useEntraAuth;
5
+ constructor(apiKey: string, baseURL?: string);
6
+ get(url: string, config?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<any, any, {}>>;
7
+ post(url: string, data?: any, config?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<any, any, {}>>;
8
+ patch(url: string, data?: any, config?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<any, any, {}>>;
9
+ delete(url: string, config?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<any, any, {}>>;
10
+ }
11
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AAAA,OAAc,EAAiB,kBAAkB,EAAE,MAAM,OAAO,CAAA;AAGhE,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,YAAY,CAAS;gBAEjB,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,MAAuC;IAuDtE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,kBAAkB;IAI5C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,kBAAkB;IAIzD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,kBAAkB;IAI1D,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,kBAAkB;CAGtD"}
@@ -0,0 +1,61 @@
1
+ import axios from 'axios';
2
+ import { getAccessToken } from './msal.js';
3
+ export class ApiClient {
4
+ constructor(apiKey, baseURL = 'http://localhost:3001/api/v1') {
5
+ this.useEntraAuth = !apiKey;
6
+ this.client = axios.create({
7
+ baseURL,
8
+ headers: {
9
+ ...(apiKey ? { 'Authorization': `Bearer ${apiKey}` } : {}),
10
+ 'Content-Type': 'application/json',
11
+ 'User-Agent': 'contextium-cli/0.2.0'
12
+ },
13
+ timeout: 30000
14
+ });
15
+ // Request interceptor — inject Entra token if using interactive auth
16
+ this.client.interceptors.request.use(async (config) => {
17
+ if (this.useEntraAuth) {
18
+ const token = await getAccessToken();
19
+ if (token) {
20
+ config.headers.Authorization = `Bearer ${token}`;
21
+ }
22
+ else {
23
+ throw new Error('Not authenticated. Run "contextium login" or pass --api-key.');
24
+ }
25
+ }
26
+ return config;
27
+ }, (error) => Promise.reject(error));
28
+ // Response interceptor
29
+ this.client.interceptors.response.use((response) => response, (error) => {
30
+ if (error.response) {
31
+ const { status, data } = error.response;
32
+ switch (status) {
33
+ case 401:
34
+ throw new Error('Invalid API key or unauthorized');
35
+ case 403:
36
+ throw new Error('Insufficient permissions');
37
+ case 404:
38
+ throw new Error('Resource not found');
39
+ case 429:
40
+ throw new Error('Rate limit exceeded');
41
+ default:
42
+ throw new Error(data?.error?.message || 'API request failed');
43
+ }
44
+ }
45
+ throw new Error('Network error');
46
+ });
47
+ }
48
+ async get(url, config) {
49
+ return this.client.get(url, config);
50
+ }
51
+ async post(url, data, config) {
52
+ return this.client.post(url, data, config);
53
+ }
54
+ async patch(url, data, config) {
55
+ return this.client.patch(url, data, config);
56
+ }
57
+ async delete(url, config) {
58
+ return this.client.delete(url, config);
59
+ }
60
+ }
61
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { File } from '../types/index.js';
2
+ interface CacheConfig {
3
+ enabled: boolean;
4
+ ttl: number;
5
+ directory: string;
6
+ }
7
+ export declare class Cache {
8
+ private memory;
9
+ private directory;
10
+ private enabled;
11
+ private ttl;
12
+ constructor(config: CacheConfig);
13
+ get(key: string): Promise<File | null>;
14
+ getSync(key: string): File | null;
15
+ set(key: string, value: File): Promise<void>;
16
+ clear(): Promise<void>;
17
+ private sanitize;
18
+ }
19
+ export {};
20
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/lib/cache.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AAExC,UAAU,WAAW;IACnB,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,qBAAa,KAAK;IAChB,OAAO,CAAC,MAAM,CAA8C;IAC5D,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,GAAG,CAAQ;gBAEP,MAAM,EAAE,WAAW;IAOzB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IA2B5C,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAW3B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB5B,OAAO,CAAC,QAAQ;CAGjB"}
@@ -0,0 +1,79 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ export class Cache {
4
+ constructor(config) {
5
+ this.enabled = config.enabled;
6
+ this.directory = config.directory;
7
+ this.ttl = config.ttl;
8
+ this.memory = new Map();
9
+ }
10
+ async get(key) {
11
+ if (!this.enabled)
12
+ return null;
13
+ // Try memory first
14
+ const memCached = this.memory.get(key);
15
+ if (memCached && memCached.expires > Date.now()) {
16
+ return memCached.data;
17
+ }
18
+ // Try disk
19
+ try {
20
+ const filePath = path.join(this.directory, `${this.sanitize(key)}.json`);
21
+ const content = await fs.readFile(filePath, 'utf-8');
22
+ const data = JSON.parse(content);
23
+ // Restore to memory
24
+ this.memory.set(key, {
25
+ data,
26
+ expires: Date.now() + this.ttl * 1000
27
+ });
28
+ return data;
29
+ }
30
+ catch {
31
+ return null;
32
+ }
33
+ }
34
+ getSync(key) {
35
+ if (!this.enabled)
36
+ return null;
37
+ const memCached = this.memory.get(key);
38
+ if (memCached && memCached.expires > Date.now()) {
39
+ return memCached.data;
40
+ }
41
+ return null;
42
+ }
43
+ async set(key, value) {
44
+ if (!this.enabled)
45
+ return;
46
+ // Set in memory
47
+ this.memory.set(key, {
48
+ data: value,
49
+ expires: Date.now() + this.ttl * 1000
50
+ });
51
+ // Persist to disk
52
+ try {
53
+ const filePath = path.join(this.directory, `${this.sanitize(key)}.json`);
54
+ await fs.writeFile(filePath, JSON.stringify(value, null, 2), 'utf-8');
55
+ }
56
+ catch (error) {
57
+ console.error('Failed to write cache:', error);
58
+ }
59
+ }
60
+ async clear() {
61
+ this.memory.clear();
62
+ // Clear disk cache
63
+ try {
64
+ const files = await fs.readdir(this.directory);
65
+ for (const file of files) {
66
+ if (file.endsWith('.json')) {
67
+ await fs.unlink(path.join(this.directory, file));
68
+ }
69
+ }
70
+ }
71
+ catch (error) {
72
+ console.error('Failed to clear cache:', error);
73
+ }
74
+ }
75
+ sanitize(key) {
76
+ return key.replace(/[^a-z0-9_-]/gi, '_').toLowerCase();
77
+ }
78
+ }
79
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/lib/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Config } from '../types/index.js';
2
+ export declare function loadConfig(): Promise<Config>;
3
+ export declare function saveConfig(config: Config): Promise<void>;
4
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAI1C,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CA+BlD;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO9D"}
@@ -0,0 +1,40 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ const DEFAULT_API_URL = 'https://api.contextium.io/api/v1';
4
+ export async function loadConfig() {
5
+ const configPath = path.join(process.cwd(), '.contextiumrc');
6
+ try {
7
+ const content = await fs.readFile(configPath, 'utf-8');
8
+ return JSON.parse(content);
9
+ }
10
+ catch (error) {
11
+ // No .contextiumrc — return defaults (Entra auth will be used)
12
+ return {
13
+ api_key: '',
14
+ api_url: DEFAULT_API_URL,
15
+ cache: {
16
+ enabled: true,
17
+ ttl: 3600,
18
+ directory: '.contextium-cache',
19
+ max_size_mb: 100,
20
+ },
21
+ sync: {
22
+ auto: true,
23
+ on_command: ['build', 'test'],
24
+ notify_changes: true,
25
+ interval: 300,
26
+ },
27
+ files: {
28
+ include: [],
29
+ exclude: [],
30
+ tags: [],
31
+ auto_include_tags: true,
32
+ },
33
+ };
34
+ }
35
+ }
36
+ export async function saveConfig(config) {
37
+ const configPath = path.join(process.cwd(), '.contextiumrc');
38
+ await fs.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
39
+ }
40
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAA;AAC5B,OAAO,IAAI,MAAM,MAAM,CAAA;AAGvB,MAAM,eAAe,GAAG,kCAAkC,CAAA;AAE1D,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,eAAe,CAAC,CAAA;IAE5D,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;QACtD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,+DAA+D;QAC/D,OAAO;YACL,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,eAAe;YACxB,KAAK,EAAE;gBACL,OAAO,EAAE,IAAI;gBACb,GAAG,EAAE,IAAI;gBACT,SAAS,EAAE,mBAAmB;gBAC9B,WAAW,EAAE,GAAG;aACjB;YACD,IAAI,EAAE;gBACJ,IAAI,EAAE,IAAI;gBACV,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;gBAC7B,cAAc,EAAE,IAAI;gBACpB,QAAQ,EAAE,GAAG;aACd;YACD,KAAK,EAAE;gBACL,OAAO,EAAE,EAAE;gBACX,OAAO,EAAE,EAAE;gBACX,IAAI,EAAE,EAAE;gBACR,iBAAiB,EAAE,IAAI;aACxB;SACF,CAAA;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAc;IAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,eAAe,CAAC,CAAA;IAC5D,MAAM,EAAE,CAAC,SAAS,CAChB,UAAU,EACV,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAC/B,OAAO,CACR,CAAA;AACH,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { type AuthenticationResult } from '@azure/msal-node';
2
+ /**
3
+ * Interactive login — opens system browser for Entra authentication.
4
+ * Returns the authentication result with access token.
5
+ */
6
+ export declare function loginInteractive(): Promise<AuthenticationResult>;
7
+ /**
8
+ * Silently acquire a token using the cached refresh token.
9
+ * Returns null if no cached account or refresh has failed.
10
+ */
11
+ export declare function acquireTokenSilent(): Promise<AuthenticationResult | null>;
12
+ /**
13
+ * Get the currently cached account (if any).
14
+ */
15
+ export declare function getCachedAccount(): Promise<import("@azure/msal-node").AccountInfo | null | undefined>;
16
+ /**
17
+ * Clear all cached accounts and tokens (logout).
18
+ */
19
+ export declare function clearCache(): Promise<void>;
20
+ /**
21
+ * Get a valid access token — tries silent first, returns null if not logged in.
22
+ * This is the main entry point for commands that need auth.
23
+ */
24
+ export declare function getAccessToken(): Promise<string | null>;
25
+ //# sourceMappingURL=msal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"msal.d.ts","sourceRoot":"","sources":["../../src/lib/msal.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+C,KAAK,oBAAoB,EAAY,MAAM,kBAAkB,CAAA;AAyEnH;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CA+BtE;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAkB/E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,uEAIrC;AAED;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAYhD;AAED;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAG7D"}
@@ -0,0 +1,150 @@
1
+ import { PublicClientApplication, LogLevel } from '@azure/msal-node';
2
+ import open from 'open';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import os from 'os';
6
+ // Entra External ID (CIAM) configuration
7
+ const ENTRA_DOMAIN = 'auth.contextium.io';
8
+ const ENTRA_TENANT_ID = '9b6eccb4-2057-43a8-be7f-f558ad8e7bc1';
9
+ const CLI_CLIENT_ID = 'e6cbbe89-a519-48c3-8818-73638b63e02f';
10
+ const API_SCOPE = 'api://7f322892-fd5c-4d8b-9c60-8f821f847c3a/user_impersonation';
11
+ const SCOPES = [API_SCOPE, 'openid', 'profile', 'email', 'offline_access'];
12
+ const CACHE_DIR = path.join(os.homedir(), '.contextium');
13
+ const CACHE_PATH = path.join(CACHE_DIR, 'msal-cache.json');
14
+ function ensureCacheDir() {
15
+ if (!fs.existsSync(CACHE_DIR)) {
16
+ fs.mkdirSync(CACHE_DIR, { recursive: true, mode: 0o700 });
17
+ }
18
+ }
19
+ function readCache() {
20
+ ensureCacheDir();
21
+ if (fs.existsSync(CACHE_PATH)) {
22
+ return fs.readFileSync(CACHE_PATH, 'utf-8');
23
+ }
24
+ return '';
25
+ }
26
+ function writeCache(data) {
27
+ ensureCacheDir();
28
+ fs.writeFileSync(CACHE_PATH, data, { mode: 0o600 });
29
+ }
30
+ let pcaInstance = null;
31
+ function createPca() {
32
+ if (pcaInstance)
33
+ return pcaInstance;
34
+ const msalConfig = {
35
+ auth: {
36
+ clientId: CLI_CLIENT_ID,
37
+ authority: `https://${ENTRA_DOMAIN}/${ENTRA_TENANT_ID}`,
38
+ knownAuthorities: [ENTRA_DOMAIN],
39
+ },
40
+ cache: {
41
+ cachePlugin: {
42
+ beforeCacheAccess: async (context) => {
43
+ const data = readCache();
44
+ if (data) {
45
+ context.tokenCache.deserialize(data);
46
+ }
47
+ },
48
+ afterCacheAccess: async (context) => {
49
+ if (context.cacheHasChanged) {
50
+ writeCache(context.tokenCache.serialize());
51
+ }
52
+ },
53
+ },
54
+ },
55
+ system: {
56
+ loggerOptions: {
57
+ logLevel: LogLevel.Warning,
58
+ },
59
+ },
60
+ };
61
+ pcaInstance = new PublicClientApplication(msalConfig);
62
+ return pcaInstance;
63
+ }
64
+ /**
65
+ * Interactive login — opens system browser for Entra authentication.
66
+ * Returns the authentication result with access token.
67
+ */
68
+ export async function loginInteractive() {
69
+ const pca = createPca();
70
+ const result = await pca.acquireTokenInteractive({
71
+ scopes: SCOPES,
72
+ openBrowser: async (url) => {
73
+ await open(url);
74
+ },
75
+ successTemplate: `<html><head><meta charset="utf-8"><title>Contextium - Login Successful</title></head>
76
+ <body style="font-family:system-ui,-apple-system,sans-serif;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:linear-gradient(135deg,#0f172a 0%,#1e293b 100%)">
77
+ <div style="text-align:center;background:#fff;padding:48px 64px;border-radius:16px;box-shadow:0 25px 50px rgba(0,0,0,0.25)">
78
+ <div style="width:64px;height:64px;background:#22c55e;border-radius:50%;display:flex;align-items:center;justify-content:center;margin:0 auto 24px">
79
+ <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
80
+ </div>
81
+ <h1 style="color:#0f172a;font-size:24px;margin:0 0 8px;font-weight:600">Login Successful</h1>
82
+ <p style="color:#64748b;margin:0 0 24px;font-size:15px">You can close this window and return to the terminal.</p>
83
+ <div style="color:#94a3b8;font-size:13px;border-top:1px solid #e2e8f0;padding-top:16px">Contextium CLI</div>
84
+ </div></body></html>`,
85
+ errorTemplate: `<html><head><meta charset="utf-8"><title>Contextium - Login Failed</title></head>
86
+ <body style="font-family:system-ui,-apple-system,sans-serif;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:linear-gradient(135deg,#0f172a 0%,#1e293b 100%)">
87
+ <div style="text-align:center;background:#fff;padding:48px 64px;border-radius:16px;box-shadow:0 25px 50px rgba(0,0,0,0.25)">
88
+ <div style="width:64px;height:64px;background:#ef4444;border-radius:50%;display:flex;align-items:center;justify-content:center;margin:0 auto 24px">
89
+ <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
90
+ </div>
91
+ <h1 style="color:#0f172a;font-size:24px;margin:0 0 8px;font-weight:600">Login Failed</h1>
92
+ <p style="color:#64748b;margin:0 0 24px;font-size:15px">Something went wrong. Please try again.</p>
93
+ <div style="color:#94a3b8;font-size:13px;border-top:1px solid #e2e8f0;padding-top:16px">Contextium CLI</div>
94
+ </div></body></html>`,
95
+ });
96
+ return result;
97
+ }
98
+ /**
99
+ * Silently acquire a token using the cached refresh token.
100
+ * Returns null if no cached account or refresh has failed.
101
+ */
102
+ export async function acquireTokenSilent() {
103
+ const pca = createPca();
104
+ const accounts = await pca.getTokenCache().getAllAccounts();
105
+ if (accounts.length === 0) {
106
+ return null;
107
+ }
108
+ try {
109
+ const result = await pca.acquireTokenSilent({
110
+ scopes: SCOPES,
111
+ account: accounts[0],
112
+ });
113
+ return result;
114
+ }
115
+ catch {
116
+ // Refresh token expired or revoked — user needs to re-login
117
+ return null;
118
+ }
119
+ }
120
+ /**
121
+ * Get the currently cached account (if any).
122
+ */
123
+ export async function getCachedAccount() {
124
+ const pca = createPca();
125
+ const accounts = await pca.getTokenCache().getAllAccounts();
126
+ return accounts.length > 0 ? accounts[0] : null;
127
+ }
128
+ /**
129
+ * Clear all cached accounts and tokens (logout).
130
+ */
131
+ export async function clearCache() {
132
+ const pca = createPca();
133
+ const accounts = await pca.getTokenCache().getAllAccounts();
134
+ for (const account of accounts) {
135
+ await pca.getTokenCache().removeAccount(account);
136
+ }
137
+ // Also delete the cache file
138
+ if (fs.existsSync(CACHE_PATH)) {
139
+ fs.unlinkSync(CACHE_PATH);
140
+ }
141
+ }
142
+ /**
143
+ * Get a valid access token — tries silent first, returns null if not logged in.
144
+ * This is the main entry point for commands that need auth.
145
+ */
146
+ export async function getAccessToken() {
147
+ const result = await acquireTokenSilent();
148
+ return result?.accessToken ?? null;
149
+ }
150
+ //# sourceMappingURL=msal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"msal.js","sourceRoot":"","sources":["../../src/lib/msal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ export declare const colors: {
2
+ reset: string;
3
+ bold: string;
4
+ dim: string;
5
+ red: string;
6
+ green: string;
7
+ yellow: string;
8
+ blue: string;
9
+ cyan: string;
10
+ gray: string;
11
+ white: string;
12
+ };
13
+ export declare function colorize(text: string, color: keyof typeof colors): string;
14
+ export declare const chalk: {
15
+ red: (text: string) => string;
16
+ green: (text: string) => string;
17
+ yellow: (text: string) => string;
18
+ blue: (text: string) => string;
19
+ cyan: (text: string) => string;
20
+ gray: (text: string) => string;
21
+ dim: (text: string) => string;
22
+ bold: (text: string) => string;
23
+ white: (text: string) => string;
24
+ };
25
+ export declare class Spinner {
26
+ private text;
27
+ private interval?;
28
+ private frames;
29
+ private currentFrame;
30
+ constructor(text: string);
31
+ start(): this;
32
+ stop(): void;
33
+ succeed(message: string): void;
34
+ fail(message: string): void;
35
+ warn(message: string): void;
36
+ info(message: string): void;
37
+ set setText(text: string);
38
+ }
39
+ export declare function ora(text: string): Spinner;
40
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/lib/output.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM;;;;;;;;;;;CAWlB,CAAA;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,OAAO,MAAM,GAAG,MAAM,CAEzE;AAED,eAAO,MAAM,KAAK;gBACJ,MAAM;kBACJ,MAAM;mBACL,MAAM;iBACR,MAAM;iBACN,MAAM;iBACN,MAAM;gBACP,MAAM;iBACL,MAAM;kBACL,MAAM;CACrB,CAAA;AAED,qBAAa,OAAO;IAClB,OAAO,CAAC,IAAI,CAAQ;IACpB,OAAO,CAAC,QAAQ,CAAC,CAAgB;IACjC,OAAO,CAAC,MAAM,CAAqD;IACnE,OAAO,CAAC,YAAY,CAAI;gBAEZ,IAAI,EAAE,MAAM;IAIxB,KAAK,IAAI,IAAI;IAQb,IAAI,IAAI,IAAI;IAOZ,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK9B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK3B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK3B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK3B,IAAI,OAAO,CAAC,IAAI,EAAE,MAAM,EAEvB;CACF;AAED,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzC"}