@undefineds.co/xpod 0.3.17 → 0.3.22

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 (99) hide show
  1. package/config/bun.json +57 -11
  2. package/config/cloud.json +14 -12
  3. package/config/local.json +16 -14
  4. package/config/xpod.json +47 -9
  5. package/dist/api/matrix/PodMatrixStore.d.ts +4 -7
  6. package/dist/api/matrix/PodMatrixStore.js +116 -148
  7. package/dist/api/matrix/PodMatrixStore.js.map +1 -1
  8. package/dist/api/matrix/types.d.ts +2 -0
  9. package/dist/api/matrix/types.js.map +1 -1
  10. package/dist/components/components.jsonld +3 -0
  11. package/dist/components/context.jsonld +71 -32
  12. package/dist/http/SubgraphSparqlHttpHandler.d.ts +1 -0
  13. package/dist/http/SubgraphSparqlHttpHandler.js +27 -4
  14. package/dist/http/SubgraphSparqlHttpHandler.js.map +1 -1
  15. package/dist/http/SubgraphSparqlHttpHandler.jsonld +4 -0
  16. package/dist/http/vector/VectorHttpHandler.d.ts +5 -1
  17. package/dist/http/vector/VectorHttpHandler.js +5 -5
  18. package/dist/http/vector/VectorHttpHandler.js.map +1 -1
  19. package/dist/http/vector/VectorHttpHandler.jsonld +40 -28
  20. package/dist/index.d.ts +5 -3
  21. package/dist/index.js +9 -6
  22. package/dist/index.js.map +1 -1
  23. package/dist/runtime/Proxy.d.ts +3 -0
  24. package/dist/runtime/Proxy.js +31 -7
  25. package/dist/runtime/Proxy.js.map +1 -1
  26. package/dist/storage/SparqlUpdateResourceStore.js +94 -33
  27. package/dist/storage/SparqlUpdateResourceStore.js.map +1 -1
  28. package/dist/storage/accessors/MixDataAccessor.d.ts +22 -5
  29. package/dist/storage/accessors/MixDataAccessor.js +376 -61
  30. package/dist/storage/accessors/MixDataAccessor.js.map +1 -1
  31. package/dist/storage/accessors/MixDataAccessor.jsonld +73 -5
  32. package/dist/storage/accessors/QuadstoreSparqlDataAccessor.js +32 -10
  33. package/dist/storage/accessors/QuadstoreSparqlDataAccessor.js.map +1 -1
  34. package/dist/storage/accessors/QuintStoreSparqlDataAccessor.js +28 -6
  35. package/dist/storage/accessors/QuintStoreSparqlDataAccessor.js.map +1 -1
  36. package/dist/storage/accessors/SolidRdfDataAccessor.d.ts +45 -0
  37. package/dist/storage/accessors/SolidRdfDataAccessor.js +277 -0
  38. package/dist/storage/accessors/SolidRdfDataAccessor.js.map +1 -0
  39. package/dist/storage/accessors/SolidRdfDataAccessor.jsonld +161 -0
  40. package/dist/storage/rdf/Rdf3xIndex.d.ts +122 -0
  41. package/dist/storage/rdf/Rdf3xIndex.js +2695 -0
  42. package/dist/storage/rdf/Rdf3xIndex.js.map +1 -0
  43. package/dist/storage/rdf/Rdf3xIndex.jsonld +528 -0
  44. package/dist/storage/rdf/Rdf3xSchema.d.ts +20 -0
  45. package/dist/storage/rdf/Rdf3xSchema.js +65 -0
  46. package/dist/storage/rdf/Rdf3xSchema.js.map +1 -0
  47. package/dist/storage/rdf/RdfLocalQueryEngine.d.ts +10 -4
  48. package/dist/storage/rdf/RdfLocalQueryEngine.js +607 -127
  49. package/dist/storage/rdf/RdfLocalQueryEngine.js.map +1 -1
  50. package/dist/storage/rdf/RdfQuadIndex.d.ts +12 -1
  51. package/dist/storage/rdf/RdfQuadIndex.js +152 -22
  52. package/dist/storage/rdf/RdfQuadIndex.js.map +1 -1
  53. package/dist/storage/rdf/RdfQuadIndex.jsonld +36 -4
  54. package/dist/storage/rdf/RdfSparqlAdapter.d.ts +20 -2
  55. package/dist/storage/rdf/RdfSparqlAdapter.js +364 -40
  56. package/dist/storage/rdf/RdfSparqlAdapter.js.map +1 -1
  57. package/dist/storage/rdf/RdfSparqlAdapter.jsonld +60 -0
  58. package/dist/storage/rdf/RdfTermDictionary.d.ts +8 -0
  59. package/dist/storage/rdf/RdfTermDictionary.js +141 -70
  60. package/dist/storage/rdf/RdfTermDictionary.js.map +1 -1
  61. package/dist/storage/rdf/RdfTermDictionary.jsonld +24 -0
  62. package/dist/storage/rdf/RdfTextIndex.js +10 -3
  63. package/dist/storage/rdf/RdfTextIndex.js.map +1 -1
  64. package/dist/storage/rdf/SolidRdfEngine.d.ts +15 -6
  65. package/dist/storage/rdf/SolidRdfEngine.js +218 -25
  66. package/dist/storage/rdf/SolidRdfEngine.js.map +1 -1
  67. package/dist/storage/rdf/SolidRdfEngine.jsonld +70 -7
  68. package/dist/storage/rdf/SolidRdfSparqlEngine.d.ts +11 -7
  69. package/dist/storage/rdf/SolidRdfSparqlEngine.js +60 -47
  70. package/dist/storage/rdf/SolidRdfSparqlEngine.js.map +1 -1
  71. package/dist/storage/rdf/SolidRdfSparqlEngine.jsonld +9 -5
  72. package/dist/storage/rdf/index.d.ts +2 -2
  73. package/dist/storage/rdf/index.js +3 -3
  74. package/dist/storage/rdf/index.js.map +1 -1
  75. package/dist/storage/rdf/models-benchmark.d.ts +12 -1
  76. package/dist/storage/rdf/models-benchmark.js +549 -32
  77. package/dist/storage/rdf/models-benchmark.js.map +1 -1
  78. package/dist/storage/rdf/types.d.ts +81 -7
  79. package/dist/storage/rdf/types.js.map +1 -1
  80. package/dist/storage/sparql/CompatibilitySparqlEngine.d.ts +36 -0
  81. package/dist/storage/sparql/CompatibilitySparqlEngine.js +96 -0
  82. package/dist/storage/sparql/CompatibilitySparqlEngine.js.map +1 -0
  83. package/dist/storage/sparql/CompatibilitySparqlEngine.jsonld +123 -0
  84. package/dist/storage/sparql/CompatibilitySparqlEngineImpl.d.ts +35 -0
  85. package/dist/storage/sparql/CompatibilitySparqlEngineImpl.js +112 -0
  86. package/dist/storage/sparql/CompatibilitySparqlEngineImpl.js.map +1 -0
  87. package/dist/storage/sparql/SubgraphQueryEngine.d.ts +1 -36
  88. package/dist/storage/sparql/SubgraphQueryEngine.js +2 -115
  89. package/dist/storage/sparql/SubgraphQueryEngine.js.map +1 -1
  90. package/dist/storage/sparql/SubgraphQueryEngine.jsonld +1 -124
  91. package/dist/terminal/AclPermissionService.d.ts +2 -1
  92. package/dist/terminal/AclPermissionService.js +26 -3
  93. package/dist/terminal/AclPermissionService.js.map +1 -1
  94. package/dist/terminal/TerminalSessionManager.js +25 -3
  95. package/dist/terminal/TerminalSessionManager.js.map +1 -1
  96. package/package.json +1 -1
  97. package/dist/storage/rdf/Rdf3xTripleIndex.d.ts +0 -55
  98. package/dist/storage/rdf/Rdf3xTripleIndex.js +0 -1235
  99. package/dist/storage/rdf/Rdf3xTripleIndex.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"RdfTextIndex.js","sourceRoot":"","sources":["../../../src/storage/rdf/RdfTextIndex.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from 'node:crypto';\nimport { existsSync, mkdirSync } from 'node:fs';\nimport { dirname, extname } from 'node:path';\nimport { HeadingChunker } from '../../document/HeadingChunker';\nimport { createSqliteRuntime, type SqliteDatabase, type SqliteStatement } from '../SqliteRuntime';\nimport type {\n RdfTextChunkInput,\n RdfTextChunkRow,\n RdfTextIndexOptions,\n RdfTextSearchOrder,\n RdfTextIndexStats,\n RdfSearchCardinalityEstimate,\n RdfTextSearchOptions,\n RdfTextSearchResult,\n RdfTextSourceInput,\n RdfTextTermDocumentFrequency,\n} from './types';\n\ninterface RdfTextSourceRow {\n id: number;\n source: string;\n workspace: string;\n local_path: string | null;\n content_type: string | null;\n source_version: string | null;\n source_hash: string | null;\n updated_at: string;\n}\n\ninterface RdfTextTermFrequencyRow {\n term: string;\n source_count: number;\n chunk_count: number;\n total_occurrences: number;\n}\n\ninterface TextSearchPredicate {\n sql: string;\n params: unknown[];\n indexChoice: 'text-normalized-scan' | 'text-term-posting';\n}\n\nexport class RdfTextIndex {\n private readonly sqliteRuntime = createSqliteRuntime();\n private db: SqliteDatabase | null = null;\n\n public constructor(private readonly options: RdfTextIndexOptions) {}\n\n public open(): void {\n if (this.db) {\n return;\n }\n\n if (this.options.path !== ':memory:') {\n const dir = dirname(this.options.path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n this.db = this.sqliteRuntime.openDatabase(this.options.path);\n this.initializeSchema();\n }\n\n public close(): void {\n this.db?.close();\n this.db = null;\n }\n\n public clear(): void {\n this.requireDb().exec('DELETE FROM rdf_text_terms; DELETE FROM rdf_text_chunks; DELETE FROM rdf_text_sources;');\n }\n\n public indexText(source: RdfTextSourceInput, text: string, chunks?: RdfTextChunkInput[]): void {\n const db = this.requireDb();\n const indexedChunks = chunks ?? this.chunkText(source, text);\n const sourceId = this.upsertSource({\n ...source,\n sourceHash: source.sourceHash ?? sha256(text),\n });\n const insertChunk = db.prepare(`\n INSERT INTO rdf_text_chunks (\n source_id,\n chunk_key,\n ordinal,\n level,\n heading,\n path,\n content,\n start_offset,\n end_offset,\n normalized_text,\n token_count,\n updated_at\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))\n `);\n const insertTerm = db.prepare(`\n INSERT INTO rdf_text_terms (\n term,\n source_id,\n chunk_id,\n occurrences,\n updated_at\n )\n VALUES (?, ?, ?, ?, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))\n `);\n\n db.transaction(() => {\n db.prepare('DELETE FROM rdf_text_terms WHERE source_id = ?').run(sourceId);\n db.prepare('DELETE FROM rdf_text_chunks WHERE source_id = ?').run(sourceId);\n for (const chunk of indexedChunks) {\n const normalizedText = normalizeText(chunk.content);\n const result = insertChunk.run(\n sourceId,\n chunk.chunkKey,\n chunk.ordinal,\n chunk.level,\n chunk.heading || null,\n JSON.stringify(chunk.path ?? []),\n chunk.content,\n chunk.startOffset,\n chunk.endOffset,\n normalizedText,\n tokenCountNormalized(normalizedText),\n );\n insertTermOccurrences(insertTerm, sourceId, Number(result.lastInsertRowid), normalizedText);\n }\n })();\n }\n\n public deleteSource(source: string): number {\n const db = this.requireDb();\n const row = db.prepare<{ id: number }>('SELECT id FROM rdf_text_sources WHERE source = ?').get(source);\n if (!row) {\n return 0;\n }\n\n return db.transaction(() => {\n db.prepare('DELETE FROM rdf_text_terms WHERE source_id = ?').run(row.id);\n const deletedChunks = db.prepare('DELETE FROM rdf_text_chunks WHERE source_id = ?').run(row.id).changes;\n db.prepare('DELETE FROM rdf_text_sources WHERE id = ?').run(row.id);\n return deletedChunks;\n })();\n }\n\n public search(options: RdfTextSearchOptions): RdfTextSearchResult[] {\n const query = normalizeText(options.query);\n if (!query) {\n return [];\n }\n\n const predicate = buildTextSearchPredicate(query);\n const params: unknown[] = [...predicate.params];\n const conditions = [predicate.sql];\n\n if (options.workspace) {\n conditions.push('source.workspace = ?');\n params.push(options.workspace);\n }\n if (options.source) {\n conditions.push('source.source = ?');\n params.push(options.source);\n }\n if (options.sourcePrefix) {\n conditions.push('source.source >= ? AND source.source < ?');\n params.push(options.sourcePrefix, `${options.sourcePrefix}\\uffff`);\n }\n\n const sql = `\n SELECT\n chunk.id,\n chunk.source_id,\n source.source,\n source.workspace,\n source.local_path,\n source.content_type,\n source.source_version,\n source.source_hash,\n chunk.chunk_key,\n chunk.ordinal,\n chunk.level,\n chunk.heading,\n chunk.path,\n chunk.content,\n chunk.start_offset,\n chunk.end_offset,\n chunk.normalized_text,\n chunk.token_count,\n chunk.updated_at\n FROM rdf_text_chunks chunk\n JOIN rdf_text_sources source ON source.id = chunk.source_id\n WHERE ${conditions.join(' AND ')}\n ORDER BY chunk.source_id ASC, chunk.ordinal ASC\n `;\n\n const rows = this.requireDb().prepare<RdfTextChunkRow>(sql).all(...params);\n const results = rows\n .map((row) => ({ row, score: occurrenceCount(row.normalized_text, query) }))\n .filter((result) => result.score > 0)\n .sort((left, right) => compareTextSearchHits(left, right, options.orderBy))\n .map((result) => this.toSearchResult(result.row, result.score));\n return results.slice(options.offset ?? 0, options.limit === undefined ? undefined : (options.offset ?? 0) + options.limit);\n }\n\n public estimateSearchCardinality(options: RdfTextSearchOptions): RdfSearchCardinalityEstimate {\n const query = normalizeText(options.query);\n if (!query) {\n return {\n rows: 0,\n source: 'text-normalized-scan',\n indexChoice: 'text-normalized-scan',\n };\n }\n\n const predicate = buildTextSearchPredicate(query);\n const params: unknown[] = [...predicate.params];\n const conditions = [predicate.sql];\n\n if (options.workspace) {\n conditions.push('source.workspace = ?');\n params.push(options.workspace);\n }\n if (options.source) {\n conditions.push('source.source = ?');\n params.push(options.source);\n }\n if (options.sourcePrefix) {\n conditions.push('source.source >= ? AND source.source < ?');\n params.push(options.sourcePrefix, `${options.sourcePrefix}\\uffff`);\n }\n\n const rows = this.requireDb().prepare<{ count: number }>(`\n SELECT COUNT(*) AS count\n FROM rdf_text_chunks chunk\n JOIN rdf_text_sources source ON source.id = chunk.source_id\n WHERE ${conditions.join(' AND ')}\n `).get(...params)?.count ?? 0;\n\n return {\n rows: applyResultWindow(rows, options.offset, options.limit),\n source: predicate.indexChoice,\n indexChoice: predicate.indexChoice,\n };\n }\n\n public stats(): RdfTextIndexStats {\n const db = this.requireDb();\n return {\n sourceCount: db.prepare<{ count: number }>('SELECT COUNT(*) AS count FROM rdf_text_sources').get()?.count ?? 0,\n chunkCount: db.prepare<{ count: number }>('SELECT COUNT(*) AS count FROM rdf_text_chunks').get()?.count ?? 0,\n databaseBytes: this.estimateDatabaseBytes(),\n termDocumentFrequency: this.termDocumentFrequency(),\n };\n }\n\n public termDocumentFrequency(limit = 100): RdfTextTermDocumentFrequency[] {\n const rows = this.requireDb().prepare<RdfTextTermFrequencyRow>(`\n SELECT\n term,\n COUNT(DISTINCT source_id) AS source_count,\n COUNT(*) AS chunk_count,\n COALESCE(SUM(occurrences), 0) AS total_occurrences\n FROM rdf_text_terms\n GROUP BY term\n ORDER BY source_count DESC, chunk_count DESC, total_occurrences DESC, term ASC\n LIMIT ?\n `).all(Math.max(0, limit));\n\n return rows\n .map((row) => ({\n term: row.term,\n sourceCount: row.source_count,\n chunkCount: row.chunk_count,\n totalOccurrences: row.total_occurrences,\n }));\n }\n\n private initializeSchema(): void {\n this.requireDb().exec(`\n CREATE TABLE IF NOT EXISTS rdf_text_sources (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n source TEXT NOT NULL UNIQUE,\n workspace TEXT NOT NULL,\n local_path TEXT,\n content_type TEXT,\n source_version TEXT,\n source_hash TEXT,\n updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))\n );\n\n CREATE TABLE IF NOT EXISTS rdf_text_chunks (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n source_id INTEGER NOT NULL,\n chunk_key TEXT NOT NULL,\n ordinal INTEGER NOT NULL,\n level INTEGER NOT NULL,\n heading TEXT,\n path TEXT,\n content TEXT NOT NULL,\n start_offset INTEGER NOT NULL,\n end_offset INTEGER NOT NULL,\n normalized_text TEXT NOT NULL,\n token_count INTEGER NOT NULL,\n updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),\n UNIQUE (source_id, chunk_key),\n FOREIGN KEY (source_id) REFERENCES rdf_text_sources(id)\n );\n\n CREATE TABLE IF NOT EXISTS rdf_text_terms (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n term TEXT NOT NULL,\n source_id INTEGER NOT NULL,\n chunk_id INTEGER NOT NULL,\n occurrences INTEGER NOT NULL,\n updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),\n UNIQUE (term, chunk_id),\n FOREIGN KEY (source_id) REFERENCES rdf_text_sources(id),\n FOREIGN KEY (chunk_id) REFERENCES rdf_text_chunks(id)\n );\n\n CREATE INDEX IF NOT EXISTS rdf_text_sources_workspace ON rdf_text_sources(workspace);\n CREATE INDEX IF NOT EXISTS rdf_text_sources_source ON rdf_text_sources(source);\n CREATE INDEX IF NOT EXISTS rdf_text_chunks_source ON rdf_text_chunks(source_id, ordinal);\n CREATE INDEX IF NOT EXISTS rdf_text_chunks_normalized ON rdf_text_chunks(normalized_text);\n CREATE INDEX IF NOT EXISTS rdf_text_terms_term ON rdf_text_terms(term);\n CREATE INDEX IF NOT EXISTS rdf_text_terms_source_term ON rdf_text_terms(source_id, term);\n CREATE INDEX IF NOT EXISTS rdf_text_terms_chunk ON rdf_text_terms(chunk_id);\n `);\n this.backfillTermPostings();\n }\n\n private backfillTermPostings(): void {\n const db = this.requireDb();\n const rows = db.prepare<{\n id: number;\n source_id: number;\n normalized_text: string;\n }>(`\n SELECT chunk.id, chunk.source_id, chunk.normalized_text\n FROM rdf_text_chunks chunk\n LEFT JOIN rdf_text_terms term ON term.chunk_id = chunk.id\n WHERE term.chunk_id IS NULL AND chunk.normalized_text <> ''\n `).all();\n if (rows.length === 0) {\n return;\n }\n\n const insertTerm = db.prepare(`\n INSERT INTO rdf_text_terms (\n term,\n source_id,\n chunk_id,\n occurrences,\n updated_at\n )\n VALUES (?, ?, ?, ?, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))\n `);\n db.transaction(() => {\n for (const row of rows) {\n insertTermOccurrences(insertTerm, row.source_id, row.id, row.normalized_text);\n }\n })();\n }\n\n private upsertSource(source: RdfTextSourceInput): number {\n const db = this.requireDb();\n db.prepare(`\n INSERT INTO rdf_text_sources (\n source,\n workspace,\n local_path,\n content_type,\n source_version,\n source_hash,\n updated_at\n )\n VALUES (?, ?, ?, ?, ?, ?, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))\n ON CONFLICT (source)\n DO UPDATE SET\n workspace = excluded.workspace,\n local_path = excluded.local_path,\n content_type = excluded.content_type,\n source_version = excluded.source_version,\n source_hash = excluded.source_hash,\n updated_at = excluded.updated_at\n `).run(\n source.source,\n source.workspace,\n source.localPath ?? null,\n source.contentType ?? null,\n source.sourceVersion ?? null,\n source.sourceHash ?? null,\n );\n\n const row = db.prepare<RdfTextSourceRow>('SELECT * FROM rdf_text_sources WHERE source = ?').get(source.source);\n if (!row) {\n throw new Error(`Failed to upsert RDF text source: ${source.source}`);\n }\n return row.id;\n }\n\n private chunkText(source: RdfTextSourceInput, text: string): RdfTextChunkInput[] {\n if (!text) {\n return [];\n }\n if (isMarkdownSource(source)) {\n const chunker = new HeadingChunker();\n return chunker.flatten(chunker.chunk(text))\n .filter((chunk) => chunk.content.trim().length > 0)\n .map((chunk, index) => ({\n chunkKey: deterministicChunkKey(source.source, index),\n ordinal: index,\n level: chunk.level,\n heading: chunk.heading || undefined,\n path: chunk.path,\n content: chunk.content,\n startOffset: chunk.startOffset,\n endOffset: chunk.endOffset,\n }));\n }\n\n return chunkPlainText(source.source, text);\n }\n\n private estimateDatabaseBytes(): number {\n const db = this.requireDb();\n try {\n const pageCount = db.prepare<{ page_count: number }>('PRAGMA page_count').get()?.page_count ?? 0;\n const pageSize = db.prepare<{ page_size: number }>('PRAGMA page_size').get()?.page_size ?? 0;\n return pageCount * pageSize;\n } catch {\n return 0;\n }\n }\n\n private toSearchResult(row: RdfTextChunkRow, score: number): RdfTextSearchResult {\n return {\n source: row.source,\n workspace: row.workspace,\n localPath: row.local_path ?? undefined,\n contentType: row.content_type ?? undefined,\n sourceVersion: row.source_version ?? undefined,\n sourceHash: row.source_hash ?? undefined,\n chunkKey: row.chunk_key,\n ordinal: row.ordinal,\n level: row.level,\n heading: row.heading ?? undefined,\n path: parsePath(row.path),\n content: row.content,\n startOffset: row.start_offset,\n endOffset: row.end_offset,\n score,\n };\n }\n\n private requireDb(): SqliteDatabase {\n if (!this.db) {\n throw new Error('RdfTextIndex is not open');\n }\n return this.db;\n }\n}\n\nfunction isMarkdownSource(source: RdfTextSourceInput): boolean {\n const contentType = source.contentType?.split(';', 1)[0]?.trim().toLowerCase();\n if (contentType === 'text/markdown' || contentType === 'text/x-markdown') {\n return true;\n }\n const path = source.localPath ?? source.source;\n return ['.md', '.markdown', '.mdown'].includes(extname(path).toLowerCase());\n}\n\nfunction chunkPlainText(source: string, text: string): RdfTextChunkInput[] {\n const chunks: RdfTextChunkInput[] = [];\n const paragraphPattern = /[^\\S\\r\\n]*(?:\\r?\\n){2,}[^\\S\\r\\n]*/g;\n let ordinal = 0;\n let start = 0;\n let match: RegExpExecArray | null;\n\n while ((match = paragraphPattern.exec(text)) !== null) {\n const end = match.index;\n ordinal = pushPlainChunk(chunks, source, ordinal, text, start, end);\n start = match.index + match[0].length;\n }\n\n pushPlainChunk(chunks, source, ordinal, text, start, text.length);\n if (chunks.length <= 1 && /\\r?\\n/.test(text)) {\n return chunkLines(source, text);\n }\n return chunks;\n}\n\nfunction chunkLines(source: string, text: string): RdfTextChunkInput[] {\n const chunks: RdfTextChunkInput[] = [];\n const lines = text.split(/\\r?\\n/);\n let offset = 0;\n let ordinal = 0;\n\n for (const line of lines) {\n const start = offset;\n const end = start + line.length;\n ordinal = pushPlainChunk(chunks, source, ordinal, text, start, end);\n offset = end + (text.slice(end, end + 2) === '\\r\\n' ? 2 : 1);\n }\n\n return chunks;\n}\n\nfunction pushPlainChunk(\n chunks: RdfTextChunkInput[],\n source: string,\n ordinal: number,\n text: string,\n start: number,\n end: number,\n): number {\n const content = text.slice(start, end).trim();\n if (!content) {\n return ordinal;\n }\n\n chunks.push({\n chunkKey: deterministicChunkKey(source, ordinal),\n ordinal,\n level: 0,\n path: [],\n content,\n startOffset: start,\n endOffset: end,\n });\n return ordinal + 1;\n}\n\nfunction deterministicChunkKey(source: string, ordinal: number): string {\n return createHash('sha256')\n .update(source)\n .update('\\0')\n .update(String(ordinal))\n .digest('hex')\n .slice(0, 24);\n}\n\nfunction sha256(value: string): string {\n return createHash('sha256').update(value).digest('hex');\n}\n\nfunction normalizeText(value: string): string {\n return value.toLowerCase().replace(/\\s+/g, ' ').trim();\n}\n\nfunction tokenCountNormalized(value: string): number {\n return tokenizeNormalizedText(value).length;\n}\n\nfunction tokenizeNormalizedText(value: string): string[] {\n return value ? value.split(' ').filter(Boolean) : [];\n}\n\nfunction insertTermOccurrences(\n insertTerm: SqliteStatement,\n sourceId: number,\n chunkId: number,\n normalizedText: string,\n): void {\n for (const [term, occurrences] of termOccurrences(normalizedText)) {\n insertTerm.run(term, sourceId, chunkId, occurrences);\n }\n}\n\nfunction termOccurrences(normalizedText: string): Map<string, number> {\n const terms = new Map<string, number>();\n for (const term of tokenizeNormalizedText(normalizedText)) {\n terms.set(term, (terms.get(term) ?? 0) + 1);\n }\n return terms;\n}\n\nfunction buildTextSearchPredicate(query: string): TextSearchPredicate {\n const terms = [...new Set(tokenizeNormalizedText(query))];\n const phraseCondition = \"chunk.normalized_text LIKE ? ESCAPE '\\\\'\";\n const phrasePattern = `%${escapeLikePattern(query)}%`;\n if (terms.length === 0) {\n return {\n sql: phraseCondition,\n params: [phrasePattern],\n indexChoice: 'text-normalized-scan',\n };\n }\n\n return {\n sql: `\n chunk.id IN (\n SELECT candidate.chunk_id\n FROM (\n ${terms.map(() => `\n SELECT term.chunk_id, ? AS query_term\n FROM rdf_text_terms term\n WHERE term.term LIKE ? ESCAPE '\\\\'\n `).join(' UNION ALL ')}\n ) candidate\n GROUP BY candidate.chunk_id\n HAVING COUNT(DISTINCT candidate.query_term) = ?\n )\n AND ${phraseCondition}\n `,\n params: [\n ...terms.flatMap((term) => [term, `%${escapeLikePattern(term)}%`]),\n terms.length,\n phrasePattern,\n ],\n indexChoice: 'text-term-posting',\n };\n}\n\nfunction occurrenceCount(haystack: string, needle: string): number {\n if (!needle) {\n return 0;\n }\n\n let count = 0;\n let offset = 0;\n while (true) {\n const index = haystack.indexOf(needle, offset);\n if (index === -1) {\n break;\n }\n count++;\n offset = index + needle.length;\n }\n return count;\n}\n\nfunction applyResultWindow(rows: number, offset: number | undefined, limit: number | undefined): number {\n const start = Math.max(0, offset ?? 0);\n if (rows <= start) {\n return 0;\n }\n const remaining = rows - start;\n return limit === undefined ? remaining : Math.min(remaining, Math.max(0, limit));\n}\n\nfunction compareTextSearchHits(\n left: { row: RdfTextChunkRow; score: number },\n right: { row: RdfTextChunkRow; score: number },\n orderBy: RdfTextSearchOrder[] | undefined,\n): number {\n const order = orderBy?.length ? orderBy : [{ field: 'score' as const, direction: 'desc' as const }];\n for (const entry of order) {\n const direction = entry.direction === 'desc' ? -1 : 1;\n const comparison = compareTextSearchField(left, right, entry.field);\n if (comparison !== 0) {\n return comparison * direction;\n }\n }\n return left.row.source_id - right.row.source_id || left.row.ordinal - right.row.ordinal;\n}\n\nfunction compareTextSearchField(\n left: { row: RdfTextChunkRow; score: number },\n right: { row: RdfTextChunkRow; score: number },\n field: RdfTextSearchOrder['field'],\n): number {\n switch (field) {\n case 'score':\n return left.score - right.score;\n case 'source':\n return left.row.source.localeCompare(right.row.source);\n case 'localPath':\n return (left.row.local_path ?? '').localeCompare(right.row.local_path ?? '');\n case 'ordinal':\n return left.row.ordinal - right.row.ordinal;\n case 'startOffset':\n return left.row.start_offset - right.row.start_offset;\n case 'endOffset':\n return left.row.end_offset - right.row.end_offset;\n default: {\n const exhaustive: never = field;\n throw new Error(`Unsupported RDF text search order field: ${exhaustive}`);\n }\n }\n}\n\nfunction escapeLikePattern(value: string): string {\n return value.replace(/[\\\\%_]/g, (match) => `\\\\${match}`);\n}\n\nfunction parsePath(value: string | null): string[] {\n if (!value) {\n return [];\n }\n try {\n const parsed = JSON.parse(value);\n return Array.isArray(parsed) ? parsed.filter((item): item is string => typeof item === 'string') : [];\n } catch {\n return [];\n }\n}\n"]}
