@voicenter-team/nuxt-llms-generator 0.1.1 → 0.1.2

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/README.md CHANGED
@@ -63,9 +63,9 @@ flowchart TB
63
63
  ENV2[🌐 Site 2<br/>SITE_ENV=partner]
64
64
  ENV3[🌐 Site 3<br/>SITE_ENV=staging]
65
65
 
66
- CACHE1[💾 .llms-cache/main/]
67
- CACHE2[💾 .llms-cache/partner/]
68
- CACHE3[💾 .llms-cache/staging/]
66
+ CACHE1[💾 .llms-templates/main/]
67
+ CACHE2[💾 .llms-templates/partner/]
68
+ CACHE3[💾 .llms-templates/staging/]
69
69
 
70
70
  OUT1[📂 .output/llms/main/]
71
71
  OUT2[📂 .output/llms/partner/]
@@ -140,9 +140,9 @@ flowchart TB
140
140
  The system automatically adapts to different environments using the `SITE_ENV` variable:
141
141
 
142
142
  ```bash
143
- SITE_ENV=main → UmbracoData-main.json → .llms-cache/main/ → .output/llms/main/
144
- SITE_ENV=partner → UmbracoData-partner.json → .llms-cache/partner/ → .output/llms/partner/
145
- SITE_ENV=staging → UmbracoData-staging.json → .llms-cache/staging/ → .output/llms/staging/
143
+ SITE_ENV=main → UmbracoData-main.json → .llms-templates/main/ → .output/llms/main/
144
+ SITE_ENV=partner → UmbracoData-partner.json → .llms-templates/partner/ → .output/llms/partner/
145
+ SITE_ENV=staging → UmbracoData-staging.json → .llms-templates/staging/ → .output/llms/staging/
146
146
  ```
147
147
 
148
148
  Each environment maintains its own isolated cache and output, preventing conflicts while sharing the same codebase and configuration logic.
@@ -231,9 +231,8 @@ npm run build
231
231
  |----------------------|----------|----------|------------------|--------------------------------------------|
232
232
  | `anthropicApiKey` | `string` | ✅ | - | Your Claude API key from Anthropic |
233
233
  | `umbracoDataPath` | `string` | ✅ | - | Path to your UmbracoData.json file |
234
- | `templatesOutputDir` | `string` | ❌ | `./templates` | Directory for generated Mustache templates |
234
+ | `templatesDir` | `string` | ❌ | `./.llms-templates` | Directory for templates and cache files |
235
235
  | `finalOutputDir` | `string` | ❌ | `./.output/llms` | Output directory for final documentation |
236
- | `cacheDir` | `string` | ❌ | `./.llms-cache` | Template cache directory |
237
236
 
238
237
  ### Generation Options
239
238
 
