@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.
- package/README.md +227 -0
- package/dist/commands/cat.d.ts +3 -0
- package/dist/commands/cat.d.ts.map +1 -0
- package/dist/commands/cat.js +153 -0
- package/dist/commands/cat.js.map +1 -0
- package/dist/commands/files.d.ts +3 -0
- package/dist/commands/files.d.ts.map +1 -0
- package/dist/commands/files.js +121 -0
- package/dist/commands/files.js.map +1 -0
- package/dist/commands/find.d.ts +3 -0
- package/dist/commands/find.d.ts.map +1 -0
- package/dist/commands/find.js +119 -0
- package/dist/commands/find.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +157 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +44 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +3 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +22 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/projects.d.ts +3 -0
- package/dist/commands/projects.d.ts.map +1 -0
- package/dist/commands/projects.js +64 -0
- package/dist/commands/projects.js.map +1 -0
- package/dist/commands/search.d.ts +3 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +79 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/setup-claude.d.ts +3 -0
- package/dist/commands/setup-claude.d.ts.map +1 -0
- package/dist/commands/setup-claude.js +106 -0
- package/dist/commands/setup-claude.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +103 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/sync.d.ts +3 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +118 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/tags.d.ts +3 -0
- package/dist/commands/tags.d.ts.map +1 -0
- package/dist/commands/tags.js +312 -0
- package/dist/commands/tags.js.map +1 -0
- package/dist/commands/whoami.d.ts +3 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +35 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/commands/workspaces.d.ts +3 -0
- package/dist/commands/workspaces.d.ts.map +1 -0
- package/dist/commands/workspaces.js +48 -0
- package/dist/commands/workspaces.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api-client.d.ts +11 -0
- package/dist/lib/api-client.d.ts.map +1 -0
- package/dist/lib/api-client.js +61 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/lib/cache.d.ts +20 -0
- package/dist/lib/cache.d.ts.map +1 -0
- package/dist/lib/cache.js +79 -0
- package/dist/lib/cache.js.map +1 -0
- package/dist/lib/config.d.ts +4 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +40 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/msal.d.ts +25 -0
- package/dist/lib/msal.d.ts.map +1 -0
- package/dist/lib/msal.js +150 -0
- package/dist/lib/msal.js.map +1 -0
- package/dist/lib/output.d.ts +40 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +70 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/types/index.d.ts +58 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- 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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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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 @@
|
|
|
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"}
|
package/dist/lib/msal.js
ADDED
|
@@ -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"}
|