1
+ {"version":3,"file":"RdfTextIndex.js","sourceRoot":"","sources":["../../../src/storage/rdf/RdfTextIndex.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from 'node:crypto';\nimport { existsSync, mkdirSync } from 'node:fs';\nimport { dirname, extname } from 'node:path';\nimport { HeadingChunker } from '../../document/HeadingChunker';\nimport { createSqliteRuntime, type SqliteDatabase, type SqliteStatement } from '../SqliteRuntime';\nimport type {\n RdfTextChunkInput,\n RdfTextChunkRow,\n RdfTextIndexOptions,\n RdfTextSearchOrder,\n RdfTextIndexStats,\n RdfSearchCardinalityEstimate,\n RdfTextSearchOptions,\n RdfTextSearchResult,\n RdfTextSourceInput,\n RdfTextTermDocumentFrequency,\n} from './types';\n\ninterface RdfTextSourceRow {\n id: number;\n source: string;\n workspace: string;\n local_path: string | null;\n content_type: string | null;\n source_version: string | null;\n source_hash: string | null;\n updated_at: string;\n}\n\ninterface RdfTextTermFrequencyRow {\n term: string;\n source_count: number;\n chunk_count: number;\n total_occurrences: number;\n}\n\ninterface TextSearchPredicate {\n sql: string;\n params: unknown[];\n indexChoice: 'text-normalized-scan' | 'text-term-posting';\n}\n\nconst RDF_TEXT_TERM_MAX_INDEX_LENGTH = 256;\n\nexport class RdfTextIndex {\n private readonly sqliteRuntime = createSqliteRuntime();\n private db: SqliteDatabase | null = null;\n\n public constructor(private readonly options: RdfTextIndexOptions) {}\n\n public open(): void {\n if (this.db) {\n return;\n }\n\n if (this.options.path !== ':memory:') {\n const dir = dirname(this.options.path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n this.db = this.sqliteRuntime.openDatabase(this.options.path);\n this.initializeSchema();\n }\n\n public close(): void {\n this.db?.close();\n this.db = null;\n }\n\n public clear(): void {\n this.requireDb().exec('DELETE FROM rdf_text_terms; DELETE FROM rdf_text_chunks; DELETE FROM rdf_text_sources;');\n }\n\n public indexText(source: RdfTextSourceInput, text: string, chunks?: RdfTextChunkInput[]): void {\n const db = this.requireDb();\n const indexedChunks = chunks ?? this.chunkText(source, text);\n const sourceId = this.upsertSource({\n ...source,\n sourceHash: source.sourceHash ?? sha256(text),\n });\n const insertChunk = db.prepare(`\n INSERT INTO rdf_text_chunks (\n source_id,\n chunk_key,\n ordinal,\n level,\n heading,\n path,\n content,\n start_offset,\n end_offset,\n normalized_text,\n token_count,\n updated_at\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))\n `);\n const insertTerm = db.prepare(`\n INSERT INTO rdf_text_terms (\n term,\n source_id,\n chunk_id,\n occurrences,\n updated_at\n )\n VALUES (?, ?, ?, ?, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))\n `);\n\n db.transaction(() => {\n db.prepare('DELETE FROM rdf_text_terms WHERE source_id = ?').run(sourceId);\n db.prepare('DELETE FROM rdf_text_chunks WHERE source_id = ?').run(sourceId);\n for (const chunk of indexedChunks) {\n const normalizedText = normalizeText(chunk.content);\n const result = insertChunk.run(\n sourceId,\n chunk.chunkKey,\n chunk.ordinal,\n chunk.level,\n chunk.heading || null,\n JSON.stringify(chunk.path ?? []),\n chunk.content,\n chunk.startOffset,\n chunk.endOffset,\n normalizedText,\n tokenCountNormalized(normalizedText),\n );\n insertTermOccurrences(insertTerm, sourceId, Number(result.lastInsertRowid), normalizedText);\n }\n })();\n }\n\n public deleteSource(source: string): number {\n const db = this.requireDb();\n const row = db.prepare<{ id: number }>('SELECT id FROM rdf_text_sources WHERE source = ?').get(source);\n if (!row) {\n return 0;\n }\n\n return db.transaction(() => {\n db.prepare('DELETE FROM rdf_text_terms WHERE source_id = ?').run(row.id);\n const deletedChunks = db.prepare('DELETE FROM rdf_text_chunks WHERE source_id = ?').run(row.id).changes;\n db.prepare('DELETE FROM rdf_text_sources WHERE id = ?').run(row.id);\n return deletedChunks;\n })();\n }\n\n public search(options: RdfTextSearchOptions): RdfTextSearchResult[] {\n const query = normalizeText(options.query);\n if (!query) {\n return [];\n }\n\n const predicate = buildTextSearchPredicate(query);\n const params: unknown[] = [...predicate.params];\n const conditions = [predicate.sql];\n\n if (options.workspace) {\n conditions.push('source.workspace = ?');\n params.push(options.workspace);\n }\n if (options.source) {\n conditions.push('source.source = ?');\n params.push(options.source);\n }\n if (options.sourcePrefix) {\n conditions.push('source.source >= ? AND source.source < ?');\n params.push(options.sourcePrefix, `${options.sourcePrefix}\\uffff`);\n }\n\n const sql = `\n SELECT\n chunk.id,\n chunk.source_id,\n source.source,\n source.workspace,\n source.local_path,\n source.content_type,\n source.source_version,\n source.source_hash,\n chunk.chunk_key,\n chunk.ordinal,\n chunk.level,\n chunk.heading,\n chunk.path,\n chunk.content,\n chunk.start_offset,\n chunk.end_offset,\n chunk.normalized_text,\n chunk.token_count,\n chunk.updated_at\n FROM rdf_text_chunks chunk\n JOIN rdf_text_sources source ON source.id = chunk.source_id\n WHERE ${conditions.join(' AND ')}\n ORDER BY chunk.source_id ASC, chunk.ordinal ASC\n `;\n\n const rows = this.requireDb().prepare<RdfTextChunkRow>(sql).all(...params);\n const results = rows\n .map((row) => ({ row, score: occurrenceCount(row.normalized_text, query) }))\n .filter((result) => result.score > 0)\n .sort((left, right) => compareTextSearchHits(left, right, options.orderBy))\n .map((result) => this.toSearchResult(result.row, result.score));\n return results.slice(options.offset ?? 0, options.limit === undefined ? undefined : (options.offset ?? 0) + options.limit);\n }\n\n public estimateSearchCardinality(options: RdfTextSearchOptions): RdfSearchCardinalityEstimate {\n const query = normalizeText(options.query);\n if (!query) {\n return {\n rows: 0,\n source: 'text-normalized-scan',\n indexChoice: 'text-normalized-scan',\n };\n }\n\n const predicate = buildTextSearchPredicate(query);\n const params: unknown[] = [...predicate.params];\n const conditions = [predicate.sql];\n\n if (options.workspace) {\n conditions.push('source.workspace = ?');\n params.push(options.workspace);\n }\n if (options.source) {\n conditions.push('source.source = ?');\n params.push(options.source);\n }\n if (options.sourcePrefix) {\n conditions.push('source.source >= ? AND source.source < ?');\n params.push(options.sourcePrefix, `${options.sourcePrefix}\\uffff`);\n }\n\n const rows = this.requireDb().prepare<{ count: number }>(`\n SELECT COUNT(*) AS count\n FROM rdf_text_chunks chunk\n JOIN rdf_text_sources source ON source.id = chunk.source_id\n WHERE ${conditions.join(' AND ')}\n `).get(...params)?.count ?? 0;\n\n return {\n rows: applyResultWindow(rows, options.offset, options.limit),\n source: predicate.indexChoice,\n indexChoice: predicate.indexChoice,\n };\n }\n\n public stats(): RdfTextIndexStats {\n const db = this.requireDb();\n return {\n sourceCount: db.prepare<{ count: number }>('SELECT COUNT(*) AS count FROM rdf_text_sources').get()?.count ?? 0,\n chunkCount: db.prepare<{ count: number }>('SELECT COUNT(*) AS count FROM rdf_text_chunks').get()?.count ?? 0,\n databaseBytes: this.estimateDatabaseBytes(),\n termDocumentFrequency: this.termDocumentFrequency(),\n };\n }\n\n public termDocumentFrequency(limit = 100): RdfTextTermDocumentFrequency[] {\n const rows = this.requireDb().prepare<RdfTextTermFrequencyRow>(`\n SELECT\n term,\n COUNT(DISTINCT source_id) AS source_count,\n COUNT(*) AS chunk_count,\n COALESCE(SUM(occurrences), 0) AS total_occurrences\n FROM rdf_text_terms\n GROUP BY term\n ORDER BY source_count DESC, chunk_count DESC, total_occurrences DESC, term ASC\n LIMIT ?\n `).all(Math.max(0, limit));\n\n return rows\n .map((row) => ({\n term: row.term,\n sourceCount: row.source_count,\n chunkCount: row.chunk_count,\n totalOccurrences: row.total_occurrences,\n }));\n }\n\n private initializeSchema(): void {\n this.requireDb().exec(`\n CREATE TABLE IF NOT EXISTS rdf_text_sources (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n source TEXT NOT NULL UNIQUE,\n workspace TEXT NOT NULL,\n local_path TEXT,\n content_type TEXT,\n source_version TEXT,\n source_hash TEXT,\n updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))\n );\n\n CREATE TABLE IF NOT EXISTS rdf_text_chunks (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n source_id INTEGER NOT NULL,\n chunk_key TEXT NOT NULL,\n ordinal INTEGER NOT NULL,\n level INTEGER NOT NULL,\n heading TEXT,\n path TEXT,\n content TEXT NOT NULL,\n start_offset INTEGER NOT NULL,\n end_offset INTEGER NOT NULL,\n normalized_text TEXT NOT NULL,\n token_count INTEGER NOT NULL,\n updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),\n UNIQUE (source_id, chunk_key),\n FOREIGN KEY (source_id) REFERENCES rdf_text_sources(id)\n );\n\n CREATE TABLE IF NOT EXISTS rdf_text_terms (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n term TEXT NOT NULL CHECK (length(term) <= ${RDF_TEXT_TERM_MAX_INDEX_LENGTH}),\n source_id INTEGER NOT NULL,\n chunk_id INTEGER NOT NULL,\n occurrences INTEGER NOT NULL,\n updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),\n UNIQUE (term, chunk_id),\n FOREIGN KEY (source_id) REFERENCES rdf_text_sources(id),\n FOREIGN KEY (chunk_id) REFERENCES rdf_text_chunks(id)\n );\n\n CREATE INDEX IF NOT EXISTS rdf_text_sources_workspace ON rdf_text_sources(workspace);\n CREATE INDEX IF NOT EXISTS rdf_text_sources_source ON rdf_text_sources(source);\n CREATE INDEX IF NOT EXISTS rdf_text_chunks_source ON rdf_text_chunks(source_id, ordinal);\n DELETE FROM rdf_text_terms WHERE length(term) > ${RDF_TEXT_TERM_MAX_INDEX_LENGTH};\n CREATE INDEX IF NOT EXISTS rdf_text_terms_term ON rdf_text_terms(term);\n CREATE INDEX IF NOT EXISTS rdf_text_terms_source_term ON rdf_text_terms(source_id, term);\n CREATE INDEX IF NOT EXISTS rdf_text_terms_chunk ON rdf_text_terms(chunk_id);\n\n DROP INDEX IF EXISTS rdf_text_chunks_normalized;\n `);\n this.backfillTermPostings();\n }\n\n private backfillTermPostings(): void {\n const db = this.requireDb();\n const rows = db.prepare<{\n id: number;\n source_id: number;\n normalized_text: string;\n }>(`\n SELECT chunk.id, chunk.source_id, chunk.normalized_text\n FROM rdf_text_chunks chunk\n LEFT JOIN rdf_text_terms term ON term.chunk_id = chunk.id\n WHERE term.chunk_id IS NULL AND chunk.normalized_text <> ''\n `).all();\n if (rows.length === 0) {\n return;\n }\n\n const insertTerm = db.prepare(`\n INSERT INTO rdf_text_terms (\n term,\n source_id,\n chunk_id,\n occurrences,\n updated_at\n )\n VALUES (?, ?, ?, ?, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))\n `);\n db.transaction(() => {\n for (const row of rows) {\n insertTermOccurrences(insertTerm, row.source_id, row.id, row.normalized_text);\n }\n })();\n }\n\n private upsertSource(source: RdfTextSourceInput): number {\n const db = this.requireDb();\n db.prepare(`\n INSERT INTO rdf_text_sources (\n source,\n workspace,\n local_path,\n content_type,\n source_version,\n source_hash,\n updated_at\n )\n VALUES (?, ?, ?, ?, ?, ?, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))\n ON CONFLICT (source)\n DO UPDATE SET\n workspace = excluded.workspace,\n local_path = excluded.local_path,\n content_type = excluded.content_type,\n source_version = excluded.source_version,\n source_hash = excluded.source_hash,\n updated_at = excluded.updated_at\n `).run(\n source.source,\n source.workspace,\n source.localPath ?? null,\n source.contentType ?? null,\n source.sourceVersion ?? null,\n source.sourceHash ?? null,\n );\n\n const row = db.prepare<RdfTextSourceRow>('SELECT * FROM rdf_text_sources WHERE source = ?').get(source.source);\n if (!row) {\n throw new Error(`Failed to upsert RDF text source: ${source.source}`);\n }\n return row.id;\n }\n\n private chunkText(source: RdfTextSourceInput, text: string): RdfTextChunkInput[] {\n if (!text) {\n return [];\n }\n if (isMarkdownSource(source)) {\n const chunker = new HeadingChunker();\n return chunker.flatten(chunker.chunk(text))\n .filter((chunk) => chunk.content.trim().length > 0)\n .map((chunk, index) => ({\n chunkKey: deterministicChunkKey(source.source, index),\n ordinal: index,\n level: chunk.level,\n heading: chunk.heading || undefined,\n path: chunk.path,\n content: chunk.content,\n startOffset: chunk.startOffset,\n endOffset: chunk.endOffset,\n }));\n }\n\n return chunkPlainText(source.source, text);\n }\n\n private estimateDatabaseBytes(): number {\n const db = this.requireDb();\n try {\n const pageCount = db.prepare<{ page_count: number }>('PRAGMA page_count').get()?.page_count ?? 0;\n const pageSize = db.prepare<{ page_size: number }>('PRAGMA page_size').get()?.page_size ?? 0;\n return pageCount * pageSize;\n } catch {\n return 0;\n }\n }\n\n private toSearchResult(row: RdfTextChunkRow, score: number): RdfTextSearchResult {\n return {\n source: row.source,\n workspace: row.workspace,\n localPath: row.local_path ?? undefined,\n contentType: row.content_type ?? undefined,\n sourceVersion: row.source_version ?? undefined,\n sourceHash: row.source_hash ?? undefined,\n chunkKey: row.chunk_key,\n ordinal: row.ordinal,\n level: row.level,\n heading: row.heading ?? undefined,\n path: parsePath(row.path),\n content: row.content,\n startOffset: row.start_offset,\n endOffset: row.end_offset,\n score,\n };\n }\n\n private requireDb(): SqliteDatabase {\n if (!this.db) {\n throw new Error('RdfTextIndex is not open');\n }\n return this.db;\n }\n}\n\nfunction isMarkdownSource(source: RdfTextSourceInput): boolean {\n const contentType = source.contentType?.split(';', 1)[0]?.trim().toLowerCase();\n if (contentType === 'text/markdown' || contentType === 'text/x-markdown') {\n return true;\n }\n const path = source.localPath ?? source.source;\n return ['.md', '.markdown', '.mdown'].includes(extname(path).toLowerCase());\n}\n\nfunction chunkPlainText(source: string, text: string): RdfTextChunkInput[] {\n const chunks: RdfTextChunkInput[] = [];\n const paragraphPattern = /[^\\S\\r\\n]*(?:\\r?\\n){2,}[^\\S\\r\\n]*/g;\n let ordinal = 0;\n let start = 0;\n let match: RegExpExecArray | null;\n\n while ((match = paragraphPattern.exec(text)) !== null) {\n const end = match.index;\n ordinal = pushPlainChunk(chunks, source, ordinal, text, start, end);\n start = match.index + match[0].length;\n }\n\n pushPlainChunk(chunks, source, ordinal, text, start, text.length);\n if (chunks.length <= 1 && /\\r?\\n/.test(text)) {\n return chunkLines(source, text);\n }\n return chunks;\n}\n\nfunction chunkLines(source: string, text: string): RdfTextChunkInput[] {\n const chunks: RdfTextChunkInput[] = [];\n const lines = text.split(/\\r?\\n/);\n let offset = 0;\n let ordinal = 0;\n\n for (const line of lines) {\n const start = offset;\n const end = start + line.length;\n ordinal = pushPlainChunk(chunks, source, ordinal, text, start, end);\n offset = end + (text.slice(end, end + 2) === '\\r\\n' ? 2 : 1);\n }\n\n return chunks;\n}\n\nfunction pushPlainChunk(\n chunks: RdfTextChunkInput[],\n source: string,\n ordinal: number,\n text: string,\n start: number,\n end: number,\n): number {\n const content = text.slice(start, end).trim();\n if (!content) {\n return ordinal;\n }\n\n chunks.push({\n chunkKey: deterministicChunkKey(source, ordinal),\n ordinal,\n level: 0,\n path: [],\n content,\n startOffset: start,\n endOffset: end,\n });\n return ordinal + 1;\n}\n\nfunction deterministicChunkKey(source: string, ordinal: number): string {\n return createHash('sha256')\n .update(source)\n .update('\\0')\n .update(String(ordinal))\n .digest('hex')\n .slice(0, 24);\n}\n\nfunction sha256(value: string): string {\n return createHash('sha256').update(value).digest('hex');\n}\n\nfunction normalizeText(value: string): string {\n return value.toLowerCase().replace(/\\s+/g, ' ').trim();\n}\n\nfunction tokenCountNormalized(value: string): number {\n return tokenizeNormalizedText(value).length;\n}\n\nfunction tokenizeNormalizedText(value: string): string[] {\n return value ? value.split(' ').filter(Boolean) : [];\n}\n\nfunction insertTermOccurrences(\n insertTerm: SqliteStatement,\n sourceId: number,\n chunkId: number,\n normalizedText: string,\n): void {\n for (const [term, occurrences] of termOccurrences(normalizedText)) {\n if (term.length > RDF_TEXT_TERM_MAX_INDEX_LENGTH) {\n continue;\n }\n insertTerm.run(term, sourceId, chunkId, occurrences);\n }\n}\n\nfunction termOccurrences(normalizedText: string): Map<string, number> {\n const terms = new Map<string, number>();\n for (const term of tokenizeNormalizedText(normalizedText)) {\n terms.set(term, (terms.get(term) ?? 0) + 1);\n }\n return terms;\n}\n\nfunction buildTextSearchPredicate(query: string): TextSearchPredicate {\n const terms = [...new Set(tokenizeNormalizedText(query))]\n .filter((term) => term.length <= RDF_TEXT_TERM_MAX_INDEX_LENGTH);\n const phraseCondition = \"chunk.normalized_text LIKE ? ESCAPE '\\\\'\";\n const phrasePattern = `%${escapeLikePattern(query)}%`;\n if (terms.length === 0) {\n return {\n sql: phraseCondition,\n params: [phrasePattern],\n indexChoice: 'text-normalized-scan',\n };\n }\n\n return {\n sql: `\n chunk.id IN (\n SELECT candidate.chunk_id\n FROM (\n ${terms.map(() => `\n SELECT term.chunk_id, ? AS query_term\n FROM rdf_text_terms term\n WHERE term.term LIKE ? ESCAPE '\\\\'\n `).join(' UNION ALL ')}\n ) candidate\n GROUP BY candidate.chunk_id\n HAVING COUNT(DISTINCT candidate.query_term) = ?\n )\n AND ${phraseCondition}\n `,\n params: [\n ...terms.flatMap((term) => [term, `%${escapeLikePattern(term)}%`]),\n terms.length,\n phrasePattern,\n ],\n indexChoice: 'text-term-posting',\n };\n}\n\nfunction occurrenceCount(haystack: string, needle: string): number {\n if (!needle) {\n return 0;\n }\n\n let count = 0;\n let offset = 0;\n while (true) {\n const index = haystack.indexOf(needle, offset);\n if (index === -1) {\n break;\n }\n count++;\n offset = index + needle.length;\n }\n return count;\n}\n\nfunction applyResultWindow(rows: number, offset: number | undefined, limit: number | undefined): number {\n const start = Math.max(0, offset ?? 0);\n if (rows <= start) {\n return 0;\n }\n const remaining = rows - start;\n return limit === undefined ? remaining : Math.min(remaining, Math.max(0, limit));\n}\n\nfunction compareTextSearchHits(\n left: { row: RdfTextChunkRow; score: number },\n right: { row: RdfTextChunkRow; score: number },\n orderBy: RdfTextSearchOrder[] | undefined,\n): number {\n const order = orderBy?.length ? orderBy : [{ field: 'score' as const, direction: 'desc' as const }];\n for (const entry of order) {\n const direction = entry.direction === 'desc' ? -1 : 1;\n const comparison = compareTextSearchField(left, right, entry.field);\n if (comparison !== 0) {\n return comparison * direction;\n }\n }\n return left.row.source_id - right.row.source_id || left.row.ordinal - right.row.ordinal;\n}\n\nfunction compareTextSearchField(\n left: { row: RdfTextChunkRow; score: number },\n right: { row: RdfTextChunkRow; score: number },\n field: RdfTextSearchOrder['field'],\n): number {\n switch (field) {\n case 'score':\n return left.score - right.score;\n case 'source':\n return left.row.source.localeCompare(right.row.source);\n case 'localPath':\n return (left.row.local_path ?? '').localeCompare(right.row.local_path ?? '');\n case 'ordinal':\n return left.row.ordinal - right.row.ordinal;\n case 'startOffset':\n return left.row.start_offset - right.row.start_offset;\n case 'endOffset':\n return left.row.end_offset - right.row.end_offset;\n default: {\n const exhaustive: never = field;\n throw new Error(`Unsupported RDF text search order field: ${exhaustive}`);\n }\n }\n}\n\nfunction escapeLikePattern(value: string): string {\n return value.replace(/[\\\\%_]/g, (match) => `\\\\${match}`);\n}\n\nfunction parsePath(value: string | null): string[] {\n if (!value) {\n return [];\n }\n try {\n const parsed = JSON.parse(value);\n return Array.isArray(parsed) ? parsed.filter((item): item is string => typeof item === 'string') : [];\n } catch {\n return [];\n }\n}\n"]}
@@ -1,16 +1,17 @@
1
1
  import type { Quad } from '@rdfjs/types';
