olly-molly 0.1.3 ā 0.1.5
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/bin/cli.js +85 -88
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -10,9 +10,33 @@ const APP_NAME = 'olly-molly';
|
|
|
10
10
|
const REPO = 'ruucm/olly-molly';
|
|
11
11
|
const APP_DIR = path.join(os.homedir(), '.olly-molly');
|
|
12
12
|
const TARBALL_URL = `https://github.com/${REPO}/archive/refs/heads/main.tar.gz`;
|
|
13
|
+
const VERSION_URL = `https://raw.githubusercontent.com/${REPO}/main/package.json`;
|
|
13
14
|
|
|
14
15
|
console.log('\nš Olly Molly - Your AI Development Team\n');
|
|
15
16
|
|
|
17
|
+
function fetchJSON(url) {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
const get = (downloadUrl) => {
|
|
20
|
+
https.get(downloadUrl, (res) => {
|
|
21
|
+
if (res.statusCode === 302 || res.statusCode === 301) {
|
|
22
|
+
get(res.headers.location);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
let data = '';
|
|
26
|
+
res.on('data', chunk => data += chunk);
|
|
27
|
+
res.on('end', () => {
|
|
28
|
+
try {
|
|
29
|
+
resolve(JSON.parse(data));
|
|
30
|
+
} catch {
|
|
31
|
+
reject(new Error('Invalid JSON'));
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}).on('error', reject);
|
|
35
|
+
};
|
|
36
|
+
get(url);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
16
40
|
function downloadAndExtract(url, destDir) {
|
|
17
41
|
return new Promise((resolve, reject) => {
|
|
18
42
|
const tempFile = path.join(os.tmpdir(), 'olly-molly.tar.gz');
|
|
@@ -22,33 +46,23 @@ function downloadAndExtract(url, destDir) {
|
|
|
22
46
|
|
|
23
47
|
const download = (downloadUrl) => {
|
|
24
48
|
https.get(downloadUrl, (response) => {
|
|
25
|
-
// Handle redirects
|
|
26
49
|
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
27
50
|
download(response.headers.location);
|
|
28
51
|
return;
|
|
29
52
|
}
|
|
30
|
-
|
|
31
53
|
if (response.statusCode !== 200) {
|
|
32
54
|
reject(new Error(`Download failed: ${response.statusCode}`));
|
|
33
55
|
return;
|
|
34
56
|
}
|
|
35
|
-
|
|
36
57
|
response.pipe(file);
|
|
37
58
|
file.on('finish', () => {
|
|
38
59
|
file.close();
|
|
39
|
-
|
|
40
60
|
console.log('š¦ Extracting...');
|
|
41
|
-
|
|
42
|
-
// Create dest directory
|
|
43
61
|
if (!fs.existsSync(destDir)) {
|
|
44
62
|
fs.mkdirSync(destDir, { recursive: true });
|
|
45
63
|
}
|
|
46
|
-
|
|
47
|
-
// Extract tarball
|
|
48
64
|
try {
|
|
49
|
-
execSync(`tar -xzf "${tempFile}" -C "${destDir}" --strip-components=1`, {
|
|
50
|
-
stdio: 'pipe'
|
|
51
|
-
});
|
|
65
|
+
execSync(`tar -xzf "${tempFile}" -C "${destDir}" --strip-components=1`, { stdio: 'pipe' });
|
|
52
66
|
fs.unlinkSync(tempFile);
|
|
53
67
|
resolve();
|
|
54
68
|
} catch (err) {
|
|
@@ -57,95 +71,78 @@ function downloadAndExtract(url, destDir) {
|
|
|
57
71
|
});
|
|
58
72
|
}).on('error', reject);
|
|
59
73
|
};
|
|
60
|
-
|
|
61
74
|
download(url);
|
|
62
75
|
});
|
|
63
76
|
}
|
|
64
77
|
|
|
78
|
+
async function getLocalVersion() {
|
|
79
|
+
const pkgPath = path.join(APP_DIR, 'package.json');
|
|
80
|
+
if (!fs.existsSync(pkgPath)) return null;
|
|
81
|
+
try {
|
|
82
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
83
|
+
return pkg.version;
|
|
84
|
+
} catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
65
89
|
async function main() {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
90
|
+
try {
|
|
91
|
+
// Check remote version
|
|
92
|
+
let remoteVersion = null;
|
|
93
|
+
try {
|
|
94
|
+
const remotePkg = await fetchJSON(VERSION_URL);
|
|
95
|
+
remoteVersion = remotePkg.version;
|
|
96
|
+
} catch {
|
|
97
|
+
// Offline or error - continue with local
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const localVersion = await getLocalVersion();
|
|
101
|
+
|
|
102
|
+
// Auto-update if versions differ
|
|
103
|
+
if (localVersion && remoteVersion && localVersion !== remoteVersion) {
|
|
104
|
+
console.log(`š New version available: ${localVersion} ā ${remoteVersion}\n`);
|
|
105
|
+
console.log(' Updating...\n');
|
|
72
106
|
fs.rmSync(APP_DIR, { recursive: true, force: true });
|
|
73
107
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
console.log('š¦ First run - downloading Olly Molly...\n');
|
|
79
|
-
try {
|
|
108
|
+
|
|
109
|
+
// Download if not exists
|
|
110
|
+
if (!fs.existsSync(APP_DIR)) {
|
|
111
|
+
console.log('š¦ Downloading Olly Molly...\n');
|
|
80
112
|
await downloadAndExtract(TARBALL_URL, APP_DIR);
|
|
81
113
|
console.log('ā
Downloaded!\n');
|
|
82
|
-
} catch (error) {
|
|
83
|
-
console.error('ā Download failed:', error.message);
|
|
84
|
-
console.error('\n Make sure the repository is public at:');
|
|
85
|
-
console.error(` https://github.com/${REPO}\n`);
|
|
86
|
-
process.exit(1);
|
|
87
114
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
try {
|
|
95
|
-
execSync('npm install --production', {
|
|
96
|
-
cwd: APP_DIR,
|
|
97
|
-
stdio: 'inherit'
|
|
98
|
-
});
|
|
99
|
-
} catch (error) {
|
|
100
|
-
console.error('ā Failed to install dependencies');
|
|
101
|
-
process.exit(1);
|
|
115
|
+
|
|
116
|
+
// Install dependencies if needed
|
|
117
|
+
const nodeModulesPath = path.join(APP_DIR, 'node_modules');
|
|
118
|
+
if (!fs.existsSync(nodeModulesPath)) {
|
|
119
|
+
console.log('š¦ Installing dependencies...\n');
|
|
120
|
+
execSync('npm install --omit=dev', { cwd: APP_DIR, stdio: 'inherit' });
|
|
102
121
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
try {
|
|
110
|
-
execSync('npm run build', {
|
|
111
|
-
cwd: APP_DIR,
|
|
112
|
-
stdio: 'inherit'
|
|
113
|
-
});
|
|
114
|
-
} catch (error) {
|
|
115
|
-
console.error('ā Failed to build');
|
|
116
|
-
process.exit(1);
|
|
122
|
+
|
|
123
|
+
// Build if needed
|
|
124
|
+
const nextPath = path.join(APP_DIR, '.next');
|
|
125
|
+
if (!fs.existsSync(nextPath)) {
|
|
126
|
+
console.log('šØ Building (first time only)...\n');
|
|
127
|
+
execSync('npm run build', { cwd: APP_DIR, stdio: 'inherit' });
|
|
117
128
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
console.error('ā
|
|
129
|
+
|
|
130
|
+
console.log('\nš http://localhost:1234\n');
|
|
131
|
+
|
|
132
|
+
// Start server
|
|
133
|
+
const server = spawn('npx', ['next', 'start', '--port', '1234'], {
|
|
134
|
+
cwd: APP_DIR,
|
|
135
|
+
stdio: 'inherit'
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
server.on('close', (code) => process.exit(code || 0));
|
|
139
|
+
process.on('SIGINT', () => { server.kill('SIGINT'); });
|
|
140
|
+
process.on('SIGTERM', () => { server.kill('SIGTERM'); });
|
|
141
|
+
|
|
142
|
+
} catch (error) {
|
|
143
|
+
console.error('ā Error:', error.message);
|
|
133
144
|
process.exit(1);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
server.on('close', (code) => {
|
|
137
|
-
process.exit(code || 0);
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
// Graceful shutdown
|
|
141
|
-
process.on('SIGINT', () => {
|
|
142
|
-
console.log('\nš Bye!');
|
|
143
|
-
server.kill('SIGINT');
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
process.on('SIGTERM', () => {
|
|
147
|
-
server.kill('SIGTERM');
|
|
148
|
-
});
|
|
145
|
+
}
|
|
149
146
|
}
|
|
150
147
|
|
|
151
|
-
main()
|
|
148
|
+
main();
|