@edtools/cli 0.2.0 → 0.3.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/bin/edtools.js CHANGED
File without changes
@@ -0,0 +1,519 @@
1
+ // src/types/adapter.ts
2
+ var AdapterRegistry = class {
3
+ adapters;
4
+ constructor() {
5
+ this.adapters = /* @__PURE__ */ new Map();
6
+ }
7
+ register(adapter) {
8
+ this.adapters.set(adapter.name, adapter);
9
+ }
10
+ get(name) {
11
+ return this.adapters.get(name);
12
+ }
13
+ async detectAdapter(projectPath) {
14
+ for (const adapter of this.adapters.values()) {
15
+ if (await adapter.detect(projectPath)) {
16
+ return adapter;
17
+ }
18
+ }
19
+ return null;
20
+ }
21
+ list() {
22
+ return Array.from(this.adapters.keys());
23
+ }
24
+ };
25
+
26
+ // src/adapters/html/index.ts
27
+ import fs from "fs-extra";
28
+ import path from "path";
29
+ import ejs from "ejs";
30
+ import { marked } from "marked";
31
+ var HTMLAdapter = class {
32
+ name = "html";
33
+ templatePath;
34
+ constructor() {
35
+ this.templatePath = path.join(__dirname, "templates", "blog-post.html.ejs");
36
+ }
37
+ async detect(projectPath) {
38
+ try {
39
+ const files = await fs.readdir(projectPath);
40
+ const hasHtml = files.some((f) => f.endsWith(".html"));
41
+ const hasIndexHtml = await fs.pathExists(path.join(projectPath, "index.html"));
42
+ return hasHtml || hasIndexHtml;
43
+ } catch (error) {
44
+ return false;
45
+ }
46
+ }
47
+ async render(content) {
48
+ const template = await fs.readFile(this.templatePath, "utf-8");
49
+ const templateData = {
50
+ metadata: content.metadata,
51
+ schemaOrg: JSON.stringify(content.schemaOrg, null, 2),
52
+ intro: await this.markdownToHTML(content.content.intro),
53
+ sections: await Promise.all(
54
+ content.content.sections.map(async (section) => ({
55
+ ...section,
56
+ content: await this.renderSectionContent(section)
57
+ }))
58
+ ),
59
+ conclusion: await this.markdownToHTML(content.content.conclusion),
60
+ cta: content.content.cta,
61
+ relatedPosts: content.relatedPosts || [],
62
+ seoScore: content.seo.score
63
+ };
64
+ const html = ejs.render(template, templateData);
65
+ return html;
66
+ }
67
+ async write(output, outputPath) {
68
+ await fs.ensureDir(path.dirname(outputPath));
69
+ await fs.writeFile(outputPath, output, "utf-8");
70
+ }
71
+ getFileExtension() {
72
+ return ".html";
73
+ }
74
+ transformPath(basePath) {
75
+ if (!basePath.endsWith(".html")) {
76
+ return basePath + "/index.html";
77
+ }
78
+ return basePath;
79
+ }
80
+ /**
81
+ * Convert markdown to HTML
82
+ */
83
+ async markdownToHTML(markdown) {
84
+ return marked(markdown);
85
+ }
86
+ /**
87
+ * Render section content based on type
88
+ */
89
+ async renderSectionContent(section) {
90
+ switch (section.type) {
91
+ case "text":
92
+ return await this.markdownToHTML(section.content);
93
+ case "comparison":
94
+ return this.renderComparisonTable(section.data);
95
+ case "list":
96
+ return this.renderList(section.data);
97
+ case "code":
98
+ return this.renderCode(section.data);
99
+ default:
100
+ return await this.markdownToHTML(section.content);
101
+ }
102
+ }
103
+ /**
104
+ * Render comparison table
105
+ */
106
+ renderComparisonTable(data) {
107
+ if (!data || !data.headers || !data.rows) {
108
+ return "";
109
+ }
110
+ let html = '<table class="comparison-table">\n';
111
+ html += " <thead>\n <tr>\n";
112
+ data.headers.forEach((header) => {
113
+ html += ` <th>${header}</th>
114
+ `;
115
+ });
116
+ html += " </tr>\n </thead>\n";
117
+ html += " <tbody>\n";
118
+ data.rows.forEach((row) => {
119
+ html += " <tr>\n";
120
+ row.forEach((cell) => {
121
+ html += ` <td>${cell}</td>
122
+ `;
123
+ });
124
+ html += " </tr>\n";
125
+ });
126
+ html += " </tbody>\n";
127
+ html += "</table>";
128
+ return html;
129
+ }
130
+ /**
131
+ * Render list
132
+ */
133
+ renderList(data) {
134
+ if (!data || !data.items) {
135
+ return "";
136
+ }
137
+ const tag = data.ordered ? "ol" : "ul";
138
+ let html = `<${tag} class="content-list">
139
+ `;
140
+ data.items.forEach((item) => {
141
+ html += " <li>\n";
142
+ html += ` <strong>${item.title}</strong>
143
+ `;
144
+ if (item.description) {
145
+ html += ` <p>${item.description}</p>
146
+ `;
147
+ }
148
+ html += " </li>\n";
149
+ });
150
+ html += `</${tag}>`;
151
+ return html;
152
+ }
153
+ /**
154
+ * Render code block
155
+ */
156
+ renderCode(data) {
157
+ if (!data || !data.code) {
158
+ return "";
159
+ }
160
+ let html = '<div class="code-block">\n';
161
+ if (data.caption) {
162
+ html += ` <div class="code-caption">${data.caption}</div>
163
+ `;
164
+ }
165
+ html += ` <pre><code class="language-${data.language || "plaintext"}">${this.escapeHtml(data.code)}</code></pre>
166
+ `;
167
+ html += "</div>";
168
+ return html;
169
+ }
170
+ /**
171
+ * Escape HTML entities
172
+ */
173
+ escapeHtml(text) {
174
+ const map = {
175
+ "&": "&amp;",
176
+ "<": "&lt;",
177
+ ">": "&gt;",
178
+ '"': "&quot;",
179
+ "'": "&#039;"
180
+ };
181
+ return text.replace(/[&<>"']/g, (m) => map[m]);
182
+ }
183
+ };
184
+
185
+ // src/core/generator.ts
186
+ import Anthropic from "@anthropic-ai/sdk";
187
+ import OpenAI from "openai";
188
+ import path2 from "path";
189
+ import fs2 from "fs-extra";
190
+ import slugify from "slugify";
191
+ var ContentGenerator = class {
192
+ anthropic = null;
193
+ openai = null;
194
+ provider;
195
+ adapters;
196
+ constructor(apiKey, provider = "anthropic") {
197
+ this.provider = provider;
198
+ if (provider === "anthropic") {
199
+ this.anthropic = new Anthropic({
200
+ apiKey: apiKey || process.env.ANTHROPIC_API_KEY || ""
201
+ });
202
+ } else if (provider === "openai") {
203
+ this.openai = new OpenAI({
204
+ apiKey: apiKey || process.env.OPENAI_API_KEY || ""
205
+ });
206
+ }
207
+ this.adapters = new AdapterRegistry();
208
+ this.adapters.register(new HTMLAdapter());
209
+ }
210
+ /**
211
+ * Main generate method
212
+ */
213
+ async generate(config) {
214
+ const results = {
215
+ success: true,
216
+ posts: [],
217
+ warnings: [],
218
+ errors: []
219
+ };
220
+ try {
221
+ const adapter = await this.adapters.detectAdapter(config.projectPath);
222
+ if (!adapter) {
223
+ throw new Error("No suitable adapter found for this project");
224
+ }
225
+ console.log(`\u2713 Using adapter: ${adapter.name}`);
226
+ const topics = config.topics || await this.generateTopics(config.productInfo, config.count || 3);
227
+ for (const topic of topics.slice(0, config.count || 3)) {
228
+ try {
229
+ console.log(`
230
+ \u{1F4DD} Generating: ${topic}`);
231
+ const content = await this.generateContent(config.productInfo, topic);
232
+ const output = await adapter.render(content);
233
+ const slug = content.metadata.slug;
234
+ const fileName = adapter.transformPath?.(slug) || `${slug}/index${adapter.getFileExtension()}`;
235
+ const outputPath = path2.join(config.outputDir, fileName);
236
+ await adapter.write(output, outputPath);
237
+ results.posts.push({
238
+ title: content.metadata.title,
239
+ slug,
240
+ path: outputPath,
241
+ seoScore: content.seo.score
242
+ });
243
+ console.log(`\u2713 Generated: ${outputPath}`);
244
+ console.log(` SEO Score: ${content.seo.score}/100`);
245
+ } catch (error) {
246
+ results.errors?.push(`Failed to generate "${topic}": ${error.message}`);
247
+ results.success = false;
248
+ }
249
+ }
250
+ if (results.posts.length > 0) {
251
+ await this.updateSitemap(config.projectPath, config.outputDir, results.posts);
252
+ }
253
+ } catch (error) {
254
+ results.success = false;
255
+ results.errors?.push(error.message);
256
+ }
257
+ return results;
258
+ }
259
+ /**
260
+ * Generate blog post content using the selected AI provider
261
+ */
262
+ async generateContent(productInfo, topic) {
263
+ const prompt = this.buildPrompt(productInfo, topic);
264
+ let contentData;
265
+ if (this.provider === "anthropic") {
266
+ contentData = await this.generateWithAnthropic(prompt);
267
+ } else if (this.provider === "openai") {
268
+ contentData = await this.generateWithOpenAI(prompt);
269
+ } else {
270
+ throw new Error(`Unsupported provider: ${this.provider}`);
271
+ }
272
+ const slug = slugify(contentData.metadata.title, { lower: true, strict: true });
273
+ const content = {
274
+ metadata: {
275
+ ...contentData.metadata,
276
+ slug,
277
+ datePublished: (/* @__PURE__ */ new Date()).toISOString(),
278
+ author: productInfo.name
279
+ },
280
+ schemaOrg: this.generateSchemaOrg({
281
+ ...contentData.metadata,
282
+ slug,
283
+ datePublished: (/* @__PURE__ */ new Date()).toISOString(),
284
+ author: productInfo.name
285
+ }, productInfo),
286
+ content: contentData.content,
287
+ relatedPosts: [],
288
+ seo: await this.calculateSEOScore(contentData)
289
+ };
290
+ return content;
291
+ }
292
+ /**
293
+ * Generate content using Anthropic's Claude API
294
+ */
295
+ async generateWithAnthropic(prompt) {
296
+ if (!this.anthropic) {
297
+ throw new Error("Anthropic client not initialized");
298
+ }
299
+ const response = await this.anthropic.messages.create({
300
+ model: "claude-3-5-sonnet-20241022",
301
+ max_tokens: 4096,
302
+ temperature: 0.7,
303
+ messages: [
304
+ {
305
+ role: "user",
306
+ content: prompt
307
+ }
308
+ ]
309
+ });
310
+ const textContent = response.content[0].type === "text" ? response.content[0].text : "";
311
+ const jsonMatch = textContent.match(/\{[\s\S]*\}/);
312
+ if (!jsonMatch) {
313
+ throw new Error("Failed to extract JSON from Claude response");
314
+ }
315
+ return JSON.parse(jsonMatch[0]);
316
+ }
317
+ /**
318
+ * Generate content using OpenAI's ChatGPT API
319
+ */
320
+ async generateWithOpenAI(prompt) {
321
+ if (!this.openai) {
322
+ throw new Error("OpenAI client not initialized");
323
+ }
324
+ const response = await this.openai.chat.completions.create({
325
+ model: "gpt-4-turbo-preview",
326
+ max_tokens: 4096,
327
+ temperature: 0.7,
328
+ messages: [
329
+ {
330
+ role: "user",
331
+ content: prompt
332
+ }
333
+ ],
334
+ response_format: { type: "json_object" }
335
+ });
336
+ const textContent = response.choices[0]?.message?.content || "";
337
+ if (!textContent) {
338
+ throw new Error("Failed to get response from OpenAI");
339
+ }
340
+ return JSON.parse(textContent);
341
+ }
342
+ /**
343
+ * Build prompt for Claude API
344
+ */
345
+ buildPrompt(productInfo, topic) {
346
+ return `You are an expert SEO content writer. Generate a comprehensive blog post about: "${topic}"
347
+
348
+ Product context:
349
+ - Name: ${productInfo.name}
350
+ - Tagline: ${productInfo.tagline || ""}
351
+ - Category: ${productInfo.category}
352
+ - Features: ${productInfo.features.join(", ")}
353
+ - Pricing: ${productInfo.pricingModel || "Not specified"}
354
+ ${productInfo.useCases ? `- Use cases: ${productInfo.useCases.join(", ")}` : ""}
355
+
356
+ IMPORTANT INSTRUCTIONS:
357
+ 1. Write for users searching on Google and being recommended by AI assistants (Claude, ChatGPT)
358
+ 2. Focus on being helpful, not promotional
359
+ 3. Include comparisons with alternatives when relevant
360
+ 4. Use natural language, avoid keyword stuffing
361
+ 5. Make it comprehensive (1000-1500 words worth of content)
362
+ 6. Structure with clear sections (intro, 3-5 main sections, conclusion)
363
+ 7. Be factual - do NOT invent statistics or make false claims
364
+
365
+ Output ONLY valid JSON in this exact format (no markdown, no code blocks):
366
+ {
367
+ "metadata": {
368
+ "title": "SEO-optimized title (under 60 chars)",
369
+ "description": "Meta description (under 160 chars)",
370
+ "keywords": ["keyword1", "keyword2", "keyword3"],
371
+ "category": "${productInfo.category}"
372
+ },
373
+ "content": {
374
+ "intro": "Engaging introduction paragraph in markdown format",
375
+ "sections": [
376
+ {
377
+ "heading": "Section title",
378
+ "level": 2,
379
+ "content": "Section content in markdown format",
380
+ "type": "text"
381
+ }
382
+ ],
383
+ "conclusion": "Conclusion paragraph in markdown",
384
+ "cta": {
385
+ "text": "Try ${productInfo.name}",
386
+ "url": "${productInfo.websiteUrl || "/signup"}"
387
+ }
388
+ }
389
+ }`;
390
+ }
391
+ /**
392
+ * Generate Schema.org structured data
393
+ */
394
+ generateSchemaOrg(metadata, productInfo) {
395
+ return {
396
+ "@context": "https://schema.org",
397
+ "@type": "BlogPosting",
398
+ headline: metadata.title,
399
+ description: metadata.description,
400
+ author: {
401
+ "@type": "Organization",
402
+ name: productInfo.name,
403
+ url: productInfo.websiteUrl
404
+ },
405
+ datePublished: metadata.datePublished,
406
+ publisher: {
407
+ "@type": "Organization",
408
+ name: productInfo.name
409
+ },
410
+ keywords: metadata.keywords.join(", "),
411
+ articleSection: metadata.category
412
+ };
413
+ }
414
+ /**
415
+ * Calculate SEO score
416
+ */
417
+ async calculateSEOScore(content) {
418
+ let score = 100;
419
+ const suggestions = [];
420
+ if (content.metadata.title.length > 60) {
421
+ score -= 10;
422
+ suggestions.push("Title is too long (should be under 60 chars)");
423
+ }
424
+ if (content.metadata.description.length > 160) {
425
+ score -= 10;
426
+ suggestions.push("Meta description is too long (should be under 160 chars)");
427
+ }
428
+ if (content.metadata.keywords.length < 3) {
429
+ score -= 5;
430
+ suggestions.push("Add more keywords (at least 3)");
431
+ }
432
+ if (content.content.sections.length < 3) {
433
+ score -= 10;
434
+ suggestions.push("Add more sections for better structure (at least 3)");
435
+ }
436
+ return {
437
+ score: Math.max(0, score),
438
+ suggestions
439
+ };
440
+ }
441
+ /**
442
+ * Generate topic suggestions
443
+ */
444
+ async generateTopics(productInfo, count) {
445
+ const prompt = `Generate ${count} SEO-friendly blog post topics for a product called "${productInfo.name}" in the ${productInfo.category} category.
446
+
447
+ Product description: ${productInfo.description}
448
+ Features: ${productInfo.features.join(", ")}
449
+
450
+ Requirements:
451
+ - Topics should be helpful for potential customers
452
+ - Focus on solving problems or answering questions
453
+ - Include comparisons, guides, and use cases
454
+ - Optimize for search engines and AI recommendations
455
+
456
+ Output ONLY a JSON array of topic strings, no markdown:
457
+ ["Topic 1", "Topic 2", "Topic 3"]`;
458
+ try {
459
+ if (this.provider === "anthropic" && this.anthropic) {
460
+ const response = await this.anthropic.messages.create({
461
+ model: "claude-3-5-sonnet-20241022",
462
+ max_tokens: 1024,
463
+ messages: [{ role: "user", content: prompt }]
464
+ });
465
+ const textContent = response.content[0].type === "text" ? response.content[0].text : "";
466
+ const jsonMatch = textContent.match(/\[[\s\S]*\]/);
467
+ if (jsonMatch) {
468
+ return JSON.parse(jsonMatch[0]);
469
+ }
470
+ } else if (this.provider === "openai" && this.openai) {
471
+ const response = await this.openai.chat.completions.create({
472
+ model: "gpt-4-turbo-preview",
473
+ max_tokens: 1024,
474
+ messages: [{ role: "user", content: prompt }],
475
+ response_format: { type: "json_object" }
476
+ });
477
+ const textContent = response.choices[0]?.message?.content || "";
478
+ if (textContent) {
479
+ const data = JSON.parse(textContent);
480
+ return data.topics || data;
481
+ }
482
+ }
483
+ } catch (error) {
484
+ console.warn("Failed to generate topics with AI, using fallback");
485
+ }
486
+ return [
487
+ `Best ${productInfo.category} software ${(/* @__PURE__ */ new Date()).getFullYear()}`,
488
+ `How to choose ${productInfo.category} solution`,
489
+ `${productInfo.name} vs alternatives: Complete comparison`
490
+ ];
491
+ }
492
+ /**
493
+ * Update sitemap.xml
494
+ */
495
+ async updateSitemap(projectPath, blogDir, posts) {
496
+ const sitemapPath = path2.join(projectPath, "sitemap.xml");
497
+ const urls = posts.map((post) => {
498
+ return ` <url>
499
+ <loc>${post.slug}/</loc>
500
+ <lastmod>${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}</lastmod>
501
+ <changefreq>weekly</changefreq>
502
+ <priority>0.8</priority>
503
+ </url>`;
504
+ }).join("\n");
505
+ const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
506
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
507
+ ${urls}
508
+ </urlset>`;
509
+ await fs2.writeFile(sitemapPath, sitemap, "utf-8");
510
+ console.log(`
511
+ \u2713 Updated sitemap.xml`);
512
+ }
513
+ };
514
+
515
+ export {
516
+ AdapterRegistry,
517
+ HTMLAdapter,
518
+ ContentGenerator
519
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"AAWA,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,eAAe,iBAmI7D"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"AAYA,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,eAAe,iBAkJ7D"}
@@ -1,5 +1,6 @@
1
1
  import fs from 'fs-extra';
2
2
  import path from 'path';
3
+ import { pathToFileURL } from 'url';
3
4
  import chalk from 'chalk';
4
5
  import ora from 'ora';
5
6
  import { ContentGenerator } from '../../core/generator.js';
@@ -12,28 +13,41 @@ export async function generateCommand(options) {
12
13
  console.log(chalk.yellow(' Run "edtools init" first\n'));
13
14
  process.exit(1);
14
15
  }
15
- const config = require(configPath);
16
- const productInfo = config.product;
16
+ const configUrl = pathToFileURL(configPath).href;
17
+ const config = await import(configUrl);
18
+ const productInfo = config.default.product;
17
19
  if (!productInfo || !productInfo.name) {
18
20
  console.log(chalk.red('✗ Invalid configuration in edtools.config.js'));
19
21
  process.exit(1);
20
22
  }
21
23
  const provider = productInfo.preferredProvider || 'anthropic';
24
+ let storedApiKey;
25
+ const edtoolsConfigPath = path.join(projectPath, '.edtools', 'config.json');
26
+ if (await fs.pathExists(edtoolsConfigPath)) {
27
+ try {
28
+ const edtoolsConfig = await fs.readJson(edtoolsConfigPath);
29
+ storedApiKey = edtoolsConfig.apiKey;
30
+ }
31
+ catch (error) {
32
+ }
33
+ }
22
34
  let apiKey;
23
35
  if (provider === 'anthropic') {
24
- apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY;
36
+ apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY || storedApiKey;
25
37
  if (!apiKey) {
26
38
  console.log(chalk.red('✗ No Anthropic API key found'));
27
- console.log(chalk.yellow(' Set ANTHROPIC_API_KEY environment variable'));
39
+ console.log(chalk.yellow(' Run "edtools init" to configure your API key'));
40
+ console.log(chalk.yellow(' Or set ANTHROPIC_API_KEY environment variable'));
28
41
  console.log(chalk.yellow(' Or use --api-key option\n'));
29
42
  process.exit(1);
30
43
  }
31
44
  }
32
45
  else if (provider === 'openai') {
33
- apiKey = options.apiKey || process.env.OPENAI_API_KEY;
46
+ apiKey = options.apiKey || process.env.OPENAI_API_KEY || storedApiKey;
34
47
  if (!apiKey) {
35
48
  console.log(chalk.red('✗ No OpenAI API key found'));
36
- console.log(chalk.yellow(' Set OPENAI_API_KEY environment variable'));
49
+ console.log(chalk.yellow(' Run "edtools init" to configure your API key'));
50
+ console.log(chalk.yellow(' Or set OPENAI_API_KEY environment variable'));
37
51
  console.log(chalk.yellow(' Or use --api-key option\n'));
38
52
  process.exit(1);
39
53
  }
@@ -1 +1 @@
1
- {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAYA,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,iBA+LrD"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAYA,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,iBA6NrD"}
@@ -126,6 +126,28 @@ export async function initCommand(options) {
126
126
  default: 'anthropic',
127
127
  },
128
128
  ]);
129
+ console.log(chalk.cyan('\n🔑 API Key Setup:\n'));
130
+ const apiKeyAnswer = await inquirer.prompt([
131
+ {
132
+ type: 'password',
133
+ name: 'apiKey',
134
+ message: answers.preferredProvider === 'anthropic'
135
+ ? 'Anthropic API Key (from https://console.anthropic.com):'
136
+ : 'OpenAI API Key (from https://platform.openai.com/api-keys):',
137
+ validate: (input) => {
138
+ if (!input || input.trim().length === 0) {
139
+ return 'API key is required';
140
+ }
141
+ if (answers.preferredProvider === 'anthropic' && !input.startsWith('sk-ant-')) {
142
+ return 'Anthropic API keys should start with "sk-ant-"';
143
+ }
144
+ if (answers.preferredProvider === 'openai' && !input.startsWith('sk-')) {
145
+ return 'OpenAI API keys should start with "sk-"';
146
+ }
147
+ return true;
148
+ },
149
+ },
150
+ ]);
129
151
  const finalProductInfo = {
130
152
  ...productInfo,
131
153
  ...answers,
@@ -157,18 +179,22 @@ export async function initCommand(options) {
157
179
  await fs.writeFile(configPath, config, 'utf-8');
158
180
  const edtoolsDir = path.join(projectPath, '.edtools');
159
181
  await fs.ensureDir(edtoolsDir);
182
+ const edtoolsConfig = {
183
+ apiKey: apiKeyAnswer.apiKey,
184
+ provider: finalProductInfo.preferredProvider,
185
+ };
186
+ const edtoolsConfigPath = path.join(edtoolsDir, 'config.json');
187
+ await fs.writeFile(edtoolsConfigPath, JSON.stringify(edtoolsConfig, null, 2), 'utf-8');
160
188
  const gitignorePath = path.join(edtoolsDir, '.gitignore');
161
189
  await fs.writeFile(gitignorePath, '*\n!.gitignore\n', 'utf-8');
162
190
  console.log(chalk.green('\n✓ Configuration created successfully!\n'));
163
191
  console.log(chalk.cyan('Files created:'));
164
192
  console.log(` - ${chalk.white('edtools.config.js')}`);
165
- console.log(` - ${chalk.white('.edtools/')} (local data directory)\n`);
193
+ console.log(` - ${chalk.white('.edtools/config.json')} (API key stored securely)\n`);
166
194
  console.log(chalk.cyan('Next steps:'));
167
195
  console.log(` 1. Review ${chalk.white('edtools.config.js')}`);
168
- const providerMessage = finalProductInfo.preferredProvider === 'openai'
169
- ? `export OPENAI_API_KEY=sk-...`
170
- : `export ANTHROPIC_API_KEY=sk-ant-...`;
171
- console.log(` 2. Set your API key: ${chalk.white(providerMessage)}`);
172
- console.log(` 3. Generate content: ${chalk.white('edtools generate')}\n`);
196
+ console.log(` 2. Generate content: ${chalk.white('edtools generate')}\n`);
197
+ console.log(chalk.gray(`💡 Your API key is stored locally in .edtools/config.json`));
198
+ console.log(chalk.gray(` This folder is gitignored to keep your key safe\n`));
173
199
  }
174
200
  //# sourceMappingURL=init.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,IAAI,IAAI,WAAW,EAAE,MAAM,SAAS,CAAC;AAO9C,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAoB;IACpD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC,CAAC;IAE/D,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAG/C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAC/D,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACpC,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;YAC1C;gBACE,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,8CAA8C;gBACvD,OAAO,EAAE,KAAK;aACf;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;YACxC,OAAO;QACT,CAAC;IACH,CAAC;IAGD,MAAM,OAAO,GAAG,GAAG,CAAC,gCAAgC,CAAC,CAAC,KAAK,EAAE,CAAC;IAC9D,IAAI,WAAW,GAAyB,EAAE,CAAC;IAE3C,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QACvD,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACnD,MAAM,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;YAG5B,WAAW,GAAG;gBACZ,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,YAAY;gBACjE,WAAW,EAAE,CAAC,CAAC,0BAA0B,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;gBAChE,UAAU,EAAE,qBAAqB;gBACjC,QAAQ,EAAE,YAAY;gBACtB,QAAQ,EAAE,EAAE;gBACZ,QAAQ,EAAE,EAAE;aACb,CAAC;YAGF,MAAM,QAAQ,GAAa,EAAE,CAAC;YAC9B,CAAC,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE;gBAC/B,MAAM,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;gBACjC,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;oBAC9B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACtB,CAAC;YACH,CAAC,CAAC,CAAC;YACH,WAAW,CAAC,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAE5C,OAAO,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IACjD,CAAC;IAGD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC,CAAC;IAEtF,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;QACpC;YACE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,eAAe;YACxB,OAAO,EAAE,WAAW,CAAC,IAAI;YACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,0BAA0B;SACpE;QACD;YACE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,8BAA8B;YACvC,OAAO,EAAE,WAAW,CAAC,WAAW;SACjC;QACD;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,WAAW;YACpB,OAAO,EAAE;gBACP,WAAW;gBACX,cAAc;gBACd,UAAU;gBACV,aAAa;gBACb,QAAQ;gBACR,WAAW;gBACX,SAAS;gBACT,QAAQ;gBACR,OAAO;aACR;YACD,OAAO,EAAE,YAAY;SACtB;QACD;YACE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,YAAY;YAClB,OAAO,EAAE,cAAc;YACvB,OAAO,EAAE,WAAW,CAAC,UAAU;YAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;gBAClB,IAAI,CAAC;oBACH,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;oBACf,OAAO,IAAI,CAAC;gBACd,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,0BAA0B,CAAC;gBACpC,CAAC;YACH,CAAC;SACF;QACD;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,cAAc;YACpB,OAAO,EAAE,gBAAgB;YACzB,OAAO,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC;YACpD,OAAO,EAAE,UAAU;SACpB;QACD;YACE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,kCAAkC;YAC3C,OAAO,EAAE,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC;YACzC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;SACjF;QACD;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,mBAAmB;YACzB,OAAO,EAAE,yBAAyB;YAClC,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,kCAAkC,EAAE,KAAK,EAAE,WAAW,EAAE;gBAChE,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,QAAQ,EAAE;aAC9C;YACD,OAAO,EAAE,WAAW;SACrB;KACF,CAAC,CAAC;IAGH,MAAM,gBAAgB,GAAgB;QACpC,GAAG,WAAW;QACd,GAAG,OAAO;KACI,CAAC;IAGjB,MAAM,MAAM,GAAG;;YAEL,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,IAAI,CAAC;eAClC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,OAAO,CAAC;mBACpC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,WAAW,CAAC;gBAC/C,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,QAAQ,CAAC;kBACvC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,UAAU,CAAC;oBACzC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,YAAY,CAAC;gBACjD,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;yBACzC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,iBAAiB,CAAC;;;;;;;;;;;;;;CAc1E,CAAC;IAEA,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAGhD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACtD,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAG/B,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAC1D,MAAM,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAC;IAE/D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,KAAK,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAAC;IAExE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,KAAK,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;IAE/D,MAAM,eAAe,GAAG,gBAAgB,CAAC,iBAAiB,KAAK,QAAQ;QACrE,CAAC,CAAC,8BAA8B;QAChC,CAAC,CAAC,qCAAqC,CAAC;IAE1C,OAAO,CAAC,GAAG,CAAC,0BAA0B,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,0BAA0B,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;AAC7E,CAAC"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
package/dist/cli/index.js CHANGED
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- ContentGenerator,
4
- __require
5
- } from "../chunk-OA4N744J.js";
3
+ ContentGenerator
4
+ } from "../chunk-P36STMVX.js";
6
5
 
7
6
  // src/cli/index.ts
8
7
  import { Command } from "commander";
@@ -134,6 +133,26 @@ async function initCommand(options) {
134
133
  default: "anthropic"
135
134
  }
136
135
  ]);
136
+ console.log(chalk.cyan("\n\u{1F511} API Key Setup:\n"));
137
+ const apiKeyAnswer = await inquirer.prompt([
138
+ {
139
+ type: "password",
140
+ name: "apiKey",
141
+ message: answers.preferredProvider === "anthropic" ? "Anthropic API Key (from https://console.anthropic.com):" : "OpenAI API Key (from https://platform.openai.com/api-keys):",
142
+ validate: (input) => {
143
+ if (!input || input.trim().length === 0) {
144
+ return "API key is required";
145
+ }
146
+ if (answers.preferredProvider === "anthropic" && !input.startsWith("sk-ant-")) {
147
+ return 'Anthropic API keys should start with "sk-ant-"';
148
+ }
149
+ if (answers.preferredProvider === "openai" && !input.startsWith("sk-")) {
150
+ return 'OpenAI API keys should start with "sk-"';
151
+ }
152
+ return true;
153
+ }
154
+ }
155
+ ]);
137
156
  const finalProductInfo = {
138
157
  ...productInfo,
139
158
  ...answers
@@ -165,24 +184,32 @@ async function initCommand(options) {
165
184
  await fs.writeFile(configPath, config, "utf-8");
166
185
  const edtoolsDir = path.join(projectPath, ".edtools");
167
186
  await fs.ensureDir(edtoolsDir);
187
+ const edtoolsConfig = {
188
+ apiKey: apiKeyAnswer.apiKey,
189
+ provider: finalProductInfo.preferredProvider
190
+ };
191
+ const edtoolsConfigPath = path.join(edtoolsDir, "config.json");
192
+ await fs.writeFile(edtoolsConfigPath, JSON.stringify(edtoolsConfig, null, 2), "utf-8");
168
193
  const gitignorePath = path.join(edtoolsDir, ".gitignore");
169
194
  await fs.writeFile(gitignorePath, "*\n!.gitignore\n", "utf-8");
170
195
  console.log(chalk.green("\n\u2713 Configuration created successfully!\n"));
171
196
  console.log(chalk.cyan("Files created:"));
172
197
  console.log(` - ${chalk.white("edtools.config.js")}`);
173
- console.log(` - ${chalk.white(".edtools/")} (local data directory)
198
+ console.log(` - ${chalk.white(".edtools/config.json")} (API key stored securely)
174
199
  `);
175
200
  console.log(chalk.cyan("Next steps:"));
176
201
  console.log(` 1. Review ${chalk.white("edtools.config.js")}`);
177
- const providerMessage = finalProductInfo.preferredProvider === "openai" ? `export OPENAI_API_KEY=sk-...` : `export ANTHROPIC_API_KEY=sk-ant-...`;
178
- console.log(` 2. Set your API key: ${chalk.white(providerMessage)}`);
179
- console.log(` 3. Generate content: ${chalk.white("edtools generate")}
202
+ console.log(` 2. Generate content: ${chalk.white("edtools generate")}
180
203
  `);
204
+ console.log(chalk.gray(`\u{1F4A1} Your API key is stored locally in .edtools/config.json`));
205
+ console.log(chalk.gray(` This folder is gitignored to keep your key safe
206
+ `));
181
207
  }
182
208
 
183
209
  // src/cli/commands/generate.ts
184
210
  import fs2 from "fs-extra";
185
211
  import path2 from "path";
212
+ import { pathToFileURL } from "url";
186
213
  import chalk2 from "chalk";
187
214
  import ora2 from "ora";
188
215
  async function generateCommand(options) {
@@ -194,27 +221,39 @@ async function generateCommand(options) {
194
221
  console.log(chalk2.yellow(' Run "edtools init" first\n'));
195
222
  process.exit(1);
196
223
  }
197
- const config = __require(configPath);
198
- const productInfo = config.product;
224
+ const configUrl = pathToFileURL(configPath).href;
225
+ const config = await import(configUrl);
226
+ const productInfo = config.default.product;
199
227
  if (!productInfo || !productInfo.name) {
200
228
  console.log(chalk2.red("\u2717 Invalid configuration in edtools.config.js"));
201
229
  process.exit(1);
202
230
  }
203
231
  const provider = productInfo.preferredProvider || "anthropic";
232
+ let storedApiKey;
233
+ const edtoolsConfigPath = path2.join(projectPath, ".edtools", "config.json");
234
+ if (await fs2.pathExists(edtoolsConfigPath)) {
235
+ try {
236
+ const edtoolsConfig = await fs2.readJson(edtoolsConfigPath);
237
+ storedApiKey = edtoolsConfig.apiKey;
238
+ } catch (error) {
239
+ }
240
+ }
204
241
  let apiKey;
205
242
  if (provider === "anthropic") {
206
- apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY;
243
+ apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY || storedApiKey;
207
244
  if (!apiKey) {
208
245
  console.log(chalk2.red("\u2717 No Anthropic API key found"));
209
- console.log(chalk2.yellow(" Set ANTHROPIC_API_KEY environment variable"));
246
+ console.log(chalk2.yellow(' Run "edtools init" to configure your API key'));
247
+ console.log(chalk2.yellow(" Or set ANTHROPIC_API_KEY environment variable"));
210
248
  console.log(chalk2.yellow(" Or use --api-key option\n"));
211
249
  process.exit(1);
212
250
  }
213
251
  } else if (provider === "openai") {
214
- apiKey = options.apiKey || process.env.OPENAI_API_KEY;
252
+ apiKey = options.apiKey || process.env.OPENAI_API_KEY || storedApiKey;
215
253
  if (!apiKey) {
216
254
  console.log(chalk2.red("\u2717 No OpenAI API key found"));
217
- console.log(chalk2.yellow(" Set OPENAI_API_KEY environment variable"));
255
+ console.log(chalk2.yellow(' Run "edtools init" to configure your API key'));
256
+ console.log(chalk2.yellow(" Or set OPENAI_API_KEY environment variable"));
218
257
  console.log(chalk2.yellow(" Or use --api-key option\n"));
219
258
  process.exit(1);
220
259
  }
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  AdapterRegistry,
3
3
  ContentGenerator,
4
4
  HTMLAdapter
5
- } from "./chunk-OA4N744J.js";
5
+ } from "./chunk-P36STMVX.js";
6
6
  export {
7
7
  AdapterRegistry,
8
8
  ContentGenerator,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edtools/cli",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Generate SEO-optimized content for LLM discovery - CLI tool",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",