2
2
  import type { QuintPattern, QuintStore } from '../quint/types';
3
- import type { Rdf3xShadowJoinResult, Rdf3xShadowScanResult, Rdf3xTripleIndexOptions, RdfIndexPutOptions, RdfPatternQuery, RdfQuadJoinOptions, RdfQuadJoinPattern, RdfQuadIndexOptions, RdfQuadIndexScanResult, RdfSourceInput, RdfShadowScanResult, RdfTextChunkInput, RdfTextIndexOptions, RdfTextSearchOptions, RdfTextSearchResult, RdfTextSourceInput, RdfVectorChunkInput, RdfVectorIndexOptions, RdfVectorSearchOptions, RdfVectorSearchResult, RdfVectorSourceInput } from './types';
3
+ import type { Rdf3xShadowJoinResult, Rdf3xShadowScanResult, Rdf3xIndexOptions, RdfDerivedIndexProfile, RdfDerivedIndexRefreshResult, RdfEngineStorageStats, RdfIndexPutOptions, RdfPatternQuery, RdfQuadJoinOptions, RdfQuadJoinPattern, RdfQuadIndexOptions, RdfQuadIndexScanResult, RdfSourceInput, RdfShadowScanResult, RdfTextChunkInput, RdfTextIndexOptions, RdfTextSearchOptions, RdfTextSearchResult, RdfTextSourceInput, RdfVectorChunkInput, RdfVectorIndexOptions, RdfVectorSearchOptions, RdfVectorSearchResult, RdfVectorSourceInput } from './types';
4
4
  import { RdfQuadIndex } from './RdfQuadIndex';
