contextstore-app 1.0.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.
@@ -0,0 +1,8 @@
1
+ export interface Config {
2
+ serverUrl: string;
3
+ authToken: string;
4
+ email?: string;
5
+ activeWorkspace?: string;
6
+ }
7
+ export declare function loadConfig(): Config;
8
+ export declare function saveConfig(config: Partial<Config>): void;
package/dist/config.js ADDED
@@ -0,0 +1,39 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ const CONFIG_DIR = path.join(os.homedir(), '.contextstore');
5
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
6
+ const DEFAULT_CONFIG = {
7
+ serverUrl: process.env.CONTEXTSTORE_SERVER_URL || 'https://contextstore.oritm.tech',
8
+ authToken: ''
9
+ };
10
+ export function loadConfig() {
11
+ try {
12
+ if (!fs.existsSync(CONFIG_DIR)) {
13
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
14
+ }
15
+ if (!fs.existsSync(CONFIG_FILE)) {
16
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(DEFAULT_CONFIG, null, 2), 'utf-8');
17
+ return DEFAULT_CONFIG;
18
+ }
19
+ const data = fs.readFileSync(CONFIG_FILE, 'utf-8');
20
+ return { ...DEFAULT_CONFIG, ...JSON.parse(data) };
21
+ }
22
+ catch (error) {
23
+ console.error('Error loading config, using defaults:', error);
24
+ return DEFAULT_CONFIG;
25
+ }
26
+ }
27
+ export function saveConfig(config) {
28
+ try {
29
+ if (!fs.existsSync(CONFIG_DIR)) {
30
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
31
+ }
32
+ const current = loadConfig();
33
+ const updated = { ...current, ...config };
34
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(updated, null, 2), 'utf-8');
35
+ }
36
+ catch (error) {
37
+ console.error('Error saving config:', error);
38
+ }
39
+ }
@@ -0,0 +1,6 @@
1
+ export interface ProjectInfo {
2
+ name: string;
3
+ path: string;
4
+ type: string;
5
+ }
6
+ export declare function detectProjects(): Promise<ProjectInfo[]>;
@@ -0,0 +1,154 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ const COMMON_PROJECT_MARKERS = [
5
+ { file: 'package.json', type: 'Node/JS' },
6
+ { file: 'requirements.txt', type: 'Python' },
7
+ { file: 'pyproject.toml', type: 'Python' },
8
+ { file: 'Cargo.toml', type: 'Rust' },
9
+ { file: 'go.mod', type: 'Go' },
10
+ { file: 'Gemfile', type: 'Ruby' },
11
+ { file: 'pom.xml', type: 'Java/Maven' },
12
+ { file: 'build.gradle', type: 'Java/Gradle' },
13
+ { file: 'CMakeLists.txt', type: 'C/C++' },
14
+ { file: '.git', type: 'Git Repository', isDir: true }
15
+ ];
16
+ export async function detectProjects() {
17
+ const projects = [];
18
+ // 1. Check if the current working directory itself is a project
19
+ const currentDir = path.resolve(process.cwd());
20
+ const currentType = identifyProjectType(currentDir);
21
+ if (currentType) {
22
+ projects.push({
23
+ name: `Current: ${path.basename(currentDir)}`,
24
+ path: currentDir,
25
+ type: currentType
26
+ });
27
+ }
28
+ // 2. Determine safe search roots
29
+ const searchRoots = [];
30
+ // Add parent of current directory if it's safe to scan (to find sibling projects)
31
+ const parentDir = path.dirname(currentDir);
32
+ if (isSafeToScan(parentDir)) {
33
+ searchRoots.push(parentDir);
34
+ }
35
+ // Add standard user locations
36
+ const desktopPath = path.join(os.homedir(), 'Desktop');
37
+ const documentsPath = path.join(os.homedir(), 'Documents');
38
+ if (isSafeToScan(desktopPath))
39
+ searchRoots.push(desktopPath);
40
+ if (isSafeToScan(documentsPath))
41
+ searchRoots.push(documentsPath);
42
+ if (isSafeToScan(os.homedir()))
43
+ searchRoots.push(os.homedir());
44
+ for (const root of searchRoots) {
45
+ if (!fs.existsSync(root))
46
+ continue;
47
+ try {
48
+ const items = fs.readdirSync(root);
49
+ for (const item of items) {
50
+ if (item.startsWith('.') || item === 'node_modules' || item === 'Library' || item === 'Applications') {
51
+ continue;
52
+ }
53
+ const fullPath = path.join(root, item);
54
+ try {
55
+ const stat = fs.statSync(fullPath);
56
+ if (stat.isDirectory()) {
57
+ const projectType = identifyProjectType(fullPath);
58
+ if (projectType) {
59
+ projects.push({
60
+ name: item,
61
+ path: fullPath,
62
+ type: projectType
63
+ });
64
+ }
65
+ else {
66
+ // Deep scan 1 level for projects inside directories (e.g. Documents/Projects/...)
67
+ const subItems = fs.readdirSync(fullPath);
68
+ for (const subItem of subItems) {
69
+ if (subItem.startsWith('.') || subItem === 'node_modules')
70
+ continue;
71
+ const subFullPath = path.join(fullPath, subItem);
72
+ try {
73
+ const subStat = fs.statSync(subFullPath);
74
+ if (subStat.isDirectory()) {
75
+ const subType = identifyProjectType(subFullPath);
76
+ if (subType) {
77
+ projects.push({
78
+ name: `${item}/${subItem}`,
79
+ path: subFullPath,
80
+ type: subType
81
+ });
82
+ }
83
+ }
84
+ }
85
+ catch {
86
+ // Ignore permission or file errors
87
+ }
88
+ }
89
+ }
90
+ }
91
+ }
92
+ catch {
93
+ // Ignore directory read errors
94
+ }
95
+ }
96
+ }
97
+ catch (error) {
98
+ // Ignore root read errors
99
+ }
100
+ }
101
+ // Deduplicate and return top 10 unique projects
102
+ return projects
103
+ .filter((v, i, a) => a.findIndex(t => t.path === v.path) === i)
104
+ .slice(0, 10);
105
+ }
106
+ function identifyProjectType(dirPath) {
107
+ try {
108
+ const files = fs.readdirSync(dirPath);
109
+ for (const marker of COMMON_PROJECT_MARKERS) {
110
+ if (files.includes(marker.file)) {
111
+ const markerPath = path.join(dirPath, marker.file);
112
+ try {
113
+ const stat = fs.statSync(markerPath);
114
+ if (marker.isDir && stat.isDirectory()) {
115
+ return marker.type;
116
+ }
117
+ else if (!marker.isDir && stat.isFile()) {
118
+ return marker.type;
119
+ }
120
+ }
121
+ catch {
122
+ // Continue if file check fails
123
+ }
124
+ }
125
+ }
126
+ }
127
+ catch {
128
+ // Return null if reading folder fails
129
+ }
130
+ return null;
131
+ }
132
+ function isSafeToScan(dirPath) {
133
+ if (!dirPath)
134
+ return false;
135
+ try {
136
+ const normalized = path.normalize(dirPath).toLowerCase();
137
+ const parsed = path.parse(normalized);
138
+ // Check if it's drive root (e.g. C:\ or /)
139
+ if (normalized === parsed.root.toLowerCase())
140
+ return false;
141
+ // Check for Windows or Unix system folders
142
+ const forbidden = [
143
+ 'c:\\users', 'c:\\users\\', 'c:\\windows', 'c:\\program files', 'c:\\program files (x86)',
144
+ '/home', '/users', '/system', '/etc', '/var', '/usr', '/bin', '/lib', '/opt', '/private'
145
+ ];
146
+ if (forbidden.some(f => normalized === f || normalized.startsWith(f + path.sep))) {
147
+ return false;
148
+ }
149
+ return true;
150
+ }
151
+ catch {
152
+ return false;
153
+ }
154
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};