@creeperhost/modlens-mcp 1.6.0 → 1.6.4

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.
Files changed (135) hide show
  1. package/README.md +950 -938
  2. package/dist/cli.js +267 -267
  3. package/dist/db-backend.d.ts +14 -1
  4. package/dist/db-backend.d.ts.map +1 -1
  5. package/dist/db-backend.js +13 -0
  6. package/dist/db-backend.js.map +1 -1
  7. package/dist/generated/sqlite/internal/class.d.ts.map +1 -1
  8. package/dist/generated/sqlite/internal/class.js +5 -4
  9. package/dist/generated/sqlite/internal/class.js.map +1 -1
  10. package/dist/launcher.js +4 -1
  11. package/dist/launcher.js.map +1 -1
  12. package/dist/platform.d.ts.map +1 -1
  13. package/dist/platform.js +6 -2
  14. package/dist/platform.js.map +1 -1
  15. package/dist/repositories/embeddings-sqlite.js +21 -21
  16. package/dist/repositories/embeddings.js +28 -28
  17. package/dist/repositories/mod.d.ts +7 -0
  18. package/dist/repositories/mod.d.ts.map +1 -1
  19. package/dist/repositories/mod.js +56 -15
  20. package/dist/repositories/mod.js.map +1 -1
  21. package/dist/search-adapter.js +51 -51
  22. package/dist/security.d.ts +9 -0
  23. package/dist/security.d.ts.map +1 -1
  24. package/dist/security.js +19 -0
  25. package/dist/security.js.map +1 -1
  26. package/dist/server.js +1248 -1217
  27. package/dist/server.js.map +1 -1
  28. package/dist/tools/compat-check.js +9 -9
  29. package/dist/tools/docs.d.ts.map +1 -1
  30. package/dist/tools/docs.js +4 -3
  31. package/dist/tools/docs.js.map +1 -1
  32. package/dist/tools/embed-registry.js +9 -9
  33. package/dist/tools/graphify.js +14 -14
  34. package/dist/tools/ingest.d.ts.map +1 -1
  35. package/dist/tools/ingest.js +4 -3
  36. package/dist/tools/ingest.js.map +1 -1
  37. package/dist/tools/kubejs.d.ts.map +1 -1
  38. package/dist/tools/kubejs.js +2 -0
  39. package/dist/tools/kubejs.js.map +1 -1
  40. package/dist/tools/mappings.d.ts.map +1 -1
  41. package/dist/tools/mappings.js +2 -1
  42. package/dist/tools/mappings.js.map +1 -1
  43. package/dist/tools/mc-fts.js +2 -2
  44. package/dist/tools/mcmeta.js +2 -2
  45. package/dist/tools/mcmeta.js.map +1 -1
  46. package/dist/tools/mixin-scan.d.ts +1 -1
  47. package/dist/tools/mixin-scan.d.ts.map +1 -1
  48. package/dist/tools/mixin-scan.js +29 -35
  49. package/dist/tools/mixin-scan.js.map +1 -1
  50. package/dist/tools/mod-data.js +2 -2
  51. package/dist/tools/mod-data.js.map +1 -1
  52. package/dist/tools/modpacks-ch.js +2 -2
  53. package/dist/tools/modpacks-ch.js.map +1 -1
  54. package/dist/tools/packtools.js +4 -4
  55. package/dist/tools/packtools.js.map +1 -1
  56. package/dist/tools/primers.d.ts.map +1 -1
  57. package/dist/tools/primers.js +4 -3
  58. package/dist/tools/primers.js.map +1 -1
  59. package/dist/tools/reports.d.ts.map +1 -1
  60. package/dist/tools/reports.js +8 -4
  61. package/dist/tools/reports.js.map +1 -1
  62. package/dist/tools/vanilla-data.js +2 -2
  63. package/dist/tools/vanilla-data.js.map +1 -1
  64. package/dist/tools/version-diff.js +3 -3
  65. package/package.json +70 -62
  66. package/prisma/backends/schema.sqlite.prisma +215 -215
  67. package/prisma/schema.prisma +303 -303
  68. package/scripts/backup.mjs +151 -151
  69. package/scripts/check-atm10.mjs +27 -27
  70. package/scripts/check-sync.mjs +13 -13
  71. package/scripts/create-fts-index.mjs +50 -50
  72. package/scripts/enable-pgvector.mjs +90 -90
  73. package/scripts/enable-sqlite-vec.mjs +158 -158
  74. package/scripts/migrate-backend.mjs +188 -188
  75. package/scripts/migrate-embed-provenance.mjs +80 -80
  76. package/scripts/migrate-metadata-source.mjs +62 -62
  77. package/scripts/migrate-mod-source-files.mjs +67 -67
  78. package/scripts/post-update.mjs +77 -77
  79. package/scripts/verify-atm10.mjs +63 -63
  80. package/dist/access-flags.test.d.ts +0 -2
  81. package/dist/access-flags.test.d.ts.map +0 -1
  82. package/dist/access-flags.test.js +0 -189
  83. package/dist/access-flags.test.js.map +0 -1
  84. package/dist/fetch-utils.test.d.ts +0 -2
  85. package/dist/fetch-utils.test.d.ts.map +0 -1
  86. package/dist/fetch-utils.test.js +0 -133
  87. package/dist/fetch-utils.test.js.map +0 -1
  88. package/dist/mappings.test.d.ts +0 -2
  89. package/dist/mappings.test.d.ts.map +0 -1
  90. package/dist/mappings.test.js +0 -161
  91. package/dist/mappings.test.js.map +0 -1
  92. package/dist/processor.test.d.ts +0 -2
  93. package/dist/processor.test.d.ts.map +0 -1
  94. package/dist/processor.test.js +0 -629
  95. package/dist/processor.test.js.map +0 -1
  96. package/dist/search.test.d.ts +0 -2
  97. package/dist/search.test.d.ts.map +0 -1
  98. package/dist/search.test.js +0 -71
  99. package/dist/search.test.js.map +0 -1
  100. package/dist/security.test.d.ts +0 -2
  101. package/dist/security.test.d.ts.map +0 -1
  102. package/dist/security.test.js +0 -687
  103. package/dist/security.test.js.map +0 -1
  104. package/dist/tools/compat-check.test.d.ts +0 -2
  105. package/dist/tools/compat-check.test.d.ts.map +0 -1
  106. package/dist/tools/compat-check.test.js +0 -179
  107. package/dist/tools/compat-check.test.js.map +0 -1
  108. package/dist/tools/diagnostics.test.d.ts +0 -2
  109. package/dist/tools/diagnostics.test.d.ts.map +0 -1
  110. package/dist/tools/diagnostics.test.js +0 -168
  111. package/dist/tools/diagnostics.test.js.map +0 -1
  112. package/dist/tools/graphify.test.d.ts +0 -2
  113. package/dist/tools/graphify.test.d.ts.map +0 -1
  114. package/dist/tools/graphify.test.js +0 -39
  115. package/dist/tools/graphify.test.js.map +0 -1
  116. package/dist/tools/ingest.test.d.ts +0 -2
  117. package/dist/tools/ingest.test.d.ts.map +0 -1
  118. package/dist/tools/ingest.test.js +0 -340
  119. package/dist/tools/ingest.test.js.map +0 -1
  120. package/dist/tools/mod-tags.test.d.ts +0 -2
  121. package/dist/tools/mod-tags.test.d.ts.map +0 -1
  122. package/dist/tools/mod-tags.test.js +0 -75
  123. package/dist/tools/mod-tags.test.js.map +0 -1
  124. package/dist/tools/packtools.test.d.ts +0 -2
  125. package/dist/tools/packtools.test.d.ts.map +0 -1
  126. package/dist/tools/packtools.test.js +0 -99
  127. package/dist/tools/packtools.test.js.map +0 -1
  128. package/dist/tools/version-diff.test.d.ts +0 -2
  129. package/dist/tools/version-diff.test.d.ts.map +0 -1
  130. package/dist/tools/version-diff.test.js +0 -102
  131. package/dist/tools/version-diff.test.js.map +0 -1
  132. package/dist/validate.test.d.ts +0 -2
  133. package/dist/validate.test.d.ts.map +0 -1
  134. package/dist/validate.test.js +0 -73
  135. package/dist/validate.test.js.map +0 -1
