@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.
- package/config/bun.json +57 -11
- package/config/cloud.json +14 -12
- package/config/local.json +16 -14
- package/config/xpod.json +47 -9
- package/dist/api/matrix/PodMatrixStore.d.ts +4 -7
- package/dist/api/matrix/PodMatrixStore.js +116 -148
- package/dist/api/matrix/PodMatrixStore.js.map +1 -1
- package/dist/api/matrix/types.d.ts +2 -0
- package/dist/api/matrix/types.js.map +1 -1
- package/dist/components/components.jsonld +3 -0
- package/dist/components/context.jsonld +71 -32
- package/dist/http/SubgraphSparqlHttpHandler.d.ts +1 -0
- package/dist/http/SubgraphSparqlHttpHandler.js +27 -4
- package/dist/http/SubgraphSparqlHttpHandler.js.map +1 -1
- package/dist/http/SubgraphSparqlHttpHandler.jsonld +4 -0
- package/dist/http/vector/VectorHttpHandler.d.ts +5 -1
- package/dist/http/vector/VectorHttpHandler.js +5 -5
- package/dist/http/vector/VectorHttpHandler.js.map +1 -1
- package/dist/http/vector/VectorHttpHandler.jsonld +40 -28
- package/dist/index.d.ts +5 -3
- package/dist/index.js +9 -6
- package/dist/index.js.map +1 -1
- package/dist/runtime/Proxy.d.ts +3 -0
- package/dist/runtime/Proxy.js +31 -7
- package/dist/runtime/Proxy.js.map +1 -1
- package/dist/storage/SparqlUpdateResourceStore.js +94 -33
- package/dist/storage/SparqlUpdateResourceStore.js.map +1 -1
- package/dist/storage/accessors/MixDataAccessor.d.ts +22 -5
- package/dist/storage/accessors/MixDataAccessor.js +376 -61
- package/dist/storage/accessors/MixDataAccessor.js.map +1 -1
- package/dist/storage/accessors/MixDataAccessor.jsonld +73 -5
- package/dist/storage/accessors/QuadstoreSparqlDataAccessor.js +32 -10
- package/dist/storage/accessors/QuadstoreSparqlDataAccessor.js.map +1 -1
- package/dist/storage/accessors/QuintStoreSparqlDataAccessor.js +28 -6
- package/dist/storage/accessors/QuintStoreSparqlDataAccessor.js.map +1 -1
- package/dist/storage/accessors/SolidRdfDataAccessor.d.ts +45 -0
- package/dist/storage/accessors/SolidRdfDataAccessor.js +277 -0
- package/dist/storage/accessors/SolidRdfDataAccessor.js.map +1 -0
- package/dist/storage/accessors/SolidRdfDataAccessor.jsonld +161 -0
- package/dist/storage/rdf/Rdf3xIndex.d.ts +122 -0
- package/dist/storage/rdf/Rdf3xIndex.js +2695 -0
- package/dist/storage/rdf/Rdf3xIndex.js.map +1 -0
- package/dist/storage/rdf/Rdf3xIndex.jsonld +528 -0
- package/dist/storage/rdf/Rdf3xSchema.d.ts +20 -0
- package/dist/storage/rdf/Rdf3xSchema.js +65 -0
- package/dist/storage/rdf/Rdf3xSchema.js.map +1 -0
- package/dist/storage/rdf/RdfLocalQueryEngine.d.ts +10 -4
- package/dist/storage/rdf/RdfLocalQueryEngine.js +607 -127
- package/dist/storage/rdf/RdfLocalQueryEngine.js.map +1 -1
- package/dist/storage/rdf/RdfQuadIndex.d.ts +12 -1
- package/dist/storage/rdf/RdfQuadIndex.js +152 -22
- package/dist/storage/rdf/RdfQuadIndex.js.map +1 -1
- package/dist/storage/rdf/RdfQuadIndex.jsonld +36 -4
- package/dist/storage/rdf/RdfSparqlAdapter.d.ts +20 -2
- package/dist/storage/rdf/RdfSparqlAdapter.js +364 -40
- package/dist/storage/rdf/RdfSparqlAdapter.js.map +1 -1
- package/dist/storage/rdf/RdfSparqlAdapter.jsonld +60 -0
- package/dist/storage/rdf/RdfTermDictionary.d.ts +8 -0
- package/dist/storage/rdf/RdfTermDictionary.js +141 -70
- package/dist/storage/rdf/RdfTermDictionary.js.map +1 -1
- package/dist/storage/rdf/RdfTermDictionary.jsonld +24 -0
- package/dist/storage/rdf/RdfTextIndex.js +10 -3
- package/dist/storage/rdf/RdfTextIndex.js.map +1 -1
- package/dist/storage/rdf/SolidRdfEngine.d.ts +15 -6
- package/dist/storage/rdf/SolidRdfEngine.js +218 -25
- package/dist/storage/rdf/SolidRdfEngine.js.map +1 -1
- package/dist/storage/rdf/SolidRdfEngine.jsonld +70 -7
- package/dist/storage/rdf/SolidRdfSparqlEngine.d.ts +11 -7
- package/dist/storage/rdf/SolidRdfSparqlEngine.js +60 -47
- package/dist/storage/rdf/SolidRdfSparqlEngine.js.map +1 -1
- package/dist/storage/rdf/SolidRdfSparqlEngine.jsonld +9 -5
- package/dist/storage/rdf/index.d.ts +2 -2
- package/dist/storage/rdf/index.js +3 -3
- package/dist/storage/rdf/index.js.map +1 -1
- package/dist/storage/rdf/models-benchmark.d.ts +12 -1
- package/dist/storage/rdf/models-benchmark.js +549 -32
- package/dist/storage/rdf/models-benchmark.js.map +1 -1
- package/dist/storage/rdf/types.d.ts +81 -7
- package/dist/storage/rdf/types.js.map +1 -1
- package/dist/storage/sparql/CompatibilitySparqlEngine.d.ts +36 -0
- package/dist/storage/sparql/CompatibilitySparqlEngine.js +96 -0
- package/dist/storage/sparql/CompatibilitySparqlEngine.js.map +1 -0
- package/dist/storage/sparql/CompatibilitySparqlEngine.jsonld +123 -0
- package/dist/storage/sparql/CompatibilitySparqlEngineImpl.d.ts +35 -0
- package/dist/storage/sparql/CompatibilitySparqlEngineImpl.js +112 -0
- package/dist/storage/sparql/CompatibilitySparqlEngineImpl.js.map +1 -0
- package/dist/storage/sparql/SubgraphQueryEngine.d.ts +1 -36
- package/dist/storage/sparql/SubgraphQueryEngine.js +2 -115
- package/dist/storage/sparql/SubgraphQueryEngine.js.map +1 -1
- package/dist/storage/sparql/SubgraphQueryEngine.jsonld +1 -124
- package/dist/terminal/AclPermissionService.d.ts +2 -1
- package/dist/terminal/AclPermissionService.js +26 -3
- package/dist/terminal/AclPermissionService.js.map +1 -1
- package/dist/terminal/TerminalSessionManager.js +25 -3
- package/dist/terminal/TerminalSessionManager.js.map +1 -1
- package/package.json +1 -1
- package/dist/storage/rdf/Rdf3xTripleIndex.d.ts +0 -55
- package/dist/storage/rdf/Rdf3xTripleIndex.js +0 -1235
- 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,
|
|
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 {
|
|
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?:
|
|
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?:
|
|
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
|
|
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
|
|
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
|
-
|
|
46
|
-
|
|
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 (
|
|
50
|
-
this.rdf3xIndex = new
|
|
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 =
|
|
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.
|
|
119
|
-
|
|
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
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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
|
-
|
|
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
|
|
234
|
-
return input !== undefined && !(input instanceof
|
|
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 (
|
|
267
|
-
result
|
|
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
|
|
271
|
-
result
|
|
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
|
|
408
|
+
function isRdf3xTermInPattern(value) {
|
|
281
409
|
return value !== null
|
|
282
410
|
&& typeof value === 'object'
|
|
283
|
-
&& '
|
|
284
|
-
&&
|
|
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
|
|
417
|
+
function isRdf3xTermNotInPattern(value) {
|
|
287
418
|
return value !== null
|
|
288
419
|
&& typeof value === 'object'
|
|
289
420
|
&& !('termType' in value)
|
|
290
|
-
&&
|
|
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
|