@zabaca/lattice 1.3.4 → 1.3.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/dist/main.js CHANGED
@@ -20,7 +20,7 @@ import"reflect-metadata";
20
20
  import { CommandFactory } from "nest-commander";
21
21
 
22
22
  // src/app.module.ts
23
- import { Module as Module5 } from "@nestjs/common";
23
+ import { Module as Module6 } from "@nestjs/common";
24
24
  import { ConfigModule as ConfigModule2 } from "@nestjs/config";
25
25
 
26
26
  // src/commands/extract.command.ts
@@ -3595,13 +3595,210 @@ ShareCommand = __legacyDecorateClassTS([
3595
3595
  ], ShareCommand);
3596
3596
  // src/commands/site.command.ts
3597
3597
  import { spawn as spawn3 } from "child_process";
3598
- import { existsSync as existsSync8, readFileSync as readFileSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "fs";
3599
- import * as path3 from "path";
3600
- import { Injectable as Injectable18 } from "@nestjs/common";
3598
+ import { existsSync as existsSync8, readFileSync as readFileSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "fs";
3599
+ import * as path4 from "path";
3600
+ import { Injectable as Injectable19 } from "@nestjs/common";
3601
3601
  import { Command as Command8, CommandRunner as CommandRunner8, Option as Option5 } from "nest-commander";
3602
+
3603
+ // src/site/site.module.ts
3604
+ import { Module as Module2 } from "@nestjs/common";
3605
+
3606
+ // src/graph/graph.module.ts
3607
+ import { Module } from "@nestjs/common";
3608
+ class GraphModule {
3609
+ }
3610
+ GraphModule = __legacyDecorateClassTS([
3611
+ Module({
3612
+ providers: [GraphService],
3613
+ exports: [GraphService]
3614
+ })
3615
+ ], GraphModule);
3616
+
3617
+ // src/site/welcome-generator.service.ts
3618
+ import { writeFileSync as writeFileSync2 } from "fs";
3619
+ import * as path3 from "path";
3620
+ import { Injectable as Injectable18, Logger as Logger8 } from "@nestjs/common";
3621
+ class WelcomeGeneratorService {
3622
+ graphService;
3623
+ logger = new Logger8(WelcomeGeneratorService.name);
3624
+ acronyms = new Set([
3625
+ "ai",
3626
+ "ml",
3627
+ "api",
3628
+ "llm",
3629
+ "gpu",
3630
+ "ui",
3631
+ "ux",
3632
+ "ci",
3633
+ "cd",
3634
+ "aws",
3635
+ "gcp",
3636
+ "seo",
3637
+ "css",
3638
+ "html",
3639
+ "sql",
3640
+ "cli",
3641
+ "sdk",
3642
+ "mcp"
3643
+ ]);
3644
+ constructor(graphService) {
3645
+ this.graphService = graphService;
3646
+ }
3647
+ async generate() {
3648
+ const topics = await this.fetchTopics();
3649
+ const grouped = this.groupByDomain(topics);
3650
+ const markdown = this.generateMarkdown(grouped, topics.length);
3651
+ const docsPath = getDocsPath();
3652
+ const welcomePath = path3.join(docsPath, "welcome.md");
3653
+ writeFileSync2(welcomePath, markdown, "utf-8");
3654
+ this.logger.log(`Generated welcome.md with ${topics.length} topics`);
3655
+ return welcomePath;
3656
+ }
3657
+ async fetchTopics() {
3658
+ const sql = `
3659
+ SELECT
3660
+ name,
3661
+ properties->>'title' as title,
3662
+ properties->>'summary' as summary,
3663
+ properties->>'domain' as domain
3664
+ FROM nodes
3665
+ WHERE label = 'Document' AND name LIKE '%/README.md'
3666
+ ORDER BY name
3667
+ `;
3668
+ const result = await this.graphService.query(sql);
3669
+ const topics = [];
3670
+ for (const row of result.resultSet) {
3671
+ const [filePath, title, summary, domain] = row;
3672
+ const slug = this.extractSlug(filePath);
3673
+ if (!slug) {
3674
+ this.logger.warn(`Could not extract slug from ${filePath}`);
3675
+ continue;
3676
+ }
3677
+ topics.push({
3678
+ slug,
3679
+ title: title || this.formatSlugAsTitle(slug),
3680
+ summary: summary || "",
3681
+ domain: domain || "uncategorized"
3682
+ });
3683
+ }
3684
+ return topics.sort((a, b) => a.slug.localeCompare(b.slug));
3685
+ }
3686
+ extractSlug(filePath) {
3687
+ const match = filePath.match(/\/docs\/([^/]+)\/README\.md$/i);
3688
+ return match ? match[1] : null;
3689
+ }
3690
+ formatSlugAsTitle(slug) {
3691
+ return slug.split("-").map((word) => {
3692
+ const lower = word.toLowerCase();
3693
+ if (this.acronyms.has(lower)) {
3694
+ return word.toUpperCase();
3695
+ }
3696
+ return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
3697
+ }).join(" ");
3698
+ }
3699
+ groupByDomain(topics) {
3700
+ const grouped = new Map;
3701
+ for (const topic of topics) {
3702
+ const domain = topic.domain;
3703
+ if (!grouped.has(domain)) {
3704
+ grouped.set(domain, []);
3705
+ }
3706
+ grouped.get(domain)?.push(topic);
3707
+ }
3708
+ return grouped;
3709
+ }
3710
+ formatDomain(domain) {
3711
+ if (domain === "uncategorized") {
3712
+ return "Uncategorized";
3713
+ }
3714
+ return domain.split("-").map((word) => {
3715
+ const lower = word.toLowerCase();
3716
+ if (this.acronyms.has(lower)) {
3717
+ return word.toUpperCase();
3718
+ }
3719
+ return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
3720
+ }).join(" ");
3721
+ }
3722
+ generateMarkdown(grouped, totalTopics) {
3723
+ const currentDate = new Date().toISOString().split("T")[0];
3724
+ const lines = [
3725
+ "---",
3726
+ `created: ${currentDate}`,
3727
+ `updated: ${currentDate}`,
3728
+ "status: ongoing",
3729
+ "topic: welcome",
3730
+ 'summary: "Auto-generated index of all research topics organized by domain."',
3731
+ "---",
3732
+ "",
3733
+ "# Research Directory",
3734
+ "",
3735
+ `Organized collection of ${totalTopics} research topics. This page is auto-generated from the knowledge graph.`,
3736
+ ""
3737
+ ];
3738
+ const sortedDomains = Array.from(grouped.keys()).sort((a, b) => {
3739
+ if (a === "uncategorized")
3740
+ return 1;
3741
+ if (b === "uncategorized")
3742
+ return -1;
3743
+ return this.formatDomain(a).localeCompare(this.formatDomain(b));
3744
+ });
3745
+ for (const domain of sortedDomains) {
3746
+ const topics = grouped.get(domain);
3747
+ if (!topics)
3748
+ continue;
3749
+ const displayDomain = this.formatDomain(domain);
3750
+ lines.push(`## ${displayDomain}`);
3751
+ lines.push("");
3752
+ lines.push("| Topic | Description |");
3753
+ lines.push("|-------|-------------|");
3754
+ for (const topic of topics) {
3755
+ const link = `./${topic.slug}/readme`;
3756
+ const summary = this.truncateSummary(topic.summary, 100);
3757
+ const escapedSummary = summary.replace(/\|/g, "\\|");
3758
+ lines.push(`| [${topic.slug}](${link}) | ${escapedSummary} |`);
3759
+ }
3760
+ lines.push("");
3761
+ }
3762
+ lines.push("---");
3763
+ lines.push(`*Auto-generated: ${currentDate}*`);
3764
+ lines.push("");
3765
+ return lines.join(`
3766
+ `);
3767
+ }
3768
+ truncateSummary(summary, maxLength) {
3769
+ const cleaned = summary.replace(/\s+/g, " ").trim();
3770
+ if (cleaned.length <= maxLength) {
3771
+ return cleaned;
3772
+ }
3773
+ return `${cleaned.slice(0, maxLength - 3)}...`;
3774
+ }
3775
+ }
3776
+ WelcomeGeneratorService = __legacyDecorateClassTS([
3777
+ Injectable18(),
3778
+ __legacyMetadataTS("design:paramtypes", [
3779
+ typeof GraphService === "undefined" ? Object : GraphService
3780
+ ])
3781
+ ], WelcomeGeneratorService);
3782
+
3783
+ // src/site/site.module.ts
3784
+ class SiteModule {
3785
+ }
3786
+ SiteModule = __legacyDecorateClassTS([
3787
+ Module2({
3788
+ imports: [GraphModule],
3789
+ providers: [WelcomeGeneratorService],
3790
+ exports: [WelcomeGeneratorService]
3791
+ })
3792
+ ], SiteModule);
3793
+ // src/commands/site.command.ts
3602
3794
  class SiteCommand extends CommandRunner8 {
3795
+ welcomeGenerator;
3796
+ constructor(welcomeGenerator) {
3797
+ super();
3798
+ this.welcomeGenerator = welcomeGenerator;
3799
+ }
3603
3800
  getPidFile() {
3604
- return path3.join(getLatticeHome(), "site.pid");
3801
+ return path4.join(getLatticeHome(), "site.pid");
3605
3802
  }
3606
3803
  async run(_inputs, options) {
3607
3804
  if (options.kill) {
@@ -3609,8 +3806,8 @@ class SiteCommand extends CommandRunner8 {
3609
3806
  process.exit(0);
3610
3807
  }
3611
3808
  const latticeHome = getLatticeHome();
3612
- const packageJsonPath = path3.join(latticeHome, "package.json");
3613
- const nodeModulesPath = path3.join(latticeHome, "node_modules");
3809
+ const packageJsonPath = path4.join(latticeHome, "package.json");
3810
+ const nodeModulesPath = path4.join(latticeHome, "node_modules");
3614
3811
  if (!existsSync8(packageJsonPath)) {
3615
3812
  console.error("Error: Site not initialized. Run 'lattice init' first.");
3616
3813
  process.exit(1);
@@ -3625,6 +3822,14 @@ class SiteCommand extends CommandRunner8 {
3625
3822
  await this.runCommand("bun", ["install"], latticeHome);
3626
3823
  console.log();
3627
3824
  }
3825
+ if (!options.noWelcome) {
3826
+ console.log("\uD83D\uDCDD Generating welcome.md...");
3827
+ try {
3828
+ await this.welcomeGenerator.generate();
3829
+ } catch (error) {
3830
+ console.warn(`\u26A0\uFE0F Warning: Failed to generate welcome.md: ${error instanceof Error ? error.message : String(error)}`);
3831
+ }
3832
+ }
3628
3833
  if (options.build) {
3629
3834
  console.log("\uD83D\uDD28 Building site...");
3630
3835
  await this.runCommand("bun", ["run", "build"], latticeHome);
@@ -3678,7 +3883,7 @@ class SiteCommand extends CommandRunner8 {
3678
3883
  env: { ...process.env, FORCE_COLOR: "1" }
3679
3884
  });
3680
3885
  if (child.pid) {
3681
- writeFileSync2(this.getPidFile(), String(child.pid));
3886
+ writeFileSync3(this.getPidFile(), String(child.pid));
3682
3887
  }
3683
3888
  const cleanup = () => {
3684
3889
  try {
@@ -3751,6 +3956,9 @@ class SiteCommand extends CommandRunner8 {
3751
3956
  parseKill() {
3752
3957
  return true;
3753
3958
  }
3959
+ parseNoWelcome() {
3960
+ return true;
3961
+ }
3754
3962
  }
3755
3963
  __legacyDecorateClassTS([
3756
3964
  Option5({
@@ -3790,15 +3998,27 @@ __legacyDecorateClassTS([
3790
3998
  __legacyMetadataTS("design:paramtypes", []),
3791
3999
  __legacyMetadataTS("design:returntype", Boolean)
3792
4000
  ], SiteCommand.prototype, "parseKill", null);
4001
+ __legacyDecorateClassTS([
4002
+ Option5({
4003
+ flags: "--no-welcome",
4004
+ description: "Skip welcome.md generation"
4005
+ }),
4006
+ __legacyMetadataTS("design:type", Function),
4007
+ __legacyMetadataTS("design:paramtypes", []),
4008
+ __legacyMetadataTS("design:returntype", Boolean)
4009
+ ], SiteCommand.prototype, "parseNoWelcome", null);
3793
4010
  SiteCommand = __legacyDecorateClassTS([
3794
- Injectable18(),
4011
+ Injectable19(),
3795
4012
  Command8({
3796
4013
  name: "site",
3797
4014
  description: "Build and run the Lattice documentation site"
3798
- })
4015
+ }),
4016
+ __legacyMetadataTS("design:paramtypes", [
4017
+ typeof WelcomeGeneratorService === "undefined" ? Object : WelcomeGeneratorService
4018
+ ])
3799
4019
  ], SiteCommand);
3800
4020
  // src/commands/status.command.ts
3801
- import { Injectable as Injectable19 } from "@nestjs/common";
4021
+ import { Injectable as Injectable20 } from "@nestjs/common";
3802
4022
  import { Command as Command9, CommandRunner as CommandRunner9, Option as Option6 } from "nest-commander";
3803
4023
  class StatusCommand extends CommandRunner9 {
3804
4024
  syncService;
@@ -3875,7 +4095,7 @@ __legacyDecorateClassTS([
3875
4095
  __legacyMetadataTS("design:returntype", Boolean)
3876
4096
  ], StatusCommand.prototype, "parseVerbose", null);
3877
4097
  StatusCommand = __legacyDecorateClassTS([
3878
- Injectable19(),
4098
+ Injectable20(),
3879
4099
  Command9({
3880
4100
  name: "status",
3881
4101
  description: "Show documents that need syncing (new or updated)"
@@ -3887,15 +4107,15 @@ StatusCommand = __legacyDecorateClassTS([
3887
4107
  ], StatusCommand);
3888
4108
  // src/commands/sync.command.ts
3889
4109
  import { watch } from "fs";
3890
- import { join as join6 } from "path";
3891
- import { Injectable as Injectable21 } from "@nestjs/common";
4110
+ import { join as join7 } from "path";
4111
+ import { Injectable as Injectable22 } from "@nestjs/common";
3892
4112
  import { Command as Command10, CommandRunner as CommandRunner10, Option as Option7 } from "nest-commander";
3893
4113
 
3894
4114
  // src/sync/graph-validator.service.ts
3895
- import { Injectable as Injectable20, Logger as Logger8 } from "@nestjs/common";
4115
+ import { Injectable as Injectable21, Logger as Logger9 } from "@nestjs/common";
3896
4116
  class GraphValidatorService {
3897
4117
  graph;
3898
- logger = new Logger8(GraphValidatorService.name);
4118
+ logger = new Logger9(GraphValidatorService.name);
3899
4119
  constructor(graph) {
3900
4120
  this.graph = graph;
3901
4121
  }
@@ -4011,15 +4231,15 @@ class GraphValidatorService {
4011
4231
  });
4012
4232
  }
4013
4233
  }
4014
- async validateDocument(path4) {
4234
+ async validateDocument(path5) {
4015
4235
  const issues = [];
4016
4236
  try {
4017
- const result = await this.graph.query(`SELECT label, name, properties FROM nodes WHERE label = 'Document' AND name = '${this.escape(path4)}'`);
4237
+ const result = await this.graph.query(`SELECT label, name, properties FROM nodes WHERE label = 'Document' AND name = '${this.escape(path5)}'`);
4018
4238
  if (result.resultSet.length === 0) {
4019
4239
  issues.push({
4020
4240
  type: "error",
4021
4241
  nodeLabel: "Document",
4022
- nodeName: path4,
4242
+ nodeName: path5,
4023
4243
  field: "node",
4024
4244
  message: "Document not found in graph",
4025
4245
  suggestion: "Run 'lattice sync' to add this document"
@@ -4029,9 +4249,9 @@ class GraphValidatorService {
4029
4249
  const row = result.resultSet[0];
4030
4250
  const propertiesJson = row[2];
4031
4251
  const properties = typeof propertiesJson === "string" ? JSON.parse(propertiesJson) : propertiesJson;
4032
- this.validateDocumentNode(path4, properties, issues);
4252
+ this.validateDocumentNode(path5, properties, issues);
4033
4253
  } catch (error) {
4034
- this.logger.error(`Failed to validate document ${path4}: ${error instanceof Error ? error.message : String(error)}`);
4254
+ this.logger.error(`Failed to validate document ${path5}: ${error instanceof Error ? error.message : String(error)}`);
4035
4255
  throw error;
4036
4256
  }
4037
4257
  return issues;
@@ -4041,7 +4261,7 @@ class GraphValidatorService {
4041
4261
  }
4042
4262
  }
4043
4263
  GraphValidatorService = __legacyDecorateClassTS([
4044
- Injectable20(),
4264
+ Injectable21(),
4045
4265
  __legacyMetadataTS("design:paramtypes", [
4046
4266
  typeof GraphService === "undefined" ? Object : GraphService
4047
4267
  ])
@@ -4191,7 +4411,7 @@ class SyncCommand extends CommandRunner10 {
4191
4411
  `);
4192
4412
  this.watcher = watch(docsPath, { recursive: true }, (event, filename) => {
4193
4413
  if (filename?.endsWith(".md")) {
4194
- const fullPath = join6(docsPath, filename);
4414
+ const fullPath = join7(docsPath, filename);
4195
4415
  trackedFiles.add(fullPath);
4196
4416
  debouncedSync();
4197
4417
  }
@@ -4393,7 +4613,7 @@ __legacyDecorateClassTS([
4393
4613
  __legacyMetadataTS("design:returntype", Boolean)
4394
4614
  ], SyncCommand.prototype, "parseSkipExtraction", null);
4395
4615
  SyncCommand = __legacyDecorateClassTS([
4396
- Injectable21(),
4616
+ Injectable22(),
4397
4617
  Command10({
4398
4618
  name: "sync",
4399
4619
  arguments: "[paths...]",
@@ -4406,37 +4626,26 @@ SyncCommand = __legacyDecorateClassTS([
4406
4626
  ])
4407
4627
  ], SyncCommand);
4408
4628
  // src/embedding/embedding.module.ts
4409
- import { Module } from "@nestjs/common";
4629
+ import { Module as Module3 } from "@nestjs/common";
4410
4630
  import { ConfigModule } from "@nestjs/config";
4411
4631
  class EmbeddingModule {
4412
4632
  }
4413
4633
  EmbeddingModule = __legacyDecorateClassTS([
4414
- Module({
4634
+ Module3({
4415
4635
  imports: [ConfigModule],
4416
4636
  providers: [EmbeddingService],
4417
4637
  exports: [EmbeddingService]
4418
4638
  })
4419
4639
  ], EmbeddingModule);
4420
4640
 
4421
- // src/graph/graph.module.ts
4422
- import { Module as Module2 } from "@nestjs/common";
4423
- class GraphModule {
4424
- }
4425
- GraphModule = __legacyDecorateClassTS([
4426
- Module2({
4427
- providers: [GraphService],
4428
- exports: [GraphService]
4429
- })
4430
- ], GraphModule);
4431
-
4432
4641
  // src/query/query.module.ts
4433
- import { Module as Module3 } from "@nestjs/common";
4642
+ import { Module as Module4 } from "@nestjs/common";
4434
4643
 
4435
4644
  // src/query/query.service.ts
4436
- import { Injectable as Injectable22, Logger as Logger9 } from "@nestjs/common";
4645
+ import { Injectable as Injectable23, Logger as Logger10 } from "@nestjs/common";
4437
4646
  class QueryService {
4438
4647
  graphService;
4439
- logger = new Logger9(QueryService.name);
4648
+ logger = new Logger10(QueryService.name);
4440
4649
  constructor(graphService) {
4441
4650
  this.graphService = graphService;
4442
4651
  }
@@ -4446,7 +4655,7 @@ class QueryService {
4446
4655
  }
4447
4656
  }
4448
4657
  QueryService = __legacyDecorateClassTS([
4449
- Injectable22(),
4658
+ Injectable23(),
4450
4659
  __legacyMetadataTS("design:paramtypes", [
4451
4660
  typeof GraphService === "undefined" ? Object : GraphService
4452
4661
  ])
@@ -4456,7 +4665,7 @@ QueryService = __legacyDecorateClassTS([
4456
4665
  class QueryModule {
4457
4666
  }
4458
4667
  QueryModule = __legacyDecorateClassTS([
4459
- Module3({
4668
+ Module4({
4460
4669
  imports: [GraphModule, EmbeddingModule],
4461
4670
  providers: [QueryService, GraphService],
4462
4671
  exports: [QueryService, GraphService]
@@ -4464,11 +4673,11 @@ QueryModule = __legacyDecorateClassTS([
4464
4673
  ], QueryModule);
4465
4674
 
4466
4675
  // src/sync/sync.module.ts
4467
- import { Module as Module4 } from "@nestjs/common";
4676
+ import { Module as Module5 } from "@nestjs/common";
4468
4677
  class SyncModule {
4469
4678
  }
4470
4679
  SyncModule = __legacyDecorateClassTS([
4471
- Module4({
4680
+ Module5({
4472
4681
  imports: [GraphModule, EmbeddingModule],
4473
4682
  providers: [
4474
4683
  SyncService,
@@ -4499,7 +4708,7 @@ SyncModule = __legacyDecorateClassTS([
4499
4708
  class AppModule {
4500
4709
  }
4501
4710
  AppModule = __legacyDecorateClassTS([
4502
- Module5({
4711
+ Module6({
4503
4712
  imports: [
4504
4713
  ConfigModule2.forRoot({
4505
4714
  isGlobal: true,
@@ -4508,7 +4717,8 @@ AppModule = __legacyDecorateClassTS([
4508
4717
  GraphModule,
4509
4718
  SyncModule,
4510
4719
  EmbeddingModule,
4511
- QueryModule
4720
+ QueryModule,
4721
+ SiteModule
4512
4722
  ],
4513
4723
  providers: [
4514
4724
  ExtractCommand,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zabaca/lattice",
3
- "version": "1.3.4",
3
+ "version": "1.3.6",
4
4
  "description": "Human-initiated, AI-powered knowledge graph for markdown documentation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,2 @@
1
+ User-agent: *
2
+ Allow: /