@@ -272,9 +271,8 @@ export default defineNuxtConfig({
272
271
 
273
272
  // Environment-specific paths
274
273
  umbracoDataPath: `./public/UmbracoData-${siteEnv}.json`,
275
- cacheDir: `./.llms-cache/${siteEnv}`,
274
+ templatesDir: `./.llms-templates/${siteEnv}`,
276
275
  finalOutputDir: `./.output/llms/${siteEnv}`,
277
- templatesOutputDir: `./templates/${siteEnv}`,
278
276
 
279
277
  // Shared settings
280
278
  maxConcurrent: 5,
@@ -300,10 +298,10 @@ export default defineNuxtConfig({
300
298
 
301
299
  ```
302
300
  project/
303
- ├── .llms-cache/
304
- │ ├── main/ # Main site cache
305
- │ ├── partner/ # Partner site cache
306
- │ └── staging/ # Staging site cache
301
+ ├── .llms-templates/
302
+ │ ├── main/ # Main site templates & cache
303
+ │ ├── partner/ # Partner site templates & cache
304
+ │ └── staging/ # Staging site templates & cache
307
305
  ├── .output/
308
306
  │ └── llms/
309
307
  │ ├── main/ # Main site docs
@@ -569,9 +567,8 @@ interface LLMSConfig {
569
567
  umbracoDataPath: string;
570
568
 
571
569
  // Optional with defaults
572
- templatesOutputDir?: string; // './templates'
570
+ templatesDir?: string; // './.llms-templates'
573
571
  finalOutputDir?: string; // './.output/llms'
574
- cacheDir?: string; // './.llms-cache'
575
572
  anthropicModel?: string; // 'claude-3-5-sonnet-20241022'
576
573
  maxConcurrent?: number; // 5
577
574
  enableLLMSFullTxt?: boolean; // true
@@ -1,10 +1,10 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from 'fs';
2
2
  import { join, dirname, basename } from 'path';
3
3
  import Mustache from 'mustache';
4
4
  import Anthropic from '@anthropic-ai/sdk';
5
5
  import { createHash } from 'crypto';
6
6
  import { JSONPath } from 'jsonpath-plus';
7
- import { T as TemplateError, E as ErrorCode, w as withErrorHandling } from '../shared/nuxt-llms-generator.3c82efc0.mjs';
7
+ import { T as TemplateError, E as ErrorCode, w as withErrorHandling } from '../shared/nuxt-llms-generator.ab079b9f.mjs';
8
8
  import { NodeHtmlMarkdown } from 'node-html-markdown';
9
9
  import '@nuxt/kit';
10
10
  import 'zod';
@@ -367,12 +367,14 @@ class PromptAnalyzer {
367
367
 
368
368
  class LLMSCache {
369
369
  cacheFilePath;
370
+ templatesDir;
370
371
  cache = {};
371
- constructor(cacheDir) {
372
- if (!existsSync(cacheDir)) {
373
- mkdirSync(cacheDir, { recursive: true });
372
+ constructor(templatesDir) {
373
+ this.templatesDir = templatesDir;
374
+ if (!existsSync(templatesDir)) {
375
+ mkdirSync(templatesDir, { recursive: true });
374
376
  }
375
- this.cacheFilePath = join(cacheDir, "templates.json");
377
+ this.cacheFilePath = join(templatesDir, "cache.json");
376
378
  this.loadCache();
377
379
  }
378
380
  loadCache() {
@@ -404,39 +406,95 @@ class LLMSCache {
404
406
  const cached = this.cache[pageId];
405
407
  if (!cached)
406
408
  return null;
409
+ const templatePath = join(this.templatesDir, `${pageId}.mustache`);
410
+ let template = "";
411
+ try {
412
+ if (existsSync(templatePath)) {
413
+ template = readFileSync(templatePath, "utf-8");
414
+ } else {
415
+ console.warn(`Template file not found: ${templatePath}`);
416
+ return null;
417
+ }
418
+ } catch (error) {
419
+ console.warn(`Failed to read template file for ${pageId}:`, error);
420
+ return null;
421
+ }
407
422
  return {
408
423
  pageId,
409
- templatePath: "",
410
- template: cached.template,
411
- hash: cached.hash,
424
+ templatePath,
425
+ template,
426
+ structureHash: cached.structureHash,
427
+ metadata: {
428
+ url: cached.pageId,
429
+ // PageContentHash.pageId contains the URL
430
+ templateAlias: cached.templateAlias,
431
+ jpath: cached.jpath,
432
+ generatedAt: new Date(cached.lastUpdated)
433
+ }
434
+ };
435
+ }
436
+ getTemplateMetadata(pageId) {
437
+ const cached = this.cache[pageId];
438
+ if (!cached)
439
+ return null;
440
+ return {
441
+ structureHash: cached.structureHash,
412
442
  metadata: {
413
- url: cached.metadata.pageId,
414
- // Contains the URL from setTemplate
415
- templateAlias: cached.metadata.templateAlias,
416
- jpath: cached.metadata.jpath,
417
- generatedAt: new Date(cached.metadata.lastUpdated)
443
+ url: cached.pageId,
444
+ // PageContentHash.pageId contains the URL
445
+ templateAlias: cached.templateAlias,
446
+ jpath: cached.jpath,
447
+ generatedAt: new Date(cached.lastUpdated)
418
448
  }
419
449
  };
420
450
  }
451
+ getTemplatePath(pageId) {
452
+ return join(this.templatesDir, `${pageId}.mustache`);
453
+ }
421
454
  getTemplateHash(pageId) {
422
- return this.cache[pageId]?.hash || null;
455
+ return this.cache[pageId]?.structureHash || null;
423
456
  }
424
- setTemplate(pageId, template, hash, metadata) {
457
+ setTemplate(pageId, template, structureHash, jpath, templateAlias, url) {
458
+ const templatePath = join(this.templatesDir, `${pageId}.mustache`);
459
+ try {
460
+ writeFileSync(templatePath, template, "utf-8");
461
+ } catch (error) {
462
+ console.error(`Failed to save template file for ${pageId}:`, error);
463
+ return;
464
+ }
425
465
  this.cache[pageId] = {
426
- hash,
427
- template,
428
- metadata: {
429
- ...metadata,
430
- lastUpdated: /* @__PURE__ */ new Date()
431
- }
466
+ pageId: url,
467
+ // Store URL in pageId field for backwards compatibility
468
+ jpath,
469
+ templateAlias,
470
+ structureHash,
471
+ lastUpdated: /* @__PURE__ */ new Date()
432
472
  };
433
473
  this.saveCache();
434
474
  }
435
475
  removeTemplate(pageId) {
476
+ const templatePath = join(this.templatesDir, `${pageId}.mustache`);
477
+ try {
478
+ if (existsSync(templatePath)) {
479
+ unlinkSync(templatePath);
480
+ }
481
+ } catch (error) {
482
+ console.warn(`Failed to remove template file for ${pageId}:`, error);
483
+ }
436
484
  delete this.cache[pageId];
437
485
  this.saveCache();
438
486
  }
439
487
  clearCache() {
488
+ for (const pageId of Object.keys(this.cache)) {
489
+ const templatePath = join(this.templatesDir, `${pageId}.mustache`);
490
+ try {
491
+ if (existsSync(templatePath)) {
492
+ unlinkSync(templatePath);
493
+ }
494
+ } catch (error) {
495
+ console.warn(`Failed to remove template file for ${pageId}:`, error);
496
+ }
497
+ }
440
498
  this.cache = {};
441
499
  this.saveCache();
442
500
  }
@@ -446,9 +504,9 @@ class LLMSCache {
446
504
  let oldestTemplate = null;
447
505
  let newestTemplate = null;
448
506
  for (const template of templates) {
449
- const alias = template.metadata.templateAlias;
507
+ const alias = template.templateAlias;
450
508
  templatesByAlias[alias] = (templatesByAlias[alias] || 0) + 1;
451
- const date = new Date(template.metadata.lastUpdated);
509
+ const date = new Date(template.lastUpdated);
452
510
  if (!oldestTemplate || date < oldestTemplate) {
453
511
  oldestTemplate = date;
454
512
  }
@@ -467,9 +525,9 @@ class LLMSCache {
467
525
  const cutoffDate = new Date(Date.now() - maxAgeMs);
468
526
  let removedCount = 0;
469
527
  for (const [pageId, template] of Object.entries(this.cache)) {
470
- const templateDate = new Date(template.metadata.lastUpdated);
528
+ const templateDate = new Date(template.lastUpdated);
471
529
  if (templateDate < cutoffDate) {
472
- delete this.cache[pageId];
530
+ this.removeTemplate(pageId);
473
531
  removedCount++;
474
532
  }
475
533
  }
@@ -651,8 +709,8 @@ function getPageVisibilityStats(umbracoData) {
651
709
 
652
710
  class TemplateCleanup {
653
711
  cache;
654
- constructor(cacheDir) {
655
- this.cache = new LLMSCache(cacheDir);
712
+ constructor(templatesDir) {
713
+ this.cache = new LLMSCache(templatesDir);
656
714
  }
657
715
  /**
658
716
  * Find templates that no longer have corresponding pages
@@ -1077,11 +1135,7 @@ class TemplateGenerator {
1077
1135
  this.config = config;
1078
1136
  this.anthropicClient = new AnthropicClient(config);
1079
1137
  this.promptAnalyzer = new PromptAnalyzer();
1080
- if (config.cacheDir) {
1081
- this.cache = new LLMSCache(config.cacheDir);
1082
- } else {
1083
- this.cache = new LLMSCache(".llms-cache");
1084
- }
1138
+ this.cache = new LLMSCache(config.templatesDir || "./.llms-templates");
1085
1139
  this.ensureOutputDirectories();
1086
1140
  }
1087
1141
  async generateTemplate(pageContent, urlItem) {
@@ -1100,7 +1154,7 @@ class TemplateGenerator {
1100
1154
  async generateAllTemplates(umbracoData) {
1101
1155
  const templates = [];
1102
1156
  const maxConcurrent = this.config.maxConcurrent || 5;
1103
- await performAutomaticCleanup(umbracoData, this.config.cacheDir || "./cache", {
1157
+ await performAutomaticCleanup(umbracoData, this.config.templatesDir || "./.llms-templates", {
1104
1158
  enableAutoCleanup: this.config.enableAutoCleanup ?? true,
1105
1159
  cleanupOrphaned: this.config.cleanupOrphaned ?? true,
1106
1160
  cleanupHidden: this.config.cleanupHidden ?? true,
@@ -1189,7 +1243,7 @@ class TemplateGenerator {
1189
1243
  const response = await this.anthropicClient.generateTemplate(request);
1190
1244
  const currentHash = generatePageStructureHash(pageContent, { excludeChildren: true });
1191
1245
  const templatePath = join(
1192
- this.config.templatesOutputDir,
1246
+ this.config.templatesDir,
1193
1247
  `${pageId}.mustache`
1194
1248
  );
1195
1249
  this.saveTemplate(templatePath, response.template);
@@ -1197,7 +1251,7 @@ class TemplateGenerator {
1197
1251
  pageId,
1198
1252
  templatePath,
1199
1253
  template: response.template,
1200
- hash: currentHash,
1254
+ structureHash: currentHash,
1201
1255
  metadata: {
1202
1256
  url: urlItem.url,
1203
1257
  templateAlias: urlItem.TemplateAlias,
@@ -1205,13 +1259,7 @@ class TemplateGenerator {
1205
1259
  generatedAt: /* @__PURE__ */ new Date()
1206
1260
  }
1207
1261
  };
1208
- this.cache.setTemplate(pageId, response.template, currentHash, {
1209
- pageId: urlItem.url,
1210
- // Store URL as pageId for cache lookup
1211
- jpath: urlItem.Jpath,
1212
- templateAlias: urlItem.TemplateAlias,
1213
- structureHash: currentHash
1214
- });
1262
+ this.cache.setTemplate(pageId, response.template, currentHash, urlItem.Jpath, urlItem.TemplateAlias, urlItem.url);
1215
1263
  return generatedTemplate;
1216
1264
  }
1217
1265
  async renderTemplate(template, data) {
@@ -1251,8 +1299,8 @@ class TemplateGenerator {
1251
1299
  writeFileSync(templatePath, content, "utf-8");
1252
1300
  }
1253
1301
  ensureOutputDirectories() {
1254
- if (!existsSync(this.config.templatesOutputDir)) {
1255
- mkdirSync(this.config.templatesOutputDir, { recursive: true });
1302
+ if (!existsSync(this.config.templatesDir || "./.llms-templates")) {
1303
+ mkdirSync(this.config.templatesDir || "./.llms-templates", { recursive: true });
1256
1304
  }
1257
1305
  if (this.config.finalOutputDir && !existsSync(this.config.finalOutputDir)) {
1258
1306
  mkdirSync(this.config.finalOutputDir, { recursive: true });
package/dist/module.d.mts CHANGED
@@ -3,9 +3,8 @@ import * as _nuxt_schema from '@nuxt/schema';
3
3
  interface LLMSConfig {
4
4
  anthropicApiKey: string;
5
5
  umbracoDataPath: string;
6
- templatesOutputDir: string;
6
+ templatesDir: string;
7
7
  finalOutputDir: string;
8
- cacheDir?: string;
9
8
  anthropicModel?: string;
10
9
  maxConcurrent?: number;
11
10
  enableLLMSFullTxt?: boolean;
@@ -55,17 +54,13 @@ interface PageContentHash {
55
54
  lastUpdated: Date;
56
55
  }
57
56
  interface TemplateCache {
58
- [pageId: string]: {
59
- hash: string;
60
- template: string;
61
- metadata: PageContentHash;
62
- };
57
+ [pageId: string]: PageContentHash;
63
58
  }
64
59
  interface GeneratedTemplate {
65
60
  pageId: string;
66
61
  templatePath: string;
67
62
  template: string;
68
- hash: string;
63
+ structureHash: string;
69
64
  metadata: {
70
65
  url: string;
71
66
  templateAlias: string;
package/dist/module.d.ts CHANGED
@@ -3,9 +3,8 @@ import * as _nuxt_schema from '@nuxt/schema';
3
3
  interface LLMSConfig {
4
4
  anthropicApiKey: string;
5
5
  umbracoDataPath: string;
6
- templatesOutputDir: string;
6
+ templatesDir: string;
7
7
  finalOutputDir: string;
8
- cacheDir?: string;
9
8
  anthropicModel?: string;
10
9
  maxConcurrent?: number;
11
10
  enableLLMSFullTxt?: boolean;
@@ -55,17 +54,13 @@ interface PageContentHash {
55
54
  lastUpdated: Date;
56
55
  }
57
56
  interface TemplateCache {
58
- [pageId: string]: {
59
- hash: string;
60
- template: string;
61
- metadata: PageContentHash;
62
- };
57
+ [pageId: string]: PageContentHash;
63
58
  }
64
59
  interface GeneratedTemplate {
65
60
  pageId: string;
66
61
  templatePath: string;
67
62
  template: string;
68
- hash: string;
63
+ structureHash: string;
69
64
  metadata: {
70
65
  url: string;
71
66
  templateAlias: string;
package/dist/module.json CHANGED
@@ -4,5 +4,5 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^3.0.0"
6
6
  },
7
- "version": "0.1.1"
7
+ "version": "0.1.2"
8
8
  }
package/dist/module.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { l as default } from './shared/nuxt-llms-generator.3c82efc0.mjs';
1
+ export { l as default } from './shared/nuxt-llms-generator.ab079b9f.mjs';
2
2
  import '@nuxt/kit';
3
3
  import 'fs';
4
4
  import 'path';
@@ -10,9 +10,8 @@ const anthropicApiKey = z.string().min(10, "API key must be at least 10 characte
10
10
  const LLMSConfigSchema = z.object({
11
11
  anthropicApiKey,
12
12
  umbracoDataPath: existingPath,
13
- templatesOutputDir: z.string().min(1, "Templates output directory is required"),
13
+ templatesDir: z.string().min(1, "Templates directory is required"),
14
14
  finalOutputDir: z.string().optional().default("public"),
15
- cacheDir: z.string().optional().default(".llms-cache"),
16
15
  anthropicModel: z.string().optional(),
17
16
  maxConcurrent: z.number().int().min(1, "maxConcurrent must be at least 1").max(10, "maxConcurrent should not exceed 10 to avoid rate limits").optional().default(3),
18
17
  enableLLMSFullTxt: z.boolean().optional().default(true),
@@ -207,7 +206,7 @@ const DEFAULT_OPTIONS = {
207
206
  maxConcurrent: 5,
208
207
  enableLLMSFullTxt: true,
209
208
  enableIndividualMd: true,
210
- cacheDir: ".llms-cache",
209
+ templatesDir: ".llms-templates",
211
210
  finalOutputDir: "public",
212
211
  enableAutoCleanup: true,
213
212
  cleanupOrphaned: true,
@@ -240,23 +239,23 @@ const llmsModule = defineNuxtModule({
240
239
  logger.warn("No Umbraco data path provided. LLMS Generator will be disabled.");
241
240
  return;
242
241
  }
243
- if (!options.templatesOutputDir) {
244
- logger.warn("No templates output directory provided. LLMS Generator will be disabled.");
242
+ if (!options.templatesDir) {
243
+ logger.warn("No templates directory provided. LLMS Generator will be disabled.");
245
244
  return;
246
245
  }
247
246
  const configForValidation = {
248
247
  anthropicApiKey: options.anthropicApiKey,
249
248
  umbracoDataPath: resolve(nuxt.options.rootDir, options.umbracoDataPath),
250
- templatesOutputDir: resolve(nuxt.options.rootDir, options.templatesOutputDir),
249
+ templatesDir: resolve(nuxt.options.rootDir, options.templatesDir),
251
250
  finalOutputDir: resolve(nuxt.options.rootDir, options.finalOutputDir ?? "public"),
252
- cacheDir: options.cacheDir ? resolve(nuxt.options.rootDir, options.cacheDir) : void 0,
253
251
  anthropicModel: options.anthropicModel || DEFAULT_OPTIONS.anthropicModel,
254
252
  maxConcurrent: options.maxConcurrent || DEFAULT_OPTIONS.maxConcurrent,
255
253
  enableLLMSFullTxt: options.enableLLMSFullTxt ?? DEFAULT_OPTIONS.enableLLMSFullTxt,
256
254
  enableIndividualMd: options.enableIndividualMd ?? DEFAULT_OPTIONS.enableIndividualMd,
257
255
  enableAutoCleanup: options.enableAutoCleanup ?? DEFAULT_OPTIONS.enableAutoCleanup,
258
256
  cleanupOrphaned: options.cleanupOrphaned ?? DEFAULT_OPTIONS.cleanupOrphaned,
259
- cleanupHidden: options.cleanupHidden ?? DEFAULT_OPTIONS.cleanupHidden
257
+ cleanupHidden: options.cleanupHidden ?? DEFAULT_OPTIONS.cleanupHidden,
258
+ enableHtmlToMarkdown: options.enableHtmlToMarkdown ?? DEFAULT_OPTIONS.enableHtmlToMarkdown
260
259
  };
261
260
  let moduleOptions;
262
261
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voicenter-team/nuxt-llms-generator",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Nuxt 3 module for automatically generating AI-optimized documentation files (llms.txt, llms-full.txt, and individual .md files) from Umbraco CMS data using Anthropic's Claude API.",
5
5
  "repository": "your-org/my-module",
6
6
  "license": "MIT",