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.
- package/dist/config.d.ts +8 -0
- package/dist/config.js +39 -0
- package/dist/detector.d.ts +6 -0
- package/dist/detector.js +154 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +874 -0
- package/dist/indexer.d.ts +6 -0
- package/dist/indexer.js +181 -0
- package/dist/syncer.d.ts +8 -0
- package/dist/syncer.js +77 -0
- package/dist/type-detector.d.ts +1 -0
- package/dist/type-detector.js +53 -0
- package/dist/walker.d.ts +4 -0
- package/dist/walker.js +103 -0
- package/dist/watcher.d.ts +3 -0
- package/dist/watcher.js +71 -0
- package/package.json +28 -0
package/dist/config.d.ts
ADDED
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
|
+
}
|
package/dist/detector.js
ADDED
|
@@ -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
|
+
}
|
package/dist/index.d.ts
ADDED