varmory 1.0.8 → 1.0.10

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "varmory",
3
3
  "description": "Component showcase for Vue 3 + Quasar apps with a built-in MCP (Model Context Protocol) server. Drop in an interactive browser for Quasar and custom components, auto-loaded docs, and searchable API definitions — and expose the same metadata to AI agents like Claude via Streamable HTTP MCP. No extra glue needed.",
4
- "version": "1.0.8",
4
+ "version": "1.0.10",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/jeka-kiselyov/varmory.git"
@@ -14,6 +14,7 @@
14
14
  "dist",
15
15
  "mcp/showcaseMcp.js",
16
16
  "mcp/server.js",
17
+ "scripts/buildSearchIndex.js",
17
18
  "src/varmory/includes/normalizeQuasarApi.js",
18
19
  "src/varmory/includes/package.json"
19
20
  ],
@@ -28,10 +29,14 @@
28
29
  "./mcp": "./mcp/showcaseMcp.js"
29
30
  },
30
31
  "scripts": {
32
+ "dev": "npm run servedemo",
31
33
  "servedemo": "vite --config demo.vite.config.mjs",
32
34
  "builddemo": "NODE_ENV=production vite build --config demo.vite.config.mjs --emptyOutDir",
33
35
  "buildcomponent": "NODE_ENV=production vite build --config component.vite.config.mjs",
36
+ "build:search": "node scripts/buildSearchIndex.js",
37
+ "exportdocs": "node mcp/exportDocs.js",
34
38
  "deploymcp": "npm run buildcomponent; npm run builddemo; bash mcp/heroku/deploy.sh varmory",
39
+ "test": "vitest run",
35
40
  "prepublishOnly": "npm run buildcomponent"
36
41
  },
37
42
  "peerDependencies": {
@@ -47,8 +52,9 @@
47
52
  "@quasar/vite-plugin": "^1.10.0",
48
53
  "@vitejs/plugin-vue": "^5.2.3",
49
54
  "quasar": "^2.19.2",
50
- "vite": "^5.4.18",
55
+ "vite": "^6.4.3",
51
56
  "vite-plugin-lib-inject-css": "^2.2.2",
57
+ "vitest": "^4.1.9",
52
58
  "vue": "^3.5.13"
53
59
  },
54
60
  "sideEffects": [
@@ -70,5 +76,8 @@
70
76
  },
71
77
  "dependencies": {
72
78
  "@quasar/quasar-ui-qmarkdown": "^2.0.5"
79
+ },
80
+ "optionalDependencies": {
81
+ "vecito": "^0.1.1"
73
82
  }
74
83
  }
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+ // ════════════════════════════════════════════════════════════════════════════
3
+ // Build a vecito search snapshot from the showcase categories and docs.
4
+ // The resulting .vecito file is used by both the MCP server (Node) and the
5
+ // browser sidebar (loaded via URL).
6
+ //
7
+ // Usage:
8
+ // node scripts/buildSearchIndex.js [--root <dir>] [--out <path>]
9
+ // [--no-quasar] [--model <name>]
10
+ // ════════════════════════════════════════════════════════════════════════════
11
+
12
+ import path from 'path';
13
+ import fs from 'fs';
14
+ import { Vecito } from 'vecito';
15
+ import { loadAll } from '../mcp/showcaseMcp.js';
16
+
17
+ function parseArgs(argv) {
18
+ const opts = {};
19
+ for (let i = 0; i < argv.length; i++) {
20
+ const a = argv[i];
21
+ if (a === '--root') opts.rootDir = argv[++i];
22
+ else if (a === '--out') opts.out = argv[++i];
23
+ else if (a === '--no-quasar') opts.quasar = false;
24
+ else if (a === '--model') opts.model = argv[++i];
25
+ else if (a === '-h' || a === '--help') opts.help = true;
26
+ else throw new Error(`Unknown arg: ${a}`);
27
+ }
28
+ return opts;
29
+ }
30
+
31
+ const HELP = `
32
+ Build a vecito search index from showcase components and docs.
33
+
34
+ Options:
35
+ --root <dir> Project root (default: cwd)
36
+ --out <path> Output file (default: <root>/dist/search.vecito)
37
+ --no-quasar Skip Quasar's component JSONs
38
+ --model <name> Embedding model (default: Xenova/all-MiniLM-L6-v2)
39
+
40
+ Example:
41
+ node scripts/buildSearchIndex.js
42
+ node scripts/buildSearchIndex.js --out public/search.vecito
43
+ `.trim();
44
+
45
+ const opts = parseArgs(process.argv.slice(2));
46
+ if (opts.help) { console.log(HELP); process.exit(0); }
47
+
48
+ const rootDir = path.resolve(opts.rootDir || process.cwd());
49
+ const outPath = path.resolve(opts.out || path.join(rootDir, 'src/public/search.vecito'));
50
+
51
+ console.log(`Loading showcase data from ${rootDir}...`);
52
+ const { categories, docs } = loadAll({ rootDir, quasar: opts.quasar !== false });
53
+
54
+ const vecitoOpts = {};
55
+ if (opts.model) vecitoOpts.model = opts.model;
56
+ const v = new Vecito(vecitoOpts);
57
+
58
+ // Index components
59
+ const componentDocs = [];
60
+ for (const [cat, items] of Object.entries(categories)) {
61
+ for (const item of items) {
62
+ const impNames = Array.isArray(item.importName) ? item.importName : (item.importName ? [item.importName] : []);
63
+ componentDocs.push({ category: cat, name: item.name, label: item.label, importName: impNames, template: item.template });
64
+ }
65
+ }
66
+
67
+ if (componentDocs.length) {
68
+ console.log(`Indexing ${componentDocs.length} components...`);
69
+ await v.addDocuments(componentDocs, {
70
+ text: d => [d.category, d.name, d.label, ...d.importName, d.template || ''].join(' '),
71
+ metadata: d => ({ type: 'component', category: d.category, name: d.name, label: d.label }),
72
+ });
73
+ }
74
+
75
+ // Index docs
76
+ const docEntries = Object.entries(docs).map(([name, content]) => ({ name, content }));
77
+ if (docEntries.length) {
78
+ console.log(`Indexing ${docEntries.length} docs...`);
79
+ await v.addDocuments(docEntries, {
80
+ text: d => `${d.name}\n${d.content}`,
81
+ metadata: d => ({ type: 'doc', name: d.name }),
82
+ });
83
+ }
84
+
85
+ fs.mkdirSync(path.dirname(outPath), { recursive: true });
86
+ await v.save(outPath);
87
+
88
+ const rel = path.relative(process.cwd(), outPath) || outPath;
89
+ console.log(`Saved search index to ${rel} (${componentDocs.length} components, ${docEntries.length} docs)`);