@creeperhost/modlens-mcp 1.6.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/README.md +938 -0
- package/dist/access-flags.d.ts +58 -0
- package/dist/access-flags.d.ts.map +1 -0
- package/dist/access-flags.js +79 -0
- package/dist/access-flags.js.map +1 -0
- package/dist/access-flags.test.d.ts +2 -0
- package/dist/access-flags.test.d.ts.map +1 -0
- package/dist/access-flags.test.js +189 -0
- package/dist/access-flags.test.js.map +1 -0
- package/dist/batch-ingest.d.ts +2 -0
- package/dist/batch-ingest.d.ts.map +1 -0
- package/dist/batch-ingest.js +54 -0
- package/dist/batch-ingest.js.map +1 -0
- package/dist/batch-resolve-mixins.d.ts +2 -0
- package/dist/batch-resolve-mixins.d.ts.map +1 -0
- package/dist/batch-resolve-mixins.js +36 -0
- package/dist/batch-resolve-mixins.js.map +1 -0
- package/dist/cache.d.ts +16 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +36 -0
- package/dist/cache.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1318 -0
- package/dist/cli.js.map +1 -0
- package/dist/curseforge.d.ts +53 -0
- package/dist/curseforge.d.ts.map +1 -0
- package/dist/curseforge.js +104 -0
- package/dist/curseforge.js.map +1 -0
- package/dist/db-backend.d.ts +17 -0
- package/dist/db-backend.d.ts.map +1 -0
- package/dist/db-backend.js +40 -0
- package/dist/db-backend.js.map +1 -0
- package/dist/db.d.ts +11 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +55 -0
- package/dist/db.js.map +1 -0
- package/dist/embed-queue.d.ts +12 -0
- package/dist/embed-queue.d.ts.map +1 -0
- package/dist/embed-queue.js +103 -0
- package/dist/embed-queue.js.map +1 -0
- package/dist/embeddings.d.ts +21 -0
- package/dist/embeddings.d.ts.map +1 -0
- package/dist/embeddings.js +55 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/env-path.d.ts +19 -0
- package/dist/env-path.d.ts.map +1 -0
- package/dist/env-path.js +40 -0
- package/dist/env-path.js.map +1 -0
- package/dist/fetch-utils.d.ts +24 -0
- package/dist/fetch-utils.d.ts.map +1 -0
- package/dist/fetch-utils.js +73 -0
- package/dist/fetch-utils.js.map +1 -0
- package/dist/fetch-utils.test.d.ts +2 -0
- package/dist/fetch-utils.test.d.ts.map +1 -0
- package/dist/fetch-utils.test.js +133 -0
- package/dist/fetch-utils.test.js.map +1 -0
- package/dist/generated/sqlite/browser.d.ts +55 -0
- package/dist/generated/sqlite/browser.d.ts.map +1 -0
- package/dist/generated/sqlite/browser.js +18 -0
- package/dist/generated/sqlite/browser.js.map +1 -0
- package/dist/generated/sqlite/client.d.ts +72 -0
- package/dist/generated/sqlite/client.d.ts.map +1 -0
- package/dist/generated/sqlite/client.js +33 -0
- package/dist/generated/sqlite/client.js.map +1 -0
- package/dist/generated/sqlite/commonInputTypes.d.ts +387 -0
- package/dist/generated/sqlite/commonInputTypes.d.ts.map +1 -0
- package/dist/generated/sqlite/commonInputTypes.js +11 -0
- package/dist/generated/sqlite/commonInputTypes.js.map +1 -0
- package/dist/generated/sqlite/enums.d.ts +2 -0
- package/dist/generated/sqlite/enums.d.ts.map +1 -0
- package/dist/generated/sqlite/enums.js +11 -0
- package/dist/generated/sqlite/enums.js.map +1 -0
- package/dist/generated/sqlite/internal/class.d.ts +226 -0
- package/dist/generated/sqlite/internal/class.d.ts.map +1 -0
- package/dist/generated/sqlite/internal/class.js +84 -0
- package/dist/generated/sqlite/internal/class.js.map +1 -0
- package/dist/generated/sqlite/internal/prismaNamespace.d.ts +1344 -0
- package/dist/generated/sqlite/internal/prismaNamespace.d.ts.map +1 -0
- package/dist/generated/sqlite/internal/prismaNamespace.js +220 -0
- package/dist/generated/sqlite/internal/prismaNamespace.js.map +1 -0
- package/dist/generated/sqlite/internal/prismaNamespaceBrowser.d.ts +204 -0
- package/dist/generated/sqlite/internal/prismaNamespaceBrowser.d.ts.map +1 -0
- package/dist/generated/sqlite/internal/prismaNamespaceBrowser.js +191 -0
- package/dist/generated/sqlite/internal/prismaNamespaceBrowser.js.map +1 -0
- package/dist/generated/sqlite/models/DocEntry.d.ts +1223 -0
- package/dist/generated/sqlite/models/DocEntry.d.ts.map +1 -0
- package/dist/generated/sqlite/models/DocEntry.js +2 -0
- package/dist/generated/sqlite/models/DocEntry.js.map +1 -0
- package/dist/generated/sqlite/models/McSourceFile.d.ts +1289 -0
- package/dist/generated/sqlite/models/McSourceFile.d.ts.map +1 -0
- package/dist/generated/sqlite/models/McSourceFile.js +2 -0
- package/dist/generated/sqlite/models/McSourceFile.js.map +1 -0
- package/dist/generated/sqlite/models/McVersion.d.ts +1315 -0
- package/dist/generated/sqlite/models/McVersion.d.ts.map +1 -0
- package/dist/generated/sqlite/models/McVersion.js +2 -0
- package/dist/generated/sqlite/models/McVersion.js.map +1 -0
- package/dist/generated/sqlite/models/McVersionDiff.d.ts +1061 -0
- package/dist/generated/sqlite/models/McVersionDiff.d.ts.map +1 -0
- package/dist/generated/sqlite/models/McVersionDiff.js +2 -0
- package/dist/generated/sqlite/models/McVersionDiff.js.map +1 -0
- package/dist/generated/sqlite/models/Mod.d.ts +2396 -0
- package/dist/generated/sqlite/models/Mod.d.ts.map +1 -0
- package/dist/generated/sqlite/models/Mod.js +2 -0
- package/dist/generated/sqlite/models/Mod.js.map +1 -0
- package/dist/generated/sqlite/models/ModClass.d.ts +1254 -0
- package/dist/generated/sqlite/models/ModClass.d.ts.map +1 -0
- package/dist/generated/sqlite/models/ModClass.js +2 -0
- package/dist/generated/sqlite/models/ModClass.js.map +1 -0
- package/dist/generated/sqlite/models/ModSourceFile.d.ts +1283 -0
- package/dist/generated/sqlite/models/ModSourceFile.d.ts.map +1 -0
- package/dist/generated/sqlite/models/ModSourceFile.js +2 -0
- package/dist/generated/sqlite/models/ModSourceFile.js.map +1 -0
- package/dist/generated/sqlite/models/ModTag.d.ts +1278 -0
- package/dist/generated/sqlite/models/ModTag.d.ts.map +1 -0
- package/dist/generated/sqlite/models/ModTag.js +2 -0
- package/dist/generated/sqlite/models/ModTag.js.map +1 -0
- package/dist/generated/sqlite/models/ModVersionDiff.d.ts +1073 -0
- package/dist/generated/sqlite/models/ModVersionDiff.d.ts.map +1 -0
- package/dist/generated/sqlite/models/ModVersionDiff.js +2 -0
- package/dist/generated/sqlite/models/ModVersionDiff.js.map +1 -0
- package/dist/generated/sqlite/models/Primer.d.ts +1319 -0
- package/dist/generated/sqlite/models/Primer.d.ts.map +1 -0
- package/dist/generated/sqlite/models/Primer.js +2 -0
- package/dist/generated/sqlite/models/Primer.js.map +1 -0
- package/dist/generated/sqlite/models.d.ts +12 -0
- package/dist/generated/sqlite/models.d.ts.map +1 -0
- package/dist/generated/sqlite/models.js +2 -0
- package/dist/generated/sqlite/models.js.map +1 -0
- package/dist/jar.d.ts +7 -0
- package/dist/jar.d.ts.map +1 -0
- package/dist/jar.js +52 -0
- package/dist/jar.js.map +1 -0
- package/dist/java-tools.d.ts +46 -0
- package/dist/java-tools.d.ts.map +1 -0
- package/dist/java-tools.js +263 -0
- package/dist/java-tools.js.map +1 -0
- package/dist/launcher.d.ts +3 -0
- package/dist/launcher.d.ts.map +1 -0
- package/dist/launcher.js +105 -0
- package/dist/launcher.js.map +1 -0
- package/dist/mappings.d.ts +95 -0
- package/dist/mappings.d.ts.map +1 -0
- package/dist/mappings.js +1094 -0
- package/dist/mappings.js.map +1 -0
- package/dist/mappings.test.d.ts +2 -0
- package/dist/mappings.test.d.ts.map +1 -0
- package/dist/mappings.test.js +161 -0
- package/dist/mappings.test.js.map +1 -0
- package/dist/minecraft.d.ts +21 -0
- package/dist/minecraft.d.ts.map +1 -0
- package/dist/minecraft.js +70 -0
- package/dist/minecraft.js.map +1 -0
- package/dist/modpacks-ch.d.ts +224 -0
- package/dist/modpacks-ch.d.ts.map +1 -0
- package/dist/modpacks-ch.js +146 -0
- package/dist/modpacks-ch.js.map +1 -0
- package/dist/modrinth.d.ts +67 -0
- package/dist/modrinth.d.ts.map +1 -0
- package/dist/modrinth.js +88 -0
- package/dist/modrinth.js.map +1 -0
- package/dist/platform-adapter.d.ts +23 -0
- package/dist/platform-adapter.d.ts.map +1 -0
- package/dist/platform-adapter.js +2 -0
- package/dist/platform-adapter.js.map +1 -0
- package/dist/platform.d.ts +47 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +175 -0
- package/dist/platform.js.map +1 -0
- package/dist/processor.d.ts +51 -0
- package/dist/processor.d.ts.map +1 -0
- package/dist/processor.js +655 -0
- package/dist/processor.js.map +1 -0
- package/dist/processor.test.d.ts +2 -0
- package/dist/processor.test.d.ts.map +1 -0
- package/dist/processor.test.js +629 -0
- package/dist/processor.test.js.map +1 -0
- package/dist/repositories/embeddings-sqlite.d.ts +38 -0
- package/dist/repositories/embeddings-sqlite.d.ts.map +1 -0
- package/dist/repositories/embeddings-sqlite.js +208 -0
- package/dist/repositories/embeddings-sqlite.js.map +1 -0
- package/dist/repositories/embeddings.d.ts +40 -0
- package/dist/repositories/embeddings.d.ts.map +1 -0
- package/dist/repositories/embeddings.js +136 -0
- package/dist/repositories/embeddings.js.map +1 -0
- package/dist/repositories/index.d.ts +2 -0
- package/dist/repositories/index.d.ts.map +1 -0
- package/dist/repositories/index.js +15 -0
- package/dist/repositories/index.js.map +1 -0
- package/dist/repositories/mcVersion.d.ts +16 -0
- package/dist/repositories/mcVersion.d.ts.map +1 -0
- package/dist/repositories/mcVersion.js +52 -0
- package/dist/repositories/mcVersion.js.map +1 -0
- package/dist/repositories/mod.d.ts +241 -0
- package/dist/repositories/mod.d.ts.map +1 -0
- package/dist/repositories/mod.js +342 -0
- package/dist/repositories/mod.js.map +1 -0
- package/dist/repositories/packs.d.ts +44 -0
- package/dist/repositories/packs.d.ts.map +1 -0
- package/dist/repositories/packs.js +138 -0
- package/dist/repositories/packs.js.map +1 -0
- package/dist/search-adapter.d.ts +34 -0
- package/dist/search-adapter.d.ts.map +1 -0
- package/dist/search-adapter.js +195 -0
- package/dist/search-adapter.js.map +1 -0
- package/dist/search.d.ts +6 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +54 -0
- package/dist/search.js.map +1 -0
- package/dist/search.test.d.ts +2 -0
- package/dist/search.test.d.ts.map +1 -0
- package/dist/search.test.js +71 -0
- package/dist/search.test.js.map +1 -0
- package/dist/security.d.ts +98 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +446 -0
- package/dist/security.js.map +1 -0
- package/dist/security.test.d.ts +2 -0
- package/dist/security.test.d.ts.map +1 -0
- package/dist/security.test.js +687 -0
- package/dist/security.test.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +1465 -0
- package/dist/server.js.map +1 -0
- package/dist/setup.d.ts +2 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +1113 -0
- package/dist/setup.js.map +1 -0
- package/dist/tools/bytecode.d.ts +129 -0
- package/dist/tools/bytecode.d.ts.map +1 -0
- package/dist/tools/bytecode.js +679 -0
- package/dist/tools/bytecode.js.map +1 -0
- package/dist/tools/catalog.d.ts +54 -0
- package/dist/tools/catalog.d.ts.map +1 -0
- package/dist/tools/catalog.js +249 -0
- package/dist/tools/catalog.js.map +1 -0
- package/dist/tools/compat-check.d.ts +23 -0
- package/dist/tools/compat-check.d.ts.map +1 -0
- package/dist/tools/compat-check.js +250 -0
- package/dist/tools/compat-check.js.map +1 -0
- package/dist/tools/compat-check.test.d.ts +2 -0
- package/dist/tools/compat-check.test.d.ts.map +1 -0
- package/dist/tools/compat-check.test.js +179 -0
- package/dist/tools/compat-check.test.js.map +1 -0
- package/dist/tools/diagnostics.d.ts +10 -0
- package/dist/tools/diagnostics.d.ts.map +1 -0
- package/dist/tools/diagnostics.js +133 -0
- package/dist/tools/diagnostics.js.map +1 -0
- package/dist/tools/diagnostics.test.d.ts +2 -0
- package/dist/tools/diagnostics.test.d.ts.map +1 -0
- package/dist/tools/diagnostics.test.js +168 -0
- package/dist/tools/diagnostics.test.js.map +1 -0
- package/dist/tools/docs.d.ts +19 -0
- package/dist/tools/docs.d.ts.map +1 -0
- package/dist/tools/docs.js +230 -0
- package/dist/tools/docs.js.map +1 -0
- package/dist/tools/embed-registry.d.ts +125 -0
- package/dist/tools/embed-registry.d.ts.map +1 -0
- package/dist/tools/embed-registry.js +560 -0
- package/dist/tools/embed-registry.js.map +1 -0
- package/dist/tools/gradle.d.ts +16 -0
- package/dist/tools/gradle.d.ts.map +1 -0
- package/dist/tools/gradle.js +182 -0
- package/dist/tools/gradle.js.map +1 -0
- package/dist/tools/graphify.d.ts +144 -0
- package/dist/tools/graphify.d.ts.map +1 -0
- package/dist/tools/graphify.js +798 -0
- package/dist/tools/graphify.js.map +1 -0
- package/dist/tools/graphify.test.d.ts +2 -0
- package/dist/tools/graphify.test.d.ts.map +1 -0
- package/dist/tools/graphify.test.js +39 -0
- package/dist/tools/graphify.test.js.map +1 -0
- package/dist/tools/ingest.d.ts +85 -0
- package/dist/tools/ingest.d.ts.map +1 -0
- package/dist/tools/ingest.js +477 -0
- package/dist/tools/ingest.js.map +1 -0
- package/dist/tools/ingest.test.d.ts +2 -0
- package/dist/tools/ingest.test.d.ts.map +1 -0
- package/dist/tools/ingest.test.js +340 -0
- package/dist/tools/ingest.test.js.map +1 -0
- package/dist/tools/kubejs.d.ts +37 -0
- package/dist/tools/kubejs.d.ts.map +1 -0
- package/dist/tools/kubejs.js +245 -0
- package/dist/tools/kubejs.js.map +1 -0
- package/dist/tools/mappings.d.ts +17 -0
- package/dist/tools/mappings.d.ts.map +1 -0
- package/dist/tools/mappings.js +85 -0
- package/dist/tools/mappings.js.map +1 -0
- package/dist/tools/mc-fts.d.ts +101 -0
- package/dist/tools/mc-fts.d.ts.map +1 -0
- package/dist/tools/mc-fts.js +279 -0
- package/dist/tools/mc-fts.js.map +1 -0
- package/dist/tools/mcmeta.d.ts +41 -0
- package/dist/tools/mcmeta.d.ts.map +1 -0
- package/dist/tools/mcmeta.js +365 -0
- package/dist/tools/mcmeta.js.map +1 -0
- package/dist/tools/mixin-scan.d.ts +113 -0
- package/dist/tools/mixin-scan.d.ts.map +1 -0
- package/dist/tools/mixin-scan.js +433 -0
- package/dist/tools/mixin-scan.js.map +1 -0
- package/dist/tools/mod-data.d.ts +83 -0
- package/dist/tools/mod-data.d.ts.map +1 -0
- package/dist/tools/mod-data.js +630 -0
- package/dist/tools/mod-data.js.map +1 -0
- package/dist/tools/mod-tags.d.ts +59 -0
- package/dist/tools/mod-tags.d.ts.map +1 -0
- package/dist/tools/mod-tags.js +279 -0
- package/dist/tools/mod-tags.js.map +1 -0
- package/dist/tools/mod-tags.test.d.ts +2 -0
- package/dist/tools/mod-tags.test.d.ts.map +1 -0
- package/dist/tools/mod-tags.test.js +75 -0
- package/dist/tools/mod-tags.test.js.map +1 -0
- package/dist/tools/modpacks-ch.d.ts +257 -0
- package/dist/tools/modpacks-ch.d.ts.map +1 -0
- package/dist/tools/modpacks-ch.js +516 -0
- package/dist/tools/modpacks-ch.js.map +1 -0
- package/dist/tools/packtools.d.ts +113 -0
- package/dist/tools/packtools.d.ts.map +1 -0
- package/dist/tools/packtools.js +809 -0
- package/dist/tools/packtools.js.map +1 -0
- package/dist/tools/packtools.test.d.ts +2 -0
- package/dist/tools/packtools.test.d.ts.map +1 -0
- package/dist/tools/packtools.test.js +99 -0
- package/dist/tools/packtools.test.js.map +1 -0
- package/dist/tools/platform.d.ts +68 -0
- package/dist/tools/platform.d.ts.map +1 -0
- package/dist/tools/platform.js +452 -0
- package/dist/tools/platform.js.map +1 -0
- package/dist/tools/primers.d.ts +36 -0
- package/dist/tools/primers.d.ts.map +1 -0
- package/dist/tools/primers.js +451 -0
- package/dist/tools/primers.js.map +1 -0
- package/dist/tools/reports.d.ts +19 -0
- package/dist/tools/reports.d.ts.map +1 -0
- package/dist/tools/reports.js +573 -0
- package/dist/tools/reports.js.map +1 -0
- package/dist/tools/source.d.ts +10 -0
- package/dist/tools/source.d.ts.map +1 -0
- package/dist/tools/source.js +101 -0
- package/dist/tools/source.js.map +1 -0
- package/dist/tools/vanilla-data.d.ts +127 -0
- package/dist/tools/vanilla-data.d.ts.map +1 -0
- package/dist/tools/vanilla-data.js +824 -0
- package/dist/tools/vanilla-data.js.map +1 -0
- package/dist/tools/vanilla.d.ts +171 -0
- package/dist/tools/vanilla.d.ts.map +1 -0
- package/dist/tools/vanilla.js +612 -0
- package/dist/tools/vanilla.js.map +1 -0
- package/dist/tools/version-diff.d.ts +113 -0
- package/dist/tools/version-diff.d.ts.map +1 -0
- package/dist/tools/version-diff.js +519 -0
- package/dist/tools/version-diff.js.map +1 -0
- package/dist/tools/version-diff.test.d.ts +2 -0
- package/dist/tools/version-diff.test.d.ts.map +1 -0
- package/dist/tools/version-diff.test.js +102 -0
- package/dist/tools/version-diff.test.js.map +1 -0
- package/dist/validate.d.ts +19 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +54 -0
- package/dist/validate.js.map +1 -0
- package/dist/validate.test.d.ts +2 -0
- package/dist/validate.test.d.ts.map +1 -0
- package/dist/validate.test.js +73 -0
- package/dist/validate.test.js.map +1 -0
- package/package.json +62 -0
- package/prisma/backends/schema.sqlite.prisma +215 -0
- package/prisma/backends/template.db +0 -0
- package/prisma/schema.prisma +303 -0
- package/scripts/backup.mjs +151 -0
- package/scripts/build-template-db.mjs +38 -0
- package/scripts/check-atm10.mjs +27 -0
- package/scripts/check-sync.mjs +13 -0
- package/scripts/create-fts-index.mjs +50 -0
- package/scripts/enable-pgvector.mjs +90 -0
- package/scripts/enable-sqlite-vec.mjs +158 -0
- package/scripts/migrate-backend.mjs +188 -0
- package/scripts/migrate-embed-provenance.mjs +80 -0
- package/scripts/migrate-metadata-source.mjs +62 -0
- package/scripts/migrate-mod-source-files.mjs +67 -0
- package/scripts/post-update.mjs +77 -0
- package/scripts/verify-atm10.mjs +63 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
generator client {
|
|
2
|
+
provider = "prisma-client-js"
|
|
3
|
+
binaryTargets = ["native", "windows", "debian-openssl-3.0.x", "rhel-openssl-3.0.x", "linux-musl-openssl-3.0.x", "darwin", "darwin-arm64"]
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
datasource db {
|
|
7
|
+
provider = "postgresql"
|
|
8
|
+
url = env("DATABASE_URL")
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
model Mod {
|
|
12
|
+
id Int @id @default(autoincrement())
|
|
13
|
+
modId String @map("mod_id")
|
|
14
|
+
displayName String @map("display_name")
|
|
15
|
+
version String
|
|
16
|
+
mcVersion String @map("mc_version")
|
|
17
|
+
loader String // fabric | neoforge | forge | quilt | unknown
|
|
18
|
+
jarPath String @unique @map("jar_path")
|
|
19
|
+
sha256 String?
|
|
20
|
+
murmur2 String?
|
|
21
|
+
sha512 String?
|
|
22
|
+
sourcePath String? @map("source_path")
|
|
23
|
+
decompPath String? @map("decomp_path")
|
|
24
|
+
decompiled Boolean @default(false)
|
|
25
|
+
graphPath String? @map("graph_path")
|
|
26
|
+
modrinthId String? @map("modrinth_id")
|
|
27
|
+
curseforgeId Int? @map("curseforge_id")
|
|
28
|
+
hasMixins Boolean @default(false) @map("has_mixins")
|
|
29
|
+
hasAt Boolean @default(false) @map("has_at")
|
|
30
|
+
hasAw Boolean @default(false) @map("has_aw")
|
|
31
|
+
mixinConfigs String[] @map("mixin_configs")
|
|
32
|
+
mixinTargets Json @default("[]") @map("mixin_targets")
|
|
33
|
+
atEntries Json @default("[]") @map("at_entries")
|
|
34
|
+
awEntries Json @default("[]") @map("aw_entries")
|
|
35
|
+
dependencies Json @default("[]")
|
|
36
|
+
metadata Json @default("{}")
|
|
37
|
+
metadataSource String? @map("metadata_source")
|
|
38
|
+
/// User-defined labels for filtering/grouping, e.g. ["combat", "storage", "compat"]
|
|
39
|
+
tags String[] @default([])
|
|
40
|
+
ingestedAt DateTime @default(now()) @map("ingested_at")
|
|
41
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
42
|
+
|
|
43
|
+
classes ModClass[]
|
|
44
|
+
modTags ModTag[]
|
|
45
|
+
packFiles PackFile[]
|
|
46
|
+
sourceFiles ModSourceFile[]
|
|
47
|
+
|
|
48
|
+
@@unique([modId, version, mcVersion, loader])
|
|
49
|
+
@@index([modId])
|
|
50
|
+
@@index([mcVersion])
|
|
51
|
+
@@index([loader])
|
|
52
|
+
@@index([modrinthId])
|
|
53
|
+
@@index([curseforgeId])
|
|
54
|
+
@@map("mods")
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
model ModClass {
|
|
58
|
+
id Int @id @default(autoincrement())
|
|
59
|
+
modId Int @map("mod_id")
|
|
60
|
+
className String @map("class_name")
|
|
61
|
+
superClass String? @map("super_class")
|
|
62
|
+
interfaces String[]
|
|
63
|
+
accessFlags Int @default(0) @map("access_flags")
|
|
64
|
+
|
|
65
|
+
mod Mod @relation(fields: [modId], references: [id], onDelete: Cascade)
|
|
66
|
+
|
|
67
|
+
@@unique([modId, className])
|
|
68
|
+
@@index([className])
|
|
69
|
+
@@index([modId])
|
|
70
|
+
@@map("mod_classes")
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ── Vanilla Minecraft versions ──────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
model McVersion {
|
|
76
|
+
id Int @id @default(autoincrement())
|
|
77
|
+
versionId String @unique @map("version_id")
|
|
78
|
+
type String @default("release")
|
|
79
|
+
jarPath String? @map("jar_path")
|
|
80
|
+
decompPath String? @map("decomp_path")
|
|
81
|
+
decompiled Boolean @default(false)
|
|
82
|
+
indexed Boolean @default(false)
|
|
83
|
+
releaseTime DateTime @map("release_time")
|
|
84
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
85
|
+
|
|
86
|
+
sourceFiles McSourceFile[]
|
|
87
|
+
|
|
88
|
+
@@map("mc_versions")
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ── Cached AST-level version diffs ──────────────────────────────────────────
|
|
92
|
+
// Keyed by (versionA, versionB, packagesHash) to allow per-package scoping.
|
|
93
|
+
// result stores the full VersionDiffResult JSON. Recomputed on force=true.
|
|
94
|
+
|
|
95
|
+
model McVersionDiff {
|
|
96
|
+
id Int @id @default(autoincrement())
|
|
97
|
+
versionA String @map("version_a")
|
|
98
|
+
versionB String @map("version_b")
|
|
99
|
+
/// SHA-1 prefix of sorted joined packages filter, or "all" when no filter
|
|
100
|
+
packagesHash String @default("all") @map("packages_hash")
|
|
101
|
+
result Json
|
|
102
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
103
|
+
|
|
104
|
+
@@unique([versionA, versionB, packagesHash])
|
|
105
|
+
@@index([versionA, versionB])
|
|
106
|
+
@@map("mc_version_diffs")
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// ── Cached AST-level mod version diffs ────────────────────────────────────────
|
|
110
|
+
// Keyed by (modDbIdA, modDbIdB, packagesHash). Integer IDs are stable per-JAR row.
|
|
111
|
+
// Mirrors McVersionDiff but for mod-to-mod comparisons.
|
|
112
|
+
|
|
113
|
+
model ModVersionDiff {
|
|
114
|
+
id Int @id @default(autoincrement())
|
|
115
|
+
modDbIdA Int @map("mod_db_id_a")
|
|
116
|
+
modDbIdB Int @map("mod_db_id_b")
|
|
117
|
+
/// SHA-1 prefix of sorted joined packages filter, or "all" when no filter
|
|
118
|
+
packagesHash String @default("all") @map("packages_hash")
|
|
119
|
+
result Json
|
|
120
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
121
|
+
|
|
122
|
+
@@unique([modDbIdA, modDbIdB, packagesHash])
|
|
123
|
+
@@index([modDbIdA, modDbIdB])
|
|
124
|
+
@@map("mod_version_diffs")
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ── Mod-shipped tag files ──────────────────────────────────────────────────────
|
|
128
|
+
// One row per data/<namespace>/tags/<registry>/<path>.json file found in a mod JAR.
|
|
129
|
+
// tagPath = "<namespace>:<subpath>" e.g. "c:ores/iron", "forge:storage_blocks"
|
|
130
|
+
// registry = folder name under tags/ e.g. "block", "item", "entity_type"
|
|
131
|
+
// entries = the values array (strings, may include #tag references)
|
|
132
|
+
// replace = true when the file sets "replace": true (overrides other mods' contributions)
|
|
133
|
+
|
|
134
|
+
model ModTag {
|
|
135
|
+
id Int @id @default(autoincrement())
|
|
136
|
+
modId Int @map("mod_id")
|
|
137
|
+
mod Mod @relation(fields: [modId], references: [id], onDelete: Cascade)
|
|
138
|
+
registry String // block | item | entity_type | fluid | worldgen/biome | …
|
|
139
|
+
tagPath String // namespace:subpath, e.g. "c:ores/iron"
|
|
140
|
+
namespace String // owning namespace of the tag file, e.g. "c", "minecraft", "forge"
|
|
141
|
+
entries String[] // values listed in this tag file
|
|
142
|
+
replace Boolean @default(false)
|
|
143
|
+
|
|
144
|
+
@@index([modId])
|
|
145
|
+
@@index([tagPath])
|
|
146
|
+
@@index([registry, tagPath])
|
|
147
|
+
@@index([namespace])
|
|
148
|
+
@@map("mod_tags")
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Stores decompiled vanilla source per class — enables PostgreSQL FTS search.
|
|
152
|
+
// GIN index is created automatically by `npm run db:setup` (scripts/create-fts-index.mjs).
|
|
153
|
+
model McSourceFile {
|
|
154
|
+
id Int @id @default(autoincrement())
|
|
155
|
+
mcVersionId Int @map("mc_version_id")
|
|
156
|
+
className String @map("class_name")
|
|
157
|
+
content String
|
|
158
|
+
/// pgvector embedding — populated by `npm run db:vector` + backfill-embeddings
|
|
159
|
+
embedding Unsupported("vector")? @map("embedding")
|
|
160
|
+
/// Provenance: "local" (user Ollama), "registry" (public download), "community" (user contribution)
|
|
161
|
+
embedSource String? @map("embed_source")
|
|
162
|
+
embedUpdatedAt DateTime? @map("embed_updated_at")
|
|
163
|
+
|
|
164
|
+
mcVersion McVersion @relation(fields: [mcVersionId], references: [id], onDelete: Cascade)
|
|
165
|
+
|
|
166
|
+
@@unique([mcVersionId, className])
|
|
167
|
+
@@index([mcVersionId])
|
|
168
|
+
@@map("mc_source_files")
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ── Documentation entries ────────────────────────────────────────────────────
|
|
172
|
+
|
|
173
|
+
model DocEntry {
|
|
174
|
+
id Int @id @default(autoincrement())
|
|
175
|
+
/// Optional: fully-qualified class name this doc entry describes (slashes or dots).
|
|
176
|
+
className String? @map("class_name")
|
|
177
|
+
title String
|
|
178
|
+
summary String?
|
|
179
|
+
url String
|
|
180
|
+
/// One of: minecraft | neoforge | fabric | forge | quilt | mod | other
|
|
181
|
+
category String @default("minecraft")
|
|
182
|
+
tags String[]
|
|
183
|
+
/// Logical namespace: vanilla | neoforge | fabric | forge | quilt | parchment
|
|
184
|
+
namespace String @default("vanilla")
|
|
185
|
+
/// How it was added: manual | seed | parchment | javadoc
|
|
186
|
+
source String @default("manual")
|
|
187
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
188
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
189
|
+
/// pgvector embedding — populated by `npm run db:vector` + backfill-embeddings
|
|
190
|
+
embedding Unsupported("vector")? @map("embedding")
|
|
191
|
+
|
|
192
|
+
@@index([className])
|
|
193
|
+
@@index([category])
|
|
194
|
+
@@map("doc_entries")
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// ── Mod decompiled source files (for semantic + FTS search) ─────────────────
|
|
198
|
+
// One row per .java file from a decompiled mod JAR.
|
|
199
|
+
// Mirrors mc_source_files but scoped to ingested mods instead of vanilla MC.
|
|
200
|
+
model ModSourceFile {
|
|
201
|
+
id Int @id @default(autoincrement())
|
|
202
|
+
modId Int @map("mod_id")
|
|
203
|
+
className String @map("class_name")
|
|
204
|
+
content String
|
|
205
|
+
/// pgvector embedding — populated by mod index_semantic action
|
|
206
|
+
embedding Unsupported("vector")? @map("embedding")
|
|
207
|
+
/// Provenance: "local" (user Ollama), "registry" (public download), "community" (user contribution)
|
|
208
|
+
embedSource String? @map("embed_source")
|
|
209
|
+
embedUpdatedAt DateTime? @map("embed_updated_at")
|
|
210
|
+
|
|
211
|
+
mod Mod @relation(fields: [modId], references: [id], onDelete: Cascade)
|
|
212
|
+
|
|
213
|
+
@@unique([modId, className])
|
|
214
|
+
@@index([modId])
|
|
215
|
+
@@map("mod_source_files")
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// ── Version migration primers ──────────────────────────────────────────────────────────
|
|
219
|
+
// Documents that guide modders through upgrading mods from one MC/loader version to another.
|
|
220
|
+
// fromDataVersion / toDataVersion store the integer data_version from mcmeta for numeric range queries.
|
|
221
|
+
|
|
222
|
+
model Primer {
|
|
223
|
+
id Int @id @default(autoincrement())
|
|
224
|
+
/// Minecraft version this primer starts at, e.g. "1.20.4"
|
|
225
|
+
fromVersion String @map("from_version")
|
|
226
|
+
/// Minecraft version this primer targets, e.g. "1.21.1"
|
|
227
|
+
toVersion String @map("to_version")
|
|
228
|
+
/// Numeric data_version from mcmeta for ordering/range queries
|
|
229
|
+
fromDataVersion Int? @map("from_data_version")
|
|
230
|
+
toDataVersion Int? @map("to_data_version")
|
|
231
|
+
/// Mod loader: neoforge | forge | fabric | quilt | vanilla | other
|
|
232
|
+
modloader String @default("neoforge")
|
|
233
|
+
title String
|
|
234
|
+
summary String?
|
|
235
|
+
url String @unique
|
|
236
|
+
/// Full text of the primer (optional — populated by ingest with fetch=true)
|
|
237
|
+
content String?
|
|
238
|
+
tags String[]
|
|
239
|
+
source String @default("manual")
|
|
240
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
241
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
242
|
+
/// pgvector embedding — populated by `npm run db:vector` + backfill-embeddings
|
|
243
|
+
embedding Unsupported("vector")? @map("embedding")
|
|
244
|
+
|
|
245
|
+
@@index([fromVersion, toVersion])
|
|
246
|
+
@@index([fromDataVersion, toDataVersion])
|
|
247
|
+
@@index([modloader])
|
|
248
|
+
@@map("primers")
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// ── Modpack version tracking ──────────────────────────────────────────────────
|
|
252
|
+
// One row per (namespace, packId, versionId) that has been synced or inspected.
|
|
253
|
+
|
|
254
|
+
model PackVersion {
|
|
255
|
+
id Int @id @default(autoincrement())
|
|
256
|
+
/// "ftb" | "curseforge"
|
|
257
|
+
namespace String
|
|
258
|
+
packId Int @map("pack_id")
|
|
259
|
+
versionId Int @map("version_id")
|
|
260
|
+
packName String @map("pack_name")
|
|
261
|
+
versionName String @map("version_name")
|
|
262
|
+
mcVersion String? @map("mc_version")
|
|
263
|
+
modloader String?
|
|
264
|
+
syncedAt DateTime @default(now()) @map("synced_at")
|
|
265
|
+
updatedAt DateTime @updatedAt @map("updated_at")
|
|
266
|
+
|
|
267
|
+
files PackFile[]
|
|
268
|
+
|
|
269
|
+
@@unique([namespace, packId, versionId])
|
|
270
|
+
@@index([namespace, packId])
|
|
271
|
+
@@map("pack_versions")
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// One row per file listed in a pack version manifest.
|
|
275
|
+
// Covers mods, configs, scripts, resource packs, and cf-extract overrides ZIPs.
|
|
276
|
+
// modId is set when the file was ingested as a Mod in this database.
|
|
277
|
+
|
|
278
|
+
model PackFile {
|
|
279
|
+
id Int @id @default(autoincrement())
|
|
280
|
+
packVersionId Int @map("pack_version_id")
|
|
281
|
+
packVersion PackVersion @relation(fields: [packVersionId], references: [id], onDelete: Cascade)
|
|
282
|
+
/// file.id from the modpacks.ch manifest
|
|
283
|
+
manifestFileId Int? @map("manifest_file_id")
|
|
284
|
+
/// "mod" | "resource" | "config" | "script" | "cf-extract" | "override" | etc.
|
|
285
|
+
fileType String @map("file_type")
|
|
286
|
+
fileName String @map("file_name")
|
|
287
|
+
/// Destination path relative to the pack root (from manifest file.path)
|
|
288
|
+
filePath String? @map("file_path")
|
|
289
|
+
cfProject Int? @map("cf_project")
|
|
290
|
+
cfFile Int? @map("cf_file")
|
|
291
|
+
sha1 String?
|
|
292
|
+
/// "ingested" | "already_ingested" | "downloaded_zip" | "error" | "skipped" | "not_synced"
|
|
293
|
+
status String @default("not_synced")
|
|
294
|
+
/// Set when this file was successfully ingested as a Mod row.
|
|
295
|
+
modId Int? @map("mod_id")
|
|
296
|
+
mod Mod? @relation(fields: [modId], references: [id], onDelete: SetNull)
|
|
297
|
+
|
|
298
|
+
@@unique([packVersionId, manifestFileId])
|
|
299
|
+
@@index([packVersionId])
|
|
300
|
+
@@index([modId])
|
|
301
|
+
@@index([cfProject])
|
|
302
|
+
@@map("pack_files")
|
|
303
|
+
}
|
|
@@ -0,0 +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
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the prebuilt SQLite template database that ships in the package.
|
|
3
|
+
*
|
|
4
|
+
* On first run as an installed package (npx / global), the launcher copies this
|
|
5
|
+
* template to `~/.modlens/data/modlens.db` so the embedded SQLite backend works
|
|
6
|
+
* with zero configuration — no `prisma db push`, no Prisma CLI, no engines, and
|
|
7
|
+
* no interactive setup required at runtime.
|
|
8
|
+
*
|
|
9
|
+
* The template is a build artifact (gitignored) regenerated on every `build`,
|
|
10
|
+
* so its schema is always in sync with `prisma/backends/schema.sqlite.prisma`.
|
|
11
|
+
*/
|
|
12
|
+
import { execSync } from "child_process";
|
|
13
|
+
import { existsSync, rmSync } from "fs";
|
|
14
|
+
import { join, dirname } from "path";
|
|
15
|
+
import { fileURLToPath } from "url";
|
|
16
|
+
|
|
17
|
+
const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
18
|
+
const dbFile = join(ROOT, "prisma", "backends", "template.db");
|
|
19
|
+
|
|
20
|
+
// Start from a clean slate so the template never carries stale tables/rows.
|
|
21
|
+
if (existsSync(dbFile)) rmSync(dbFile);
|
|
22
|
+
|
|
23
|
+
// Prisma resolves a relative `file:` URL relative to the schema file's directory
|
|
24
|
+
// (prisma/backends/), so `file:./template.db` lands the db next to the schema.
|
|
25
|
+
execSync(
|
|
26
|
+
"npx prisma db push --schema prisma/backends/schema.sqlite.prisma --skip-generate --accept-data-loss",
|
|
27
|
+
{
|
|
28
|
+
cwd: ROOT,
|
|
29
|
+
stdio: "inherit",
|
|
30
|
+
env: { ...process.env, DATABASE_URL: "file:./template.db" },
|
|
31
|
+
},
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
if (!existsSync(dbFile)) {
|
|
35
|
+
console.error(`[build-template-db] expected template at ${dbFile} but it was not created.`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
console.log(`[build-template-db] built template database at ${dbFile}`);
|
|
@@ -0,0 +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();
|
|
@@ -0,0 +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();
|
|
@@ -0,0 +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());
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enables the pgvector extension and adds embedding columns to the three tables
|
|
3
|
+
* that support semantic search: doc_entries, primers, mc_source_files.
|
|
4
|
+
*
|
|
5
|
+
* Run once after `docker compose up`:
|
|
6
|
+
* npm run db:vector
|
|
7
|
+
*
|
|
8
|
+
* Safe to re-run — all statements use IF NOT EXISTS / IF NOT EXISTS.
|
|
9
|
+
*/
|
|
10
|
+
import { PrismaClient } from "@prisma/client";
|
|
11
|
+
import { readFileSync, existsSync } from "fs";
|
|
12
|
+
import { join, dirname } from "path";
|
|
13
|
+
import { fileURLToPath } from "url";
|
|
14
|
+
|
|
15
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const envPath = join(__dirname, "..", ".env");
|
|
17
|
+
if (existsSync(envPath)) {
|
|
18
|
+
for (const line of readFileSync(envPath, "utf8").split("\n")) {
|
|
19
|
+
const m = line.match(/^([^#=]+)=(.*)$/);
|
|
20
|
+
if (m) process.env[m[1].trim()] ??= m[2].trim().replace(/^["']|["']$/g, "");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const prisma = new PrismaClient();
|
|
25
|
+
|
|
26
|
+
async function main() {
|
|
27
|
+
// 1. Enable extension
|
|
28
|
+
await prisma.$executeRawUnsafe(`CREATE EXTENSION IF NOT EXISTS vector`);
|
|
29
|
+
console.log("✓ pgvector extension enabled");
|
|
30
|
+
|
|
31
|
+
// 2. Add or resize embedding columns
|
|
32
|
+
const dim = parseInt(process.env.OLLAMA_EMBED_DIM ?? "768", 10);
|
|
33
|
+
for (const table of ["doc_entries", "primers", "mc_source_files", "mod_source_files"]) {
|
|
34
|
+
// Check existing column dimension (atttypmod = dimension for pgvector)
|
|
35
|
+
const rows = await prisma.$queryRawUnsafe(
|
|
36
|
+
`SELECT atttypmod AS dim FROM pg_attribute
|
|
37
|
+
JOIN pg_class ON pg_attribute.attrelid = pg_class.oid
|
|
38
|
+
WHERE pg_class.relname = $1 AND pg_attribute.attname = 'embedding' AND pg_attribute.attnum > 0`,
|
|
39
|
+
table
|
|
40
|
+
);
|
|
41
|
+
const currentDim = Array.isArray(rows) && rows.length > 0 ? Number(rows[0].dim) : null;
|
|
42
|
+
|
|
43
|
+
if (currentDim === null) {
|
|
44
|
+
await prisma.$executeRawUnsafe(
|
|
45
|
+
`ALTER TABLE ${table} ADD COLUMN embedding vector(${dim})`
|
|
46
|
+
);
|
|
47
|
+
console.log(`✓ ${table}.embedding added (dim=${dim})`);
|
|
48
|
+
} else if (currentDim !== dim) {
|
|
49
|
+
// Drop the HNSW index first — ALTER TYPE fails if index exists
|
|
50
|
+
const idxName = `${table}_embedding_idx`;
|
|
51
|
+
await prisma.$executeRawUnsafe(`DROP INDEX IF EXISTS ${idxName}`);
|
|
52
|
+
await prisma.$executeRawUnsafe(
|
|
53
|
+
`ALTER TABLE ${table} ALTER COLUMN embedding TYPE vector(${dim})`
|
|
54
|
+
);
|
|
55
|
+
console.log(`✓ ${table}.embedding resized ${currentDim} → ${dim}`);
|
|
56
|
+
} else {
|
|
57
|
+
console.log(` ${table}.embedding already vector(${dim}) — skipping`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 3. HNSW indexes for fast approximate nearest-neighbour
|
|
62
|
+
const indexes = [
|
|
63
|
+
["doc_entries_embedding_idx", "doc_entries"],
|
|
64
|
+
["primers_embedding_idx", "primers"],
|
|
65
|
+
["mc_source_files_embedding_idx", "mc_source_files"],
|
|
66
|
+
["mod_source_files_embedding_idx","mod_source_files"],
|
|
67
|
+
];
|
|
68
|
+
for (const [idxName, table] of indexes) {
|
|
69
|
+
const existing = await prisma.$queryRawUnsafe(
|
|
70
|
+
`SELECT 1 FROM pg_indexes WHERE schemaname='public' AND indexname=$1 LIMIT 1`,
|
|
71
|
+
idxName,
|
|
72
|
+
);
|
|
73
|
+
if (Array.isArray(existing) && existing.length > 0) {
|
|
74
|
+
console.log(` (index ${idxName} already exists — skipping)`);
|
|
75
|
+
} else {
|
|
76
|
+
console.log(` Creating HNSW index ${idxName}…`);
|
|
77
|
+
await prisma.$executeRawUnsafe(
|
|
78
|
+
`CREATE INDEX ${idxName} ON ${table} USING hnsw (embedding vector_cosine_ops)`
|
|
79
|
+
);
|
|
80
|
+
console.log(`✓ ${idxName} created`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
console.log("\nDone — semantic search is ready.");
|
|
85
|
+
console.log("Next: set OLLAMA_URL in .env and run node dist/cli.js backfill-embeddings --type docs");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
main()
|
|
89
|
+
.catch((err) => { console.error("Failed:", err); process.exit(1); })
|
|
90
|
+
.finally(() => prisma.$disconnect());
|