@@ -1,151 +1,151 @@
1
- // scripts/backup.mjs
2
- /**
3
- * Backup the active modlens database.
4
- * Usage: node scripts/backup.mjs
5
- * Or via npm: npm run db:backup
6
- *
7
- * Backs up to ~/.modlens-backups/<timestamp>-<backend>.<ext>
8
- * Appends restore instructions to ~/.modlens-backups/README.md
9
- */
10
- import { execSync } from "child_process";
11
- import { cpSync, mkdirSync, existsSync, appendFileSync, copyFileSync } from "fs";
12
- import { homedir } from "os";
13
- import { join } from "path";
14
- import { createRequire } from "module";
15
-
16
- const require = createRequire(import.meta.url);
17
- try { require("dotenv").config(); } catch { /* dotenv optional */ }
18
-
19
- const DATABASE_URL = process.env.DATABASE_URL ?? "";
20
- const BACKUP_ROOT = process.env.MODLENS_BACKUP_DIR ?? join(homedir(), ".modlens-backups");
21
-
22
- function detectBackend(url) {
23
- if (url.startsWith("file:") || url.endsWith(".db")) return "sqlite";
24
- if (url.startsWith("pglite://") || url.startsWith("pglite:")) return "pglite";
25
- return "postgres";
26
- }
27
-
28
- function timestamp() {
29
- return new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
30
- }
31
-
32
- function ensureDir(dir) {
33
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
34
- }
35
-
36
- function appendReadme(root, lines) {
37
- ensureDir(root);
38
- appendFileSync(join(root, "README.md"), lines.join("\n") + "\n\n");
39
- }
40
-
41
- // ── Postgres backup ──────────────────────────────────────────────────────────
42
-
43
- function backupPostgres(url, root = BACKUP_ROOT) {
44
- ensureDir(root);
45
- const ts = timestamp();
46
- const file = join(root, `modlens-postgres-${ts}.sql`);
47
-
48
- try {
49
- execSync(`pg_dump "${url}" -f "${file}"`, { stdio: "inherit" });
50
- } catch {
51
- try {
52
- const container = process.env.MODLENS_POSTGRES_CONTAINER ?? "modlens-postgres";
53
- execSync(
54
- `docker exec ${container} pg_dump "${url}" > "${file}"`,
55
- { stdio: "inherit", shell: true },
56
- );
57
- } catch (e) {
58
- throw new Error(
59
- `pg_dump failed. Install pg_dump or ensure the postgres container is running.\n${e.message}`,
60
- );
61
- }
62
- }
63
-
64
- const restore = `psql "${url}" < "${file}"`;
65
- appendReadme(root, [
66
- `## Postgres backup — ${ts}`,
67
- `File: ${file}`,
68
- `Restore: \`${restore}\``,
69
- ]);
70
- return { file, restore };
71
- }
72
-
73
- // ── PGlite backup ────────────────────────────────────────────────────────────
74
-
75
- function backupPglite(url, root = BACKUP_ROOT) {
76
- ensureDir(root);
77
- const ts = timestamp();
78
- const dataDir = url.replace(/^pglite:\/\//, "");
79
- const outDir = join(root, `modlens-pglite-${ts}`);
80
-
81
- if (!existsSync(dataDir)) {
82
- throw new Error(`PGlite data directory does not exist: ${dataDir}`);
83
- }
84
-
85
- cpSync(dataDir, outDir, { recursive: true });
86
-
87
- const restore = `cp -r "${outDir}" "${dataDir}"`;
88
- appendReadme(root, [
89
- `## PGlite backup — ${ts}`,
90
- `Directory: ${outDir}`,
91
- `Restore: \`${restore}\``,
92
- ]);
93
- return { dir: outDir, restore };
94
- }
95
-
96
- // ── SQLite backup ────────────────────────────────────────────────────────────
97
-
98
- function backupSqlite(url, root = BACKUP_ROOT) {
99
- ensureDir(root);
100
- const ts = timestamp();
101
- const dbPath = url.replace(/^file:\/\//, "").replace(/^file:/, "");
102
- const file = join(root, `modlens-sqlite-${ts}.db`);
103
-
104
- if (!existsSync(dbPath)) {
105
- throw new Error(`SQLite database file does not exist: ${dbPath}`);
106
- }
107
-
108
- copyFileSync(dbPath, file);
109
-
110
- const restore = `cp "${file}" "${dbPath}"`;
111
- appendReadme(root, [
112
- `## SQLite backup — ${ts}`,
113
- `File: ${file}`,
114
- `Restore: \`${restore}\``,
115
- ]);
116
- return { file, restore };
117
- }
118
-
119
- // ── Programmatic API ─────────────────────────────────────────────────────────
120
-
121
- /**
122
- * Backup the database at `url` to `backupRoot` (defaults to ~/.modlens-backups).
123
- * @param {string} url
124
- * @param {string} [backupRoot]
125
- * @returns {{ file?: string, dir?: string, restore: string }}
126
- */
127
- export async function backup(url, backupRoot) {
128
- const root = backupRoot ?? BACKUP_ROOT;
129
- const backend = detectBackend(url);
130
- if (backend === "postgres") return backupPostgres(url, root);
131
- if (backend === "pglite") return backupPglite(url, root);
132
- return backupSqlite(url, root);
133
- }
134
-
135
- // ── CLI entry point ───────────────────────────────────────────────────────────
136
-
137
- const isCli = process.argv[1]?.replace(/\\/g, "/").endsWith("backup.mjs");
138
- if (isCli) {
139
- if (!DATABASE_URL) {
140
- console.error("DATABASE_URL is not set. Create a .env file or set the variable.");
141
- process.exit(1);
142
- }
143
-
144
- const backend = detectBackend(DATABASE_URL);
145
- console.log(`Backing up ${backend} database...`);
146
-
147
- const result = await backup(DATABASE_URL);
148
- console.log(`Backup written: ${result.file ?? result.dir}`);
149
- console.log(`Restore command: ${result.restore}`);
150
- console.log(`Restore instructions also appended to: ${join(BACKUP_ROOT, "README.md")}`);
151
- }
1
+ // scripts/backup.mjs
2
+ /**
3
+ * Backup the active modlens database.
4
+ * Usage: node scripts/backup.mjs
5
+ * Or via npm: npm run db:backup
6
+ *
7
+ * Backs up to ~/.modlens-backups/<timestamp>-<backend>.<ext>
8
+ * Appends restore instructions to ~/.modlens-backups/README.md
9
+ */
10
+ import { execSync } from "child_process";
11
+ import { cpSync, mkdirSync, existsSync, appendFileSync, copyFileSync } from "fs";
12
+ import { homedir } from "os";
13
+ import { join } from "path";
14
+ import { createRequire } from "module";
15
+
16
+ const require = createRequire(import.meta.url);
17
+ try { require("dotenv").config(); } catch { /* dotenv optional */ }
18
+
19
+ const DATABASE_URL = process.env.DATABASE_URL ?? "";
20
+ const BACKUP_ROOT = process.env.MODLENS_BACKUP_DIR ?? join(homedir(), ".modlens-backups");
21
+
22
+ function detectBackend(url) {
23
+ if (url.startsWith("file:") || url.endsWith(".db")) return "sqlite";
24
+ if (url.startsWith("pglite://") || url.startsWith("pglite:")) return "pglite";
25
+ return "postgres";
26
+ }
27
+
28
+ function timestamp() {
29
+ return new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
30
+ }
31
+
32
+ function ensureDir(dir) {
33
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
34
+ }
35
+
36
+ function appendReadme(root, lines) {
37
+ ensureDir(root);
38
+ appendFileSync(join(root, "README.md"), lines.join("\n") + "\n\n");
39
+ }
40
+
41
+ // ── Postgres backup ──────────────────────────────────────────────────────────
42
+
43
+ function backupPostgres(url, root = BACKUP_ROOT) {
44
+ ensureDir(root);
45
+ const ts = timestamp();
46
+ const file = join(root, `modlens-postgres-${ts}.sql`);
47
+
48
+ try {
49
+ execSync(`pg_dump "${url}" -f "${file}"`, { stdio: "inherit" });
50
+ } catch {
51
+ try {
52
+ const container = process.env.MODLENS_POSTGRES_CONTAINER ?? "modlens-postgres";
53
+ execSync(
54
+ `docker exec ${container} pg_dump "${url}" > "${file}"`,
55
+ { stdio: "inherit", shell: true },
56
+ );
57
+ } catch (e) {
58
+ throw new Error(
59
+ `pg_dump failed. Install pg_dump or ensure the postgres container is running.\n${e.message}`,
60
+ );
61
+ }
62
+ }
63
+
64
+ const restore = `psql "${url}" < "${file}"`;
65
+ appendReadme(root, [
66
+ `## Postgres backup — ${ts}`,
67
+ `File: ${file}`,
68
+ `Restore: \`${restore}\``,
69
+ ]);
70
+ return { file, restore };
71
+ }
72
+
73
+ // ── PGlite backup ────────────────────────────────────────────────────────────
74
+
75
+ function backupPglite(url, root = BACKUP_ROOT) {
76
+ ensureDir(root);
77
+ const ts = timestamp();
78
+ const dataDir = url.replace(/^pglite:\/\//, "");
79
+ const outDir = join(root, `modlens-pglite-${ts}`);
80
+
81
+ if (!existsSync(dataDir)) {
82
+ throw new Error(`PGlite data directory does not exist: ${dataDir}`);
83
+ }
84
+
85
+ cpSync(dataDir, outDir, { recursive: true });
86
+
87
+ const restore = `cp -r "${outDir}" "${dataDir}"`;
88
+ appendReadme(root, [
89
+ `## PGlite backup — ${ts}`,
90
+ `Directory: ${outDir}`,
91
+ `Restore: \`${restore}\``,
92
+ ]);
93
+ return { dir: outDir, restore };
94
+ }
95
+
96
+ // ── SQLite backup ────────────────────────────────────────────────────────────
97
+
98
+ function backupSqlite(url, root = BACKUP_ROOT) {
99
+ ensureDir(root);
100
+ const ts = timestamp();
101
+ const dbPath = url.replace(/^file:\/\//, "").replace(/^file:/, "");
102
+ const file = join(root, `modlens-sqlite-${ts}.db`);
103
+
104
+ if (!existsSync(dbPath)) {
105
+ throw new Error(`SQLite database file does not exist: ${dbPath}`);
106
+ }
107
+
108
+ copyFileSync(dbPath, file);
109
+
110
+ const restore = `cp "${file}" "${dbPath}"`;
111
+ appendReadme(root, [
112
+ `## SQLite backup — ${ts}`,
113
+ `File: ${file}`,
114
+ `Restore: \`${restore}\``,
115
+ ]);
116
+ return { file, restore };
117
+ }
118
+
119
+ // ── Programmatic API ─────────────────────────────────────────────────────────
120
+
121
+ /**
122
+ * Backup the database at `url` to `backupRoot` (defaults to ~/.modlens-backups).
123
+ * @param {string} url
124
+ * @param {string} [backupRoot]
125
+ * @returns {{ file?: string, dir?: string, restore: string }}
126
+ */
127
+ export async function backup(url, backupRoot) {
128
+ const root = backupRoot ?? BACKUP_ROOT;
129
+ const backend = detectBackend(url);
130
+ if (backend === "postgres") return backupPostgres(url, root);
131
+ if (backend === "pglite") return backupPglite(url, root);
132
+ return backupSqlite(url, root);
133
+ }
134
+
135
+ // ── CLI entry point ───────────────────────────────────────────────────────────
136
+
137
+ const isCli = process.argv[1]?.replace(/\\/g, "/").endsWith("backup.mjs");
138
+ if (isCli) {
139
+ if (!DATABASE_URL) {
140
+ console.error("DATABASE_URL is not set. Create a .env file or set the variable.");
141
+ process.exit(1);
142
+ }
143
+
144
+ const backend = detectBackend(DATABASE_URL);
145
+ console.log(`Backing up ${backend} database...`);
146
+
147
+ const result = await backup(DATABASE_URL);
148
+ console.log(`Backup written: ${result.file ?? result.dir}`);
149
+ console.log(`Restore command: ${result.restore}`);
150
+ console.log(`Restore instructions also appended to: ${join(BACKUP_ROOT, "README.md")}`);
151
+ }
@@ -1,27 +1,27 @@
1
- import { PrismaClient } from '@prisma/client';
2
- const db = new PrismaClient();
3
-
4
- const stats = await db.mod.aggregate({ _min: { id: true }, _max: { id: true } });
5
- const totalMods = await db.mod.count();
6
- const atm10Files = await db.packFile.count({ where: { packVersionId: 1, fileType: 'mod' } });
7
- const atm10WithModId = await db.packFile.count({ where: { packVersionId: 1, fileType: 'mod', modId: { not: null } } });
8
- const atm10NotSynced = await db.packFile.count({ where: { packVersionId: 1, fileType: 'mod', status: 'not_synced' } });
9
- const atm10AlreadyIngested = await db.packFile.count({ where: { packVersionId: 1, fileType: 'mod', status: 'already_ingested' } });
10
- const atm10Ingested = await db.packFile.count({ where: { packVersionId: 1, fileType: 'mod', status: 'ingested' } });
11
-
12
- const lowestAtm10Mod = await db.packFile.findFirst({ where: { packVersionId: 1, modId: { not: null } }, orderBy: { modId: 'asc' }, select: { modId: true, fileName: true } });
13
- const highestAtm10Mod = await db.packFile.findFirst({ where: { packVersionId: 1, modId: { not: null } }, orderBy: { modId: 'desc' }, select: { modId: true, fileName: true } });
14
-
15
- console.log(JSON.stringify({
16
- totalModsInDb: totalMods,
17
- dbModIdRange: stats,
18
- atm10Files,
19
- atm10WithModId,
20
- atm10Ingested,
21
- atm10AlreadyIngested,
22
- atm10NotSynced,
23
- lowestAtm10Mod,
24
- highestAtm10Mod,
25
- }, null, 2));
26
-
27
- await db.$disconnect();
1
+ import { PrismaClient } from '@prisma/client';
2
+ const db = new PrismaClient();
3
+
4
+ const stats = await db.mod.aggregate({ _min: { id: true }, _max: { id: true } });
5
+ const totalMods = await db.mod.count();
6
+ const atm10Files = await db.packFile.count({ where: { packVersionId: 1, fileType: 'mod' } });
7
+ const atm10WithModId = await db.packFile.count({ where: { packVersionId: 1, fileType: 'mod', modId: { not: null } } });
8
+ const atm10NotSynced = await db.packFile.count({ where: { packVersionId: 1, fileType: 'mod', status: 'not_synced' } });
9
+ const atm10AlreadyIngested = await db.packFile.count({ where: { packVersionId: 1, fileType: 'mod', status: 'already_ingested' } });
10
+ const atm10Ingested = await db.packFile.count({ where: { packVersionId: 1, fileType: 'mod', status: 'ingested' } });
11
+
12
+ const lowestAtm10Mod = await db.packFile.findFirst({ where: { packVersionId: 1, modId: { not: null } }, orderBy: { modId: 'asc' }, select: { modId: true, fileName: true } });
13
+ const highestAtm10Mod = await db.packFile.findFirst({ where: { packVersionId: 1, modId: { not: null } }, orderBy: { modId: 'desc' }, select: { modId: true, fileName: true } });
14
+
15
+ console.log(JSON.stringify({
16
+ totalModsInDb: totalMods,
17
+ dbModIdRange: stats,
18
+ atm10Files,
19
+ atm10WithModId,
20
+ atm10Ingested,
21
+ atm10AlreadyIngested,
22
+ atm10NotSynced,
23
+ lowestAtm10Mod,
24
+ highestAtm10Mod,
25
+ }, null, 2));
26
+
27
+ await db.$disconnect();
@@ -1,13 +1,13 @@
1
- import { readFileSync } from 'fs';
2
- // Load .env
3
- for (const line of readFileSync('d:/Downloads/modlens-mcp/.env', 'utf8').split('\n')) {
4
- const m = line.match(/^([^#=]+)=(.*)$/);
5
- if (m) process.env[m[1].trim()] ??= m[2].trim().replace(/^["']|["']$/g, '');
6
- }
7
- import { PrismaClient } from '@prisma/client';
8
- const db = new PrismaClient();
9
- const cfFilled = await db.mod.count({ where: { curseforgeId: { not: null } } });
10
- const mrFilled = await db.mod.count({ where: { modrinthId: { not: null } } });
11
- console.log(`curseforgeId populated: ${cfFilled} / 821`);
12
- console.log(`modrinthId populated: ${mrFilled} / 821`);
13
- await db.$disconnect();
1
+ import { readFileSync } from 'fs';
2
+ // Load .env
3
+ for (const line of readFileSync('d:/Downloads/modlens-mcp/.env', 'utf8').split('\n')) {
4
+ const m = line.match(/^([^#=]+)=(.*)$/);
5
+ if (m) process.env[m[1].trim()] ??= m[2].trim().replace(/^["']|["']$/g, '');
6
+ }
7
+ import { PrismaClient } from '@prisma/client';
8
+ const db = new PrismaClient();
9
+ const cfFilled = await db.mod.count({ where: { curseforgeId: { not: null } } });
10
+ const mrFilled = await db.mod.count({ where: { modrinthId: { not: null } } });
11
+ console.log(`curseforgeId populated: ${cfFilled} / 821`);
12
+ console.log(`modrinthId populated: ${mrFilled} / 821`);
13
+ await db.$disconnect();
@@ -1,50 +1,50 @@
1
- /**
2
- * Creates the PostgreSQL GIN index for full-text search on mc_source_files.
3
- * Run via: npm run db:setup
4
- *
5
- * CREATE INDEX CONCURRENTLY cannot run inside a Prisma migration transaction,
6
- * so it lives here as a post-migrate step.
7
- */
8
- import { PrismaClient } from "@prisma/client";
9
- import { readFileSync, existsSync } from "fs";
10
- import { join, dirname } from "path";
11
- import { fileURLToPath } from "url";
12
-
13
- const __dirname = dirname(fileURLToPath(import.meta.url));
14
- const envPath = join(__dirname, "..", ".env");
15
- if (existsSync(envPath)) {
16
- for (const line of readFileSync(envPath, "utf8").split("\n")) {
17
- const m = line.match(/^([^#=]+)=(.*)$/);
18
- if (m) process.env[m[1].trim()] ??= m[2].trim().replace(/^["']|["']$/g, "");
19
- }
20
- }
21
-
22
- const prisma = new PrismaClient();
23
-
24
- async function main() {
25
- // Check if the index already exists to avoid a no-op CONCURRENTLY call
26
- const existing = await prisma.$queryRaw`
27
- SELECT 1 FROM pg_indexes
28
- WHERE schemaname = 'public'
29
- AND tablename = 'mc_source_files'
30
- AND indexname = 'mc_source_files_tsv_idx'
31
- LIMIT 1
32
- `;
33
-
34
- if (Array.isArray(existing) && existing.length > 0) {
35
- console.log("FTS index mc_source_files_tsv_idx already exists — skipping.");
36
- return;
37
- }
38
-
39
- console.log("Creating GIN FTS index on mc_source_files(content) — this may take a while...");
40
- // CONCURRENTLY cannot run inside a transaction; Prisma $executeRaw runs outside one here.
41
- await prisma.$executeRawUnsafe(`
42
- CREATE INDEX CONCURRENTLY IF NOT EXISTS mc_source_files_tsv_idx
43
- ON mc_source_files USING GIN (to_tsvector('simple', content))
44
- `);
45
- console.log("Done: mc_source_files_tsv_idx created.");
46
- }
47
-
48
- main()
49
- .catch((err) => { console.error("Failed to create FTS index:", err); process.exit(1); })
50
- .finally(() => prisma.$disconnect());
1
+ /**
2
+ * Creates the PostgreSQL GIN index for full-text search on mc_source_files.
3
+ * Run via: npm run db:setup
4
+ *
5
+ * CREATE INDEX CONCURRENTLY cannot run inside a Prisma migration transaction,
6
+ * so it lives here as a post-migrate step.
7
+ */
8
+ import { PrismaClient } from "@prisma/client";
9
+ import { readFileSync, existsSync } from "fs";
10
+ import { join, dirname } from "path";
11
+ import { fileURLToPath } from "url";
12
+
13
+ const __dirname = dirname(fileURLToPath(import.meta.url));
14
+ const envPath = join(__dirname, "..", ".env");
15
+ if (existsSync(envPath)) {
16
+ for (const line of readFileSync(envPath, "utf8").split("\n")) {
17
+ const m = line.match(/^([^#=]+)=(.*)$/);
18
+ if (m) process.env[m[1].trim()] ??= m[2].trim().replace(/^["']|["']$/g, "");
19
+ }
20
+ }
21
+
22
+ const prisma = new PrismaClient();
23
+
24
+ async function main() {
25
+ // Check if the index already exists to avoid a no-op CONCURRENTLY call
26
+ const existing = await prisma.$queryRaw`
27
+ SELECT 1 FROM pg_indexes
28
+ WHERE schemaname = 'public'
29
+ AND tablename = 'mc_source_files'
30
+ AND indexname = 'mc_source_files_tsv_idx'
31
+ LIMIT 1
32
+ `;
33
+
34
+ if (Array.isArray(existing) && existing.length > 0) {
35
+ console.log("FTS index mc_source_files_tsv_idx already exists — skipping.");
36
+ return;
37
+ }
38
+
39
+ console.log("Creating GIN FTS index on mc_source_files(content) — this may take a while...");
40
+ // CONCURRENTLY cannot run inside a transaction; Prisma $executeRaw runs outside one here.
41
+ await prisma.$executeRawUnsafe(`
42
+ CREATE INDEX CONCURRENTLY IF NOT EXISTS mc_source_files_tsv_idx
43
+ ON mc_source_files USING GIN (to_tsvector('simple', content))
44
+ `);
45
+ console.log("Done: mc_source_files_tsv_idx created.");
46
+ }
47
+
48
+ main()
49
+ .catch((err) => { console.error("Failed to create FTS index:", err); process.exit(1); })
50
+ .finally(() => prisma.$disconnect());