import { entityKind } from 'drizzle-orm'; import { SQL } from 'drizzle-orm'; import { PodTable } from './schema'; import { QueryCondition } from './query-conditions'; import { ASTToSPARQLConverter, type SPARQLQuery } from './ast-to-sparql'; import { ComunicaSPARQLExecutor } from './sparql-executor'; import { TypeIndexManager, TypeIndexEntry, TypeIndexConfig, DiscoveredTable } from './typeindex-manager'; import { DataDiscovery } from './discovery'; import type { ExecutionStrategy } from './execution'; import type { TableResourceDescriptor } from './execution/pod-executor-types'; import { UriResolverImpl } from './uri'; import type { SelectQueryPlan } from './select-plan'; import type { InsertQueryPlan, UpdateQueryPlan, DeleteQueryPlan } from './pod-session'; import { ShapeManager } from './shape'; import type { ResourceResolver } from './resource-resolver'; import type { SPARQLQueryEngineFactory } from './sparql-engine'; export interface SolidAuthSession { info: { isLoggedIn: boolean; webId?: string; sessionId?: string; clientId?: string; client_id?: string; podUrl?: string; }; fetch: typeof fetch; login?: (options?: Record) => Promise; logout?: () => Promise; } import type { ChannelType } from './notifications'; export interface PodDialectConfig { session: SolidAuthSession; typeIndex?: TypeIndexConfig; createQueryEngine?: SPARQLQueryEngineFactory; /** Explicit Pod base URL for IdP/SP split deployments. */ podUrl?: string; disableInteropDiscovery?: boolean; /** * Controls implicit LDP container/resource probes before ORM operations. * * - best-effort: register schema metadata, but defer LDP preparation to write time. This is the default. * - strict: fail when preparation fails. * - off: do not preflight resource preparation; let direct LDP reads/writes surface real failures. */ resourcePreparation?: 'strict' | 'best-effort' | 'off'; /** * 通知通道偏好顺序,默认 ['streaming-http', 'websocket'] * 会根据服务器支持的通道自动选择第一个匹配的 */ preferredChannels?: ChannelType[]; /** * Storage 缓存过期时间(毫秒),默认 5 分钟 * 用于 IdP-SP 分离场景,控制从 profile 重新读取 pim:storage 的频率 */ storageTTL?: number; /** * 启用 debug 模式,输出查询信息 */ debug?: boolean; } export interface PodOperation { type: 'select' | 'insert' | 'update' | 'delete'; table: PodTable; sql?: SQL; data?: unknown; where?: Record | QueryCondition; select?: Record; values?: unknown | unknown[]; plan?: SelectQueryPlan | InsertQueryPlan | UpdateQueryPlan | DeleteQueryPlan; joins?: Array<{ type: 'leftJoin' | 'rightJoin' | 'innerJoin' | 'fullJoin' | 'crossJoin'; table: PodTable; condition: unknown; }>; limit?: number; offset?: number; orderBy?: Array<{ column: string; direction: 'asc' | 'desc'; }>; distinct?: boolean; } export declare class PodDialect { static readonly [entityKind] = "PodDialect"; private runtime; private services; private podUrl; private webId; private sparqlConverter; private sparqlExecutor; private ldpExecutor; private strategyFactory; private executor; private typeIndexManager; private discovery; private shapeManager; private resolverFactory; private uriResolver; config: PodDialectConfig; private registeredTables; private preparedContainers; private preparedResources; private shortIdSubjectIndex; private debugLogger; private currentTableRegistry; private currentTableNameRegistry; constructor(config: PodDialectConfig); /** * Get the ResourceResolver for a table */ getResolver(table: PodTable): ResourceResolver; private buildShortIdSubjectIndexKey; registerResourceSubject(table: PodTable, subject: string): void; unregisterResourceSubject(table: PodTable, subject: string): void; lookupIndexedResourceSubject(table: PodTable, id: string): string | null; /** * Get the ExecutionStrategy for a table */ getStrategy(table: PodTable): ExecutionStrategy; /** * 获取 ShapeManager 实例 */ getShapeManager(): ShapeManager; /** * 获取 UriResolver 实例 */ getUriResolver(): UriResolverImpl; /** * 获取 DataDiscovery 实例 */ getDiscovery(): DataDiscovery; /** * 设置 schema(表注册表) * 用于 URI 引用字段的自动补全 * * 构建两个注册表: * - tableRegistry: rdfClass -> tables[](同一 class 可能对应多个表) * - tableNameRegistry: tableName -> table(用于明确指定表名时查找) */ setSchema(schema: Record): void; private refreshBaseUrlFromRuntime; private findSubjectsForCondition; connect(): Promise; disconnect(): Promise; isConnected(): boolean; private extractUserPathFromWebId; resolveTableResource(table: PodTable): TableResourceDescriptor; /** * Resolve LDP container/resource URLs for a table. * * Always returns the physical LDP storage location, regardless of whether * the table has a sparqlEndpoint configured. SPARQL strategy will resolve * the endpoint URL separately via table.getSparqlEndpoint(). */ private resolveTableUrls; private resolveLdpResource; private resourceExists; private normalizeResourceUrl; private normalizeContainerKey; private normalizeResourceKey; private isStorageRootContainer; private markContainerPrepared; private markResourcePrepared; private isAbsoluteUrl; private resolveAbsoluteUrl; private ensureResourceExists; executeOnResource(resourceUrl: string, sparqlQuery: SPARQLQuery, descriptor?: TableResourceDescriptor): Promise; /** * Get the appropriate fetch function for a SPARQL endpoint * - Same-origin endpoints (e.g., CSS SPARQL sidecar): use authenticated session.fetch * - Cross-origin endpoints: use unauthenticated fetch (standard SPARQL endpoint behavior) */ private getFetchForEndpoint; private executeOnSparqlEndpoint; /** * 确保表有 resourcePath,如果没有则从 TypeIndex 自动发现 * 如果设置了 typeIndex,优先使用发现的位置(覆盖配置的 base) */ private ensureTableResourcePath; /** * 尝试自动发现 SPARQL endpoint * 按约定:${base}/-/sparql * 使用 OPTIONS 做能力探测,因为 xpod sidecar 不接受 HEAD。 */ private tryDiscoverSparqlEndpoint; query(operation: PodOperation): Promise; /** * Collect all resource URLs involved in a query plan. * Used for resolving data sources for SPARQL queries. */ private collectSelectSources; private buildIdInConditionFromSubjects; private isInsertPlan; private isUpdatePlan; private isDeletePlan; private isSelectPlan; private buildSubjectLookupPlan; private isQueryConditionNode; private extractSubjectFromRow; private conditionTargetsIdentifier; private rewriteIdentifierConditionWithSubjects; private ensureIdentifierCondition; private rewriteWhereConditionWithSubjects; executeSql(sql: SQL, table: PodTable): Promise; addNamespace(prefix: string, uri: string): void; getConfig(): { podUrl: string; webId: string; connected: boolean; }; /** * 获取认证的 fetch 函数 * 用于需要认证访问的操作(如 Notifications) */ getAuthenticatedFetch(): typeof fetch; getSPARQLConverter(): ASTToSPARQLConverter; getSPARQLExecutor(): ComunicaSPARQLExecutor; getPodUrl(): string; /** * 获取用户的 WebID */ getWebId(): string; /** * 发现特定 RDF 类型的数据位置 * 通过 TypeIndex 和 Interop 发现 * * @param rdfClass RDF 类型 URI * @returns 数据位置列表 */ discoverDataLocations(rdfClass: string, options?: import('./discovery').DiscoverOptions): Promise; /** * 获取所有数据注册信息 */ discoverAll(): Promise; /** * 按应用 ID 发现数据位置 */ discoverByApp(appId: string): Promise; addSource(source: string): void; removeSource(source: string): void; getSources(): string[]; addSourcesFromTypeIndex(): Promise; queryContainer(containerPath: string, sql: SQL, table: PodTable): Promise; getPodMetadata(): Promise; private stripSPARQLProlog; private looksLikeRawSQL; private inferSPARQLQueryType; executeSPARQL(query: string): Promise; transaction(transaction: (tx: PodDialect) => Promise): Promise; getResourcePreparationMode(): NonNullable; shouldSkipResourcePreparation(): boolean; shouldUseWriteTimeResourcePreparation(): boolean; shouldContinueAfterResourcePreparationError(): boolean; /** * Prepare and optionally register a resource mapping. */ registerTable(table: PodTable): Promise; /** * 查找用户的 TypeIndex */ findTypeIndex(): Promise; /** * 创建 TypeIndex */ createTypeIndex(): Promise; /** * 发现已注册的类型 */ discoverTypes(typeIndexUrl?: string): Promise; /** * 自动发现和注册类型(用于数据消费方) */ autoDiscoverAndRegister(webId?: string): Promise; /** * 从 Profile 中自动发现类型(不依赖 TypeIndex) */ discoverTypesFromProfile(): Promise; /** * 发现特定的类型定义(按需发现) * @param rdfClassUri 要发现的 RDF 类型 URI */ discoverSpecificType(rdfClassUri: string): Promise; /** * 发现多个特定类型 * @param rdfClassUris 要发现的 RDF 类型 URI 数组 */ discoverSpecificTypes(rdfClassUris: string[]): Promise; /** * 发现并创建可用的表定义 * @param rdfClassUri 要发现的 RDF 类型 URI * @returns 可用的表定义,如果未找到则返回 null */ discoverTable(rdfClassUri: string): Promise; /** * 发现并创建多个可用的表定义 * @param rdfClassUris 要发现的 RDF 类型 URI 数组 * @returns 可用的表定义数组 */ discoverTables(rdfClassUris: string[]): Promise; /** * 检查类型是否已注册 */ isTypeRegistered(type: string, typeIndexUrl?: string): Promise; /** * 获取 TypeIndex 管理器 */ getTypeIndexManager(): TypeIndexManager; private ensureContainerExists; private createContainerWithRetry; private sleep; private readErrorResponseBody; private formatResourcePreparationError; /** * 获取父容器 URL * 例如: https://pod.com/alice/data/users/ -> https://pod.com/alice/data/ */ private getParentContainer; /** * List all resources in a container * Uses LDP containment triples to discover resources */ private listContainerResources; } //# sourceMappingURL=pod-dialect.d.ts.map