ramadan-cal 1.0.2 → 1.0.3
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/package.json +1 -1
- package/scripts/postinstall.js +99 -97
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
* Postinstall script — runs automatically after npm install.
|
|
5
|
-
* Interactively sets up Claude Code integration if the user wants it.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync } from 'fs';
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync, createReadStream, createWriteStream, openSync, closeSync } from 'fs';
|
|
9
4
|
import { join } from 'path';
|
|
10
5
|
import { homedir } from 'os';
|
|
11
6
|
import { execSync } from 'child_process';
|
|
@@ -42,6 +37,10 @@ ramadan $ARGUMENTS
|
|
|
42
37
|
\`\`\`
|
|
43
38
|
`;
|
|
44
39
|
|
|
40
|
+
function log(msg) {
|
|
41
|
+
process.stderr.write(msg + '\n');
|
|
42
|
+
}
|
|
43
|
+
|
|
45
44
|
function isClaudeInstalled() {
|
|
46
45
|
try {
|
|
47
46
|
execSync('which claude', { stdio: 'ignore' });
|
|
@@ -53,132 +52,135 @@ function isClaudeInstalled() {
|
|
|
53
52
|
|
|
54
53
|
function isClaudeMdConfigured() {
|
|
55
54
|
if (!existsSync(claudeMd)) return false;
|
|
56
|
-
|
|
57
|
-
return content.includes(MARKER);
|
|
55
|
+
return readFileSync(claudeMd, 'utf-8').includes(MARKER);
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
function isSkillInstalled() {
|
|
61
59
|
if (!existsSync(ramadanSkillFile)) return false;
|
|
62
|
-
|
|
63
|
-
return content.includes(SKILL_MARKER);
|
|
60
|
+
return readFileSync(ramadanSkillFile, 'utf-8').includes(SKILL_MARKER);
|
|
64
61
|
}
|
|
65
62
|
|
|
66
|
-
function
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
|
|
63
|
+
function configureClaudeMd() {
|
|
64
|
+
if (isClaudeMdConfigured()) return;
|
|
65
|
+
if (!existsSync(claudeDir)) mkdirSync(claudeDir, { recursive: true });
|
|
66
|
+
if (existsSync(claudeMd)) {
|
|
67
|
+
appendFileSync(claudeMd, CLAUDE_ENTRY);
|
|
68
|
+
} else {
|
|
69
|
+
writeFileSync(claudeMd, CLAUDE_ENTRY.trimStart());
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function createSkill() {
|
|
74
|
+
if (!existsSync(skillsDir)) mkdirSync(skillsDir, { recursive: true });
|
|
75
|
+
if (!existsSync(ramadanSkillDir)) mkdirSync(ramadanSkillDir, { recursive: true });
|
|
76
|
+
writeFileSync(ramadanSkillFile, RAMADAN_SKILL);
|
|
77
|
+
configureClaudeMd();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function canPrompt() {
|
|
81
|
+
try {
|
|
82
|
+
const fd = openSync('/dev/tty', 'r+');
|
|
83
|
+
closeSync(fd);
|
|
84
|
+
return true;
|
|
85
|
+
} catch {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
70
88
|
}
|
|
71
89
|
|
|
72
90
|
function ask(question) {
|
|
73
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
74
91
|
return new Promise((resolve) => {
|
|
92
|
+
// Use /dev/tty so prompts work even when stdin is piped (npm install)
|
|
93
|
+
let ttyInput, ttyOutput;
|
|
94
|
+
try {
|
|
95
|
+
ttyInput = createReadStream('/dev/tty');
|
|
96
|
+
ttyOutput = createWriteStream('/dev/tty', { flags: 'a' });
|
|
97
|
+
} catch {
|
|
98
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
99
|
+
rl.question(question, (answer) => { rl.close(); resolve(answer.trim().toLowerCase()); });
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const rl = createInterface({ input: ttyInput, output: ttyOutput });
|
|
75
103
|
rl.question(question, (answer) => {
|
|
76
104
|
rl.close();
|
|
105
|
+
ttyInput.destroy();
|
|
106
|
+
ttyOutput.destroy();
|
|
77
107
|
resolve(answer.trim().toLowerCase());
|
|
78
108
|
});
|
|
79
109
|
});
|
|
80
110
|
}
|
|
81
111
|
|
|
82
112
|
async function main() {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
113
|
+
log('');
|
|
114
|
+
log(' 🌙 Ramadan CLI installed successfully!');
|
|
115
|
+
log('');
|
|
116
|
+
|
|
117
|
+
// Step 1: Check if Claude Code is installed
|
|
118
|
+
if (!isClaudeInstalled()) {
|
|
119
|
+
log(' Claude Code not detected on your PATH.');
|
|
120
|
+
log(' Run `npm rebuild ramadan-cal` to set up Claude Code integration later.');
|
|
121
|
+
log('');
|
|
122
|
+
log(' ➜ Run `ramadan` to get started.');
|
|
123
|
+
log('');
|
|
94
124
|
return;
|
|
95
125
|
}
|
|
96
126
|
|
|
97
|
-
|
|
98
|
-
|
|
127
|
+
log(' ✓ Claude Code detected');
|
|
128
|
+
log('');
|
|
99
129
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// They use Claude Code but it's not on PATH
|
|
109
|
-
console.log(' ℹ Claude Code wasn\'t detected on your PATH.');
|
|
110
|
-
|
|
111
|
-
const proceed = await ask(' Set up the integration anyway? (y/n) ');
|
|
112
|
-
|
|
113
|
-
if (proceed !== 'y' && proceed !== 'yes') {
|
|
114
|
-
console.log(' ✓ No worries — run `npm rebuild ramadan-cal` anytime to set it up later.\n');
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
} else {
|
|
118
|
-
console.log(' ✓ Claude Code detected');
|
|
119
|
-
|
|
120
|
-
const answer = await ask(' Set up Claude Code integration? Type `ramadan` or `/ramadan` in Claude Code. (y/n) ');
|
|
121
|
-
|
|
122
|
-
if (answer !== 'y' && answer !== 'yes') {
|
|
123
|
-
console.log(' ✓ Skipped. Run `npm rebuild ramadan-cal` anytime to set it up later.\n');
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
130
|
+
// Already fully set up?
|
|
131
|
+
if (isSkillInstalled() && isClaudeMdConfigured()) {
|
|
132
|
+
log(' ✓ Claude Code integration already configured');
|
|
133
|
+
log(' Type "ramadan" or "/ramadan" in Claude Code.');
|
|
134
|
+
log('');
|
|
135
|
+
return;
|
|
126
136
|
}
|
|
127
137
|
|
|
128
|
-
//
|
|
129
|
-
if (!
|
|
130
|
-
|
|
131
|
-
|
|
138
|
+
// If we can't open a terminal for prompts, bail out gracefully
|
|
139
|
+
if (!canPrompt()) {
|
|
140
|
+
log(' Run `npm rebuild ramadan-cal` in your terminal to finish Claude Code setup.');
|
|
141
|
+
log('');
|
|
142
|
+
return;
|
|
132
143
|
}
|
|
133
144
|
|
|
134
|
-
//
|
|
135
|
-
if (!
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
145
|
+
// Step 2: Check if skills folder exists
|
|
146
|
+
if (!existsSync(skillsDir)) {
|
|
147
|
+
// Skills folder doesn't exist — ask to create it
|
|
148
|
+
const answer = await ask(' Create a Claude Code skills folder and add the ramadan skill? (y/n) ');
|
|
149
|
+
log('');
|
|
150
|
+
if (answer === 'y' || answer === 'yes') {
|
|
151
|
+
createSkill();
|
|
152
|
+
log(' ✓ Created ~/.claude/skills/ramadan/');
|
|
153
|
+
log(' ✓ Ramadan skill added');
|
|
154
|
+
log('');
|
|
155
|
+
log(' Type "ramadan" or "/ramadan" in Claude Code to use it.');
|
|
139
156
|
} else {
|
|
140
|
-
|
|
141
|
-
|
|
157
|
+
log(' Skipped. Run `npm rebuild ramadan-cal` or type `ramadan` directly in your terminal.');
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
// Skills folder exists — ask if they want the skill added
|
|
161
|
+
if (isSkillInstalled()) {
|
|
162
|
+
log(' ✓ Ramadan skill already installed');
|
|
163
|
+
configureClaudeMd();
|
|
164
|
+
log(' Type "ramadan" or "/ramadan" in Claude Code.');
|
|
165
|
+
log('');
|
|
166
|
+
return;
|
|
142
167
|
}
|
|
143
|
-
}
|
|
144
168
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if (
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
} else {
|
|
153
|
-
writeFileSync(ramadanSkillFile, RAMADAN_SKILL);
|
|
154
|
-
console.log(' ✓ Created ramadan skill — type `/ramadan` in Claude Code');
|
|
155
|
-
}
|
|
169
|
+
const answer = await ask(' Add the ramadan skill to Claude Code? (y/n) ');
|
|
170
|
+
log('');
|
|
171
|
+
if (answer === 'y' || answer === 'yes') {
|
|
172
|
+
createSkill();
|
|
173
|
+
log(' ✓ Ramadan skill added to ~/.claude/skills/');
|
|
174
|
+
log('');
|
|
175
|
+
log(' Type "ramadan" or "/ramadan" in Claude Code to use it.');
|
|
156
176
|
} else {
|
|
157
|
-
|
|
158
|
-
mkdirSync(skillsDir, { recursive: true });
|
|
159
|
-
console.log(' ✓ Created ~/.claude/skills/');
|
|
160
|
-
}
|
|
161
|
-
if (!existsSync(ramadanSkillDir)) {
|
|
162
|
-
mkdirSync(ramadanSkillDir, { recursive: true });
|
|
163
|
-
}
|
|
164
|
-
writeFileSync(ramadanSkillFile, RAMADAN_SKILL);
|
|
165
|
-
console.log(' ✓ Created ramadan skill — type `/ramadan` in Claude Code');
|
|
177
|
+
log(' Skipped. Run `npm rebuild ramadan-cal` or type `ramadan` directly in your terminal.');
|
|
166
178
|
}
|
|
167
179
|
}
|
|
168
180
|
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Handle non-interactive environments (CI, piped input)
|
|
173
|
-
if (!process.stdin.isTTY) {
|
|
174
|
-
console.log('');
|
|
175
|
-
console.log(' 🌙 Ramadan CLI installed successfully!');
|
|
176
|
-
console.log(' Run `ramadan` to get started.');
|
|
177
|
-
console.log(' Run `npm rebuild ramadan-cal` in an interactive terminal to set up Claude Code.\n');
|
|
178
|
-
process.exit(0);
|
|
181
|
+
log('');
|
|
179
182
|
}
|
|
180
183
|
|
|
181
184
|
main().catch(() => {
|
|
182
|
-
// Non-fatal — never block the install
|
|
183
185
|
process.exit(0);
|
|
184
186
|
});
|