@ztffn/presentation-generator-plugin 1.0.4 → 1.0.6
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/index.js +86 -39
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -5,6 +5,7 @@ const { execSync } = require("child_process");
|
|
|
5
5
|
const fs = require("fs");
|
|
6
6
|
const path = require("path");
|
|
7
7
|
const os = require("os");
|
|
8
|
+
const readline = require("readline");
|
|
8
9
|
|
|
9
10
|
const NPM_PACKAGE = "@ztffn/presentation-generator-plugin";
|
|
10
11
|
const PLUGIN_NAME = "presentation-generator";
|
|
@@ -63,20 +64,19 @@ function downloadFile(url, dest) {
|
|
|
63
64
|
});
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
async function
|
|
67
|
+
async function getLatestNpmMeta() {
|
|
67
68
|
try {
|
|
68
69
|
const data = await fetchJson(
|
|
69
70
|
`https://registry.npmjs.org/${NPM_PACKAGE}/latest`
|
|
70
71
|
);
|
|
71
|
-
|
|
72
|
+
if (!data.version || !data.dist?.tarball) return null;
|
|
73
|
+
return { version: data.version, tarball: data.dist.tarball };
|
|
72
74
|
} catch {
|
|
73
75
|
return null;
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
78
|
|
|
77
|
-
async function downloadAndExtract(version) {
|
|
78
|
-
const pkgSlug = NPM_PACKAGE.replace("@", "").replace("/", "-");
|
|
79
|
-
const tarballUrl = `https://registry.npmjs.org/${NPM_PACKAGE}/-/${pkgSlug}-${version}.tgz`;
|
|
79
|
+
async function downloadAndExtract(version, tarballUrl) {
|
|
80
80
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "claude-plugin-"));
|
|
81
81
|
const tarball = path.join(tmpDir, "plugin.tgz");
|
|
82
82
|
|
|
@@ -101,14 +101,43 @@ async function downloadAndExtract(version) {
|
|
|
101
101
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
function
|
|
104
|
+
function prompt(question) {
|
|
105
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
106
|
+
return new Promise((resolve) => {
|
|
107
|
+
rl.question(question, (answer) => {
|
|
108
|
+
rl.close();
|
|
109
|
+
resolve(answer.trim().toLowerCase());
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function resolveSettingsPath() {
|
|
115
|
+
const projectClaudeDir = path.join(process.cwd(), ".claude");
|
|
116
|
+
const userSettingsPath = path.join(os.homedir(), ".claude", "settings.json");
|
|
117
|
+
|
|
118
|
+
if (!fs.existsSync(projectClaudeDir)) {
|
|
119
|
+
return { settingsPath: userSettingsPath, scope: "user" };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
console.log("\nDetected a .claude/ folder in the current directory.");
|
|
123
|
+
const answer = await prompt(
|
|
124
|
+
"Install for (u) user — available everywhere, or (p) project — this directory only? [u/p]: "
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
if (answer === "p") {
|
|
128
|
+
return {
|
|
129
|
+
settingsPath: path.join(projectClaudeDir, "settings.json"),
|
|
130
|
+
scope: "project",
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return { settingsPath: userSettingsPath, scope: "user" };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async function registerPlugin() {
|
|
105
138
|
console.log("\nRegistering plugin with Claude Code...");
|
|
106
139
|
|
|
107
|
-
|
|
108
|
-
const projectDir = path.join(process.cwd(), ".claude");
|
|
109
|
-
const settingsPath = fs.existsSync(projectDir)
|
|
110
|
-
? path.join(projectDir, "settings.json")
|
|
111
|
-
: path.join(os.homedir(), ".claude", "settings.json");
|
|
140
|
+
const { settingsPath, scope } = await resolveSettingsPath();
|
|
112
141
|
|
|
113
142
|
try {
|
|
114
143
|
let settings = {};
|
|
@@ -127,18 +156,15 @@ function registerPlugin() {
|
|
|
127
156
|
fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
|
|
128
157
|
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
129
158
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
console.log("Commit that file to share the plugin with your team.");
|
|
159
|
+
if (scope === "project") {
|
|
160
|
+
console.log(`Plugin registered in .claude/settings.json ✓`);
|
|
161
|
+
console.log("Commit that file to enable the plugin for your whole team.");
|
|
162
|
+
} else {
|
|
163
|
+
console.log(`Plugin registered in ~/.claude/settings.json ✓`);
|
|
164
|
+
console.log("Available in all your Claude Code sessions.");
|
|
137
165
|
}
|
|
138
166
|
} catch {
|
|
139
|
-
console.log(
|
|
140
|
-
"\nCould not write settings. Add manually to .claude/settings.json:"
|
|
141
|
-
);
|
|
167
|
+
console.log("\nCould not write settings. Add manually to ~/.claude/settings.json:");
|
|
142
168
|
console.log(JSON.stringify({ enabledPlugins: [INSTALL_DIR] }, null, 2));
|
|
143
169
|
console.log(`\nOr load for a single session:`);
|
|
144
170
|
console.log(` claude --plugin-dir "${INSTALL_DIR}"`);
|
|
@@ -148,14 +174,15 @@ function registerPlugin() {
|
|
|
148
174
|
// ── Commands ──────────────────────────────────────────────────────────────────
|
|
149
175
|
|
|
150
176
|
async function install() {
|
|
177
|
+
const meta = await getLatestNpmMeta();
|
|
178
|
+
|
|
151
179
|
if (fs.existsSync(INSTALL_DIR)) {
|
|
152
180
|
const installed = getInstalledVersion();
|
|
153
|
-
const latest = await getLatestNpmVersion();
|
|
154
181
|
|
|
155
|
-
if (
|
|
182
|
+
if (meta && installed && installed !== meta.version) {
|
|
156
183
|
console.log(`\nPlugin already installed (v${installed}).`);
|
|
157
184
|
console.log(
|
|
158
|
-
`v${
|
|
185
|
+
`v${meta.version} is available — run: npx ${NPM_PACKAGE} update\n`
|
|
159
186
|
);
|
|
160
187
|
} else {
|
|
161
188
|
console.log(
|
|
@@ -168,16 +195,15 @@ async function install() {
|
|
|
168
195
|
|
|
169
196
|
console.log(`\nInstalling presentation-generator plugin...`);
|
|
170
197
|
|
|
171
|
-
|
|
172
|
-
if (!version) {
|
|
198
|
+
if (!meta) {
|
|
173
199
|
console.error(
|
|
174
200
|
"\nCould not fetch latest version from npm registry. Check your internet connection.\n"
|
|
175
201
|
);
|
|
176
202
|
process.exit(1);
|
|
177
203
|
}
|
|
178
204
|
|
|
179
|
-
await downloadAndExtract(version);
|
|
180
|
-
console.log(`\nInstalled v${version} to: ${INSTALL_DIR}`);
|
|
205
|
+
await downloadAndExtract(meta.version, meta.tarball);
|
|
206
|
+
console.log(`\nInstalled v${meta.version} to: ${INSTALL_DIR}`);
|
|
181
207
|
registerPlugin();
|
|
182
208
|
}
|
|
183
209
|
|
|
@@ -189,26 +215,26 @@ async function update() {
|
|
|
189
215
|
}
|
|
190
216
|
|
|
191
217
|
const before = getInstalledVersion();
|
|
192
|
-
const
|
|
218
|
+
const meta = await getLatestNpmMeta();
|
|
193
219
|
|
|
194
|
-
if (!
|
|
220
|
+
if (!meta) {
|
|
195
221
|
console.error(
|
|
196
222
|
"\nCould not fetch latest version from npm registry. Check your internet connection.\n"
|
|
197
223
|
);
|
|
198
224
|
process.exit(1);
|
|
199
225
|
}
|
|
200
226
|
|
|
201
|
-
if (before ===
|
|
227
|
+
if (before === meta.version) {
|
|
202
228
|
console.log(`\nAlready up to date (v${before}) ✓`);
|
|
203
229
|
registerPlugin();
|
|
204
230
|
return;
|
|
205
231
|
}
|
|
206
232
|
|
|
207
233
|
console.log(
|
|
208
|
-
`\nUpdating presentation-generator plugin (v${before || "unknown"} → v${
|
|
234
|
+
`\nUpdating presentation-generator plugin (v${before || "unknown"} → v${meta.version})...`
|
|
209
235
|
);
|
|
210
|
-
await downloadAndExtract(
|
|
211
|
-
console.log(`\nUpdated to v${
|
|
236
|
+
await downloadAndExtract(meta.version, meta.tarball);
|
|
237
|
+
console.log(`\nUpdated to v${meta.version} ✓`);
|
|
212
238
|
registerPlugin();
|
|
213
239
|
}
|
|
214
240
|
|
|
@@ -219,30 +245,51 @@ async function checkUpdate() {
|
|
|
219
245
|
}
|
|
220
246
|
|
|
221
247
|
const installed = getInstalledVersion();
|
|
222
|
-
const
|
|
248
|
+
const meta = await getLatestNpmMeta();
|
|
223
249
|
|
|
224
|
-
if (!
|
|
250
|
+
if (!meta) {
|
|
225
251
|
console.log(
|
|
226
252
|
`\nInstalled: v${installed || "unknown"} (could not reach npm registry)\n`
|
|
227
253
|
);
|
|
228
254
|
return;
|
|
229
255
|
}
|
|
230
256
|
|
|
231
|
-
if (installed ===
|
|
257
|
+
if (installed === meta.version) {
|
|
232
258
|
console.log(`\nUp to date: v${installed} ✓\n`);
|
|
233
259
|
} else {
|
|
234
|
-
console.log(`\nUpdate available: v${installed} → v${
|
|
260
|
+
console.log(`\nUpdate available: v${installed} → v${meta.version}`);
|
|
235
261
|
console.log(`Run: npx ${NPM_PACKAGE} update\n`);
|
|
236
262
|
}
|
|
237
263
|
}
|
|
238
264
|
|
|
265
|
+
function removeFromSettings(settingsPath) {
|
|
266
|
+
if (!fs.existsSync(settingsPath)) return;
|
|
267
|
+
try {
|
|
268
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, "utf8"));
|
|
269
|
+
if (!Array.isArray(settings.enabledPlugins)) return;
|
|
270
|
+
const before = settings.enabledPlugins.length;
|
|
271
|
+
settings.enabledPlugins = settings.enabledPlugins.filter((p) => p !== INSTALL_DIR);
|
|
272
|
+
if (settings.enabledPlugins.length !== before) {
|
|
273
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
274
|
+
console.log(`Removed from ${settingsPath}`);
|
|
275
|
+
}
|
|
276
|
+
} catch {
|
|
277
|
+
// ignore
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
239
281
|
function uninstall() {
|
|
240
282
|
if (!fs.existsSync(INSTALL_DIR)) {
|
|
241
283
|
console.log("\nPlugin not installed.\n");
|
|
242
284
|
return;
|
|
243
285
|
}
|
|
244
286
|
fs.rmSync(INSTALL_DIR, { recursive: true, force: true });
|
|
245
|
-
console.log(`\nRemoved: ${INSTALL_DIR}
|
|
287
|
+
console.log(`\nRemoved: ${INSTALL_DIR}`);
|
|
288
|
+
|
|
289
|
+
// Clean up both possible settings locations
|
|
290
|
+
removeFromSettings(path.join(os.homedir(), ".claude", "settings.json"));
|
|
291
|
+
removeFromSettings(path.join(process.cwd(), ".claude", "settings.json"));
|
|
292
|
+
console.log();
|
|
246
293
|
}
|
|
247
294
|
|
|
248
295
|
function help() {
|