5
- import { Rdf3xTripleIndex } from './Rdf3xTripleIndex';
5
+ import { Rdf3xIndex } from './Rdf3xIndex';
6
6
  import { RdfTextIndex } from './RdfTextIndex';
7
7
  import { RdfVectorIndex } from './RdfVectorIndex';
8
8
  import type { RdfLocalQuery, RdfLocalQueryResult } from './types';
9
9
  export interface SolidRdfEngineOptions {
10
10
  index: RdfQuadIndex | RdfQuadIndexOptions;
11
+ derivedIndexProfile?: RdfDerivedIndexProfile;
11
12
  textIndex?: RdfTextIndex | RdfTextIndexOptions;
12
13
  vectorIndex?: RdfVectorIndex | RdfVectorIndexOptions;
13
- rdf3xIndex?: Rdf3xTripleIndex | Rdf3xTripleIndexOptions;
14
+ rdf3xIndex?: Rdf3xIndex | Rdf3xIndexOptions;
14
15
  rdf3xPrimary?: boolean;
15
16
  compatibilityStore?: QuintStore;
16
17
  autoOpen?: boolean;
@@ -19,7 +20,8 @@ export declare class SolidRdfEngine {
19
20
  readonly index: RdfQuadIndex;
20
21
  readonly textIndex?: RdfTextIndex;
21
22
  readonly vectorIndex?: RdfVectorIndex;
22
- readonly rdf3xIndex?: Rdf3xTripleIndex;
23
+ readonly rdf3xIndex?: Rdf3xIndex;
24
+ readonly derivedIndexProfile: RdfDerivedIndexProfile;
23
25
  private readonly ownsIndex;
24
26
  private readonly ownsTextIndex;
25
27
  private readonly ownsVectorIndex;
@@ -27,8 +29,8 @@ export declare class SolidRdfEngine {
27
29
  private readonly rdf3xPrimary;
28
30
  private readonly compatibilityStore?;
29
31
  private shadowComparator?;
30
- private readonly queryEngine;
31
32
  private rdf3xDirty;
33
+ private rdf3xDataVersion;
32
34
  constructor(options: SolidRdfEngineOptions);
33
35
  open(): void;
34
36
  close(): Promise<void>;
@@ -36,8 +38,13 @@ export declare class SolidRdfEngine {
36
38
  replaceSource(quads: Quad[], source: RdfSourceInput): void;
37
39
  deleteSource(source: string): number;
38
40
  delete(pattern: QuintPattern): number;
41
+ applyDelta(deletes: QuintPattern[], inserts: Quad[], options?: RdfIndexPutOptions): {
42
+ deletedRows: number;
43
+ insertedRows: number;
44
+ };
39
45
  scan(query: RdfPatternQuery): RdfQuadIndexScanResult;
40
46
  query(query: RdfLocalQuery): RdfLocalQueryResult;
47
+ refreshDerivedIndexes(): RdfDerivedIndexRefreshResult;
41
48
  indexTextSource(source: RdfTextSourceInput, text: string, chunks?: RdfTextChunkInput[]): void;
42
49
  deleteTextSource(source: string): number;
43
50
  searchText(options: RdfTextSearchOptions | string): RdfTextSearchResult[];
@@ -48,9 +55,11 @@ export declare class SolidRdfEngine {
48
55
  shadowRdf3xScan(query: RdfPatternQuery): Rdf3xShadowScanResult;
49
56
  shadowRdf3xJoin(patterns: RdfQuadJoinPattern[], options?: RdfQuadJoinOptions): Rdf3xShadowJoinResult;
50
57
  supportsPrimary(query: RdfPatternQuery): boolean;
58
+ storageStats(): RdfEngineStorageStats;
51
59
  private requireTextIndex;
52
60
  private requireVectorIndex;
53
61
  private requireRdf3xIndex;
54
62
  private markRdf3xDirty;
55
- private refreshRdf3xPrimary;
63
+ private isRdf3xPrimaryReady;
64
+ private refreshRdf3xDerivedIndex;
56
65
  }
@@ -4,7 +4,7 @@ exports.SolidRdfEngine = void 0;
4
4
  const n3_1 = require("n3");
5
5
  const types_1 = require("../quint/types");
6
6
  const RdfQuadIndex_1 = require("./RdfQuadIndex");
7
- const Rdf3xTripleIndex_1 = require("./Rdf3xTripleIndex");
7
+ const Rdf3xIndex_1 = require("./Rdf3xIndex");
8
8
  const RdfTextIndex_1 = require("./RdfTextIndex");
9
9
  const RdfVectorIndex_1 = require("./RdfVectorIndex");
10
10
  const RdfShadowComparator_1 = require("./RdfShadowComparator");
@@ -12,6 +12,9 @@ const RdfLocalQueryEngine_1 = require("./RdfLocalQueryEngine");
12
12
  class SolidRdfEngine {
13
13
  constructor(options) {
14
14
  this.rdf3xDirty = true;
15
+ const indexOptions = isRdfQuadIndexOptions(options.index) ? options.index : undefined;
16
+ const rdf3xIndexInput = normalizeOptionalRdf3xIndex(options.rdf3xIndex);
17
+ this.derivedIndexProfile = resolveDerivedIndexProfile(options, indexOptions, rdf3xIndexInput);
15
18
  if (options.index instanceof RdfQuadIndex_1.RdfQuadIndex) {
16
19
  this.index = options.index;
17
20
  this.ownsIndex = false;
@@ -42,23 +45,37 @@ class SolidRdfEngine {
42
45
  else {
43
46
  this.ownsVectorIndex = false;
44
47
  }
45
- if (options.rdf3xIndex instanceof Rdf3xTripleIndex_1.Rdf3xTripleIndex) {
46
- this.rdf3xIndex = options.rdf3xIndex;
48
+ let autoConfiguredRdf3xPrimary = false;
49
+ if (rdf3xIndexInput instanceof Rdf3xIndex_1.Rdf3xIndex) {
50
+ this.rdf3xIndex = rdf3xIndexInput;
47
51
  this.ownsRdf3xIndex = false;
48
52
  }
49
- else if (isRdf3xTripleIndexOptions(options.rdf3xIndex)) {
50
- this.rdf3xIndex = new Rdf3xTripleIndex_1.Rdf3xTripleIndex(options.rdf3xIndex);
53
+ else if (isRdf3xIndexOptions(rdf3xIndexInput)) {
54
+ this.rdf3xIndex = new Rdf3xIndex_1.Rdf3xIndex(rdf3xIndexInput);
51
55
  this.ownsRdf3xIndex = true;
52
56
  }
57
+ else if (shouldAutoConfigureRdf3xIndex(this.derivedIndexProfile, rdf3xIndexInput, indexOptions)) {
58
+ this.rdf3xIndex = new Rdf3xIndex_1.Rdf3xIndex({
59
+ path: indexOptions.path,
60
+ debug: indexOptions.debug,
61
+ });
62
+ this.ownsRdf3xIndex = true;
63
+ autoConfiguredRdf3xPrimary = true;
64
+ }
53
65
  else {
54
66
  this.ownsRdf3xIndex = false;
55
67
  }
68
+ if (this.derivedIndexProfile === 'baseline' && this.rdf3xIndex) {
69
+ throw new Error('SolidRdfEngine derivedIndexProfile=baseline cannot materialize an rdf3xIndex');
70
+ }
71
+ if (this.derivedIndexProfile === 'rdf3x' && !this.rdf3xIndex) {
72
+ throw new Error('SolidRdfEngine derivedIndexProfile=rdf3x requires an rdf3xIndex or a file-backed index option');
73
+ }
56
74
  if (options.rdf3xPrimary && !this.rdf3xIndex) {
57
- throw new Error('SolidRdfEngine rdf3xPrimary requires an rdf3xIndex');
75
+ throw new Error('SolidRdfEngine rdf3xPrimary requires an rdf3xIndex or a file-backed index option');
58
76
  }
59
- this.rdf3xPrimary = Boolean(options.rdf3xPrimary);
77
+ this.rdf3xPrimary = options.rdf3xPrimary ?? autoConfiguredRdf3xPrimary;
60
78
  this.compatibilityStore = options.compatibilityStore;
61
- this.queryEngine = new RdfLocalQueryEngine_1.RdfLocalQueryEngine(this.index, this.textIndex, this.vectorIndex, this.rdf3xPrimary ? this.rdf3xIndex : undefined);
62
79
  if (this.compatibilityStore) {
63
80
  this.shadowComparator = new RdfShadowComparator_1.RdfShadowComparator(this.index, this.compatibilityStore);
64
81
  }
@@ -111,12 +128,32 @@ class SolidRdfEngine {
111
128
  }
112
129
  return changes;
113
130
  }
131
+ applyDelta(deletes, inserts, options) {
132
+ const result = this.index.applyDelta(deletes, inserts, options);
133
+ if (result.deletedRows > 0 || result.insertedRows > 0) {
134
+ this.markRdf3xDirty();
135
+ }
136
+ return result;
137
+ }
114
138
  scan(query) {
115
139
  return this.index.scan(query.pattern, query.options);
116
140
  }
117
141
  query(query) {
118
- this.refreshRdf3xPrimary();
119
- return this.queryEngine.query(query);
142
+ const rdf3xReady = this.isRdf3xPrimaryReady();
143
+ const result = new RdfLocalQueryEngine_1.RdfLocalQueryEngine(this.index, this.textIndex, this.vectorIndex, rdf3xReady ? this.rdf3xIndex : undefined).query(query);
144
+ if (this.rdf3xPrimary && this.rdf3xIndex && !rdf3xReady) {
145
+ result.metrics.plan.unshift('Rdf3xPrimaryStaleFallback');
146
+ }
147
+ return result;
148
+ }
149
+ refreshDerivedIndexes() {
150
+ const factsDataVersion = this.index.dataVersion();
151
+ const rdf3x = this.refreshRdf3xDerivedIndex(factsDataVersion);
152
+ return {
153
+ derivedIndexProfile: this.derivedIndexProfile,
154
+ factsDataVersion,
155
+ ...(rdf3x ? { rdf3x } : {}),
156
+ };
120
157
  }
121
158
  indexTextSource(source, text, chunks) {
122
159
  this.requireTextIndex().indexText(source, text, chunks);
@@ -192,6 +229,28 @@ class SolidRdfEngine {
192
229
  return false;
193
230
  }
194
231
  }
232
+ storageStats() {
233
+ const facts = this.index.stats();
234
+ const rdf3x = this.rdf3xIndex
235
+ ? {
236
+ stats: this.rdf3xIndex.stats(),
237
+ syncedWithFacts: this.rdf3xIndex.isSyncedWithCurrentQuads(),
238
+ }
239
+ : undefined;
240
+ const factsBytes = facts.databaseBytes;
241
+ const derivedBytes = rdf3x?.stats.databaseBytes ?? 0;
242
+ const totalBytes = factsBytes + derivedBytes;
243
+ return {
244
+ derivedIndexProfile: this.derivedIndexProfile,
245
+ facts,
246
+ ...(rdf3x ? { rdf3x } : {}),
247
+ factsBytes,
248
+ derivedBytes,
249
+ totalBytes,
250
+ derivedToFactsRatio: byteRatio(derivedBytes, factsBytes),
251
+ totalToFactsRatio: byteRatio(totalBytes, factsBytes),
252
+ };
253
+ }
195
254
  requireTextIndex() {
196
255
  if (!this.textIndex) {
197
256
  throw new Error('SolidRdfEngine text index is not configured');
@@ -215,12 +274,44 @@ class SolidRdfEngine {
215
274
  this.rdf3xDirty = true;
216
275
  }
217
276
  }
218
- refreshRdf3xPrimary() {
219
- if (!this.rdf3xPrimary || !this.rdf3xDirty) {
220
- return;
277
+ isRdf3xPrimaryReady() {
278
+ return Boolean(this.rdf3xPrimary && this.rdf3xIndex?.isSyncedWithCurrentQuads());
279
+ }
280
+ refreshRdf3xDerivedIndex(factsDataVersion = this.index.dataVersion()) {
281
+ if (!this.rdf3xIndex) {
282
+ return undefined;
283
+ }
284
+ const dataVersion = factsDataVersion;
285
+ if (!this.rdf3xDirty && this.rdf3xDataVersion === dataVersion) {
286
+ return {
287
+ refreshed: false,
288
+ previousFactsDataVersion: dataVersion,
289
+ factsDataVersion: dataVersion,
290
+ syncedWithFacts: true,
291
+ };
292
+ }
293
+ const rdf3xIndex = this.rdf3xIndex;
294
+ const previousFactsDataVersion = rdf3xIndex.factsDataVersion();
295
+ if (previousFactsDataVersion === dataVersion) {
296
+ this.rdf3xDirty = false;
297
+ this.rdf3xDataVersion = dataVersion;
298
+ return {
299
+ refreshed: false,
300
+ previousFactsDataVersion,
301
+ factsDataVersion: dataVersion,
302
+ syncedWithFacts: true,
303
+ };
221
304
  }
222
- this.requireRdf3xIndex().rebuildFromCurrentQuads();
305
+ const rebuild = rdf3xIndex.rebuildFromCurrentQuads();
223
306
  this.rdf3xDirty = false;
307
+ this.rdf3xDataVersion = rebuild.factsDataVersion;
308
+ return {
309
+ refreshed: true,
310
+ previousFactsDataVersion,
311
+ factsDataVersion: rebuild.factsDataVersion,
312
+ syncedWithFacts: rdf3xIndex.factsDataVersion() === this.index.dataVersion(),
313
+ rebuild,
314
+ };
224
315
  }
225
316
  }
226
317
  exports.SolidRdfEngine = SolidRdfEngine;
@@ -230,8 +321,41 @@ function isRdfTextIndexOptions(input) {
230
321
  function isRdfVectorIndexOptions(input) {
231
322
  return input !== undefined && !(input instanceof RdfVectorIndex_1.RdfVectorIndex) && typeof input.path === 'string';
232
323
  }
233
- function isRdf3xTripleIndexOptions(input) {
234
- return input !== undefined && !(input instanceof Rdf3xTripleIndex_1.Rdf3xTripleIndex) && typeof input.path === 'string';
324
+ function isRdf3xIndexOptions(input) {
325
+ return input !== undefined && !(input instanceof Rdf3xIndex_1.Rdf3xIndex) && typeof input.path === 'string';
326
+ }
327
+ function isRdfQuadIndexOptions(input) {
328
+ return !(input instanceof RdfQuadIndex_1.RdfQuadIndex) && typeof input.path === 'string';
329
+ }
330
+ function resolveDerivedIndexProfile(options, indexOptions, rdf3xIndexInput) {
331
+ if (options.derivedIndexProfile) {
332
+ return options.derivedIndexProfile;
333
+ }
334
+ if (rdf3xIndexInput !== undefined || options.rdf3xPrimary === true) {
335
+ return 'rdf3x';
336
+ }
337
+ if (options.rdf3xPrimary === false) {
338
+ return 'baseline';
339
+ }
340
+ return indexOptions !== undefined && indexOptions.path !== ':memory:' ? 'rdf3x' : 'baseline';
341
+ }
342
+ function shouldAutoConfigureRdf3xIndex(profile, rdf3xIndexInput, indexOptions) {
343
+ return profile === 'rdf3x'
344
+ && rdf3xIndexInput === undefined
345
+ && indexOptions !== undefined
346
+ && indexOptions.path !== ':memory:';
347
+ }
348
+ function normalizeOptionalRdf3xIndex(input) {
349
+ if (input instanceof Rdf3xIndex_1.Rdf3xIndex || isRdf3xIndexOptions(input)) {
350
+ return input;
351
+ }
352
+ return undefined;
353
+ }
354
+ function byteRatio(numerator, denominator) {
355
+ if (denominator <= 0) {
356
+ return numerator <= 0 ? 1 : Number.POSITIVE_INFINITY;
357
+ }
358
+ return numerator / denominator;
235
359
  }
236
360
  function canonicalQuadKeys(quads) {
237
361
  return quads.map((quad) => [
@@ -263,12 +387,16 @@ function toRdf3xTriplePattern(pattern) {
263
387
  continue;
264
388
  }
265
389
  if (!(0, types_1.isTerm)(value)) {
266
- if (key === 'graph' && isStartsWithOperator(value)) {
267
- result.graph = { $startsWith: value.$startsWith };
390
+ if (isRdf3xTermInPattern(value)) {
391
+ result[key] = value;
392
+ continue;
393
+ }
394
+ if (isRdf3xTermNotInPattern(value)) {
395
+ result[key] = value;
268
396
  continue;
269
397
  }
270
- if (key === 'object' && isNumericObjectRangeOperator(value)) {
271
- result.object = value;
398
+ if (isRdf3xCompatibleOperatorPattern(key, value)) {
399
+ result[key] = value;
272
400
  continue;
273
401
  }
274
402
  throw new Error(`SolidRdfEngine RDF-3X shadow scan only supports exact ${key} terms${key === 'graph' ? ' or graph $startsWith' : ''}`);
@@ -277,16 +405,81 @@ function toRdf3xTriplePattern(pattern) {
277
405
  }
278
406
  return result;
279
407
  }
280
- function isStartsWithOperator(value) {
408
+ function isRdf3xTermInPattern(value) {
281
409
  return value !== null
282
410
  && typeof value === 'object'
283
- && '$startsWith' in value
284
- && typeof value.$startsWith === 'string';
411
+ && !('termType' in value)
412
+ && Object.keys(value).length === 1
413
+ && Array.isArray(value.$in)
414
+ && (value.$in).length > 0
415
+ && (value.$in).every((entry) => (0, types_1.isTerm)(entry));
285
416
  }
286
- function isNumericObjectRangeOperator(value) {
417
+ function isRdf3xTermNotInPattern(value) {
287
418
  return value !== null
288
419
  && typeof value === 'object'
289
420
  && !('termType' in value)
290
- && ['$gt', '$gte', '$lt', '$lte'].some((operator) => operator in value);
421
+ && Object.keys(value).length === 1
422
+ && Array.isArray(value.$notIn)
423
+ && (value.$notIn).length > 0
424
+ && (value.$notIn).every((entry) => (0, types_1.isTerm)(entry));
425
+ }
426
+ function isRdf3xCompatibleOperatorPattern(key, value) {
427
+ if (value === null || typeof value !== 'object' || 'termType' in value) {
428
+ return false;
429
+ }
430
+ const allowed = new Set([
431
+ '$in',
432
+ '$notIn',
433
+ '$termType',
434
+ '$language',
435
+ '$notLanguage',
436
+ '$langMatches',
437
+ '$datatype',
438
+ '$notDatatype',
439
+ ...(key === 'graph' ? ['$startsWith'] : []),
440
+ ...(key === 'object' ? ['$gt', '$gte', '$lt', '$lte', '$contains', '$endsWith'] : []),
441
+ ]);
442
+ if (Object.keys(value).length === 0 || Object.keys(value).some((operator) => !allowed.has(operator))) {
443
+ return false;
444
+ }
445
+ const operators = value;
446
+ if (operators.$in !== undefined && !isRdf3xTermInPattern({ $in: operators.$in }))
447
+ return false;
448
+ if (operators.$notIn !== undefined && !isRdf3xTermNotInPattern({ $notIn: operators.$notIn }))
449
+ return false;
450
+ if (operators.$startsWith !== undefined && typeof operators.$startsWith !== 'string')
451
+ return false;
452
+ if (operators.$termType !== undefined && !['iri', 'blank', 'literal', 'numeric'].includes(operators.$termType))
453
+ return false;
454
+ for (const languageOperator of ['$language', '$notLanguage', '$langMatches']) {
455
+ if (operators[languageOperator] !== undefined && typeof operators[languageOperator] !== 'string')
456
+ return false;
457
+ }
458
+ for (const datatypeOperator of ['$datatype', '$notDatatype']) {
459
+ const datatype = operators[datatypeOperator];
460
+ if (datatype !== undefined && (!(0, types_1.isTerm)(datatype) || datatype.termType !== 'NamedNode'))
461
+ return false;
462
+ }
463
+ if (key === 'object') {
464
+ for (const rangeOperator of ['$gt', '$gte', '$lt', '$lte']) {
465
+ const rangeValue = operators[rangeOperator];
466
+ if (rangeValue !== undefined && !isRdf3xObjectRangeValue(rangeValue))
467
+ return false;
468
+ }
469
+ for (const textOperator of ['$contains', '$endsWith']) {
470
+ if (operators[textOperator] !== undefined && typeof operators[textOperator] !== 'string')
471
+ return false;
472
+ }
473
+ }
474
+ return true;
475
+ }
476
+ function isRdf3xObjectRangeValue(value) {
477
+ if (typeof value === 'number') {
478
+ return Number.isFinite(value);
479
+ }
480
+ if (typeof value === 'string') {
481
+ return true;
482
+ }
483
+ return (0, types_1.isTerm)(value);
291
484
  }
292
485
  //# sourceMappingURL=SolidRdfEngine.js.map