@arke-institute/sdk 0.1.2 → 0.1.3
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/dist/content/index.cjs +95 -10
- package/dist/content/index.cjs.map +1 -1
- package/dist/content/index.d.cts +128 -15
- package/dist/content/index.d.ts +128 -15
- package/dist/content/index.js +95 -10
- package/dist/content/index.js.map +1 -1
- package/dist/edit/index.cjs +590 -116
- package/dist/edit/index.cjs.map +1 -1
- package/dist/edit/index.d.cts +2 -2
- package/dist/edit/index.d.ts +2 -2
- package/dist/edit/index.js +580 -116
- package/dist/edit/index.js.map +1 -1
- package/dist/errors-CT7yzKkU.d.cts +874 -0
- package/dist/errors-CT7yzKkU.d.ts +874 -0
- package/dist/graph/index.cjs +52 -58
- package/dist/graph/index.cjs.map +1 -1
- package/dist/graph/index.d.cts +84 -55
- package/dist/graph/index.d.ts +84 -55
- package/dist/graph/index.js +52 -58
- package/dist/graph/index.js.map +1 -1
- package/dist/index.cjs +796 -196
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +796 -196
- package/dist/index.js.map +1 -1
- package/dist/query/index.cjs +67 -0
- package/dist/query/index.cjs.map +1 -1
- package/dist/query/index.d.cts +96 -1
- package/dist/query/index.d.ts +96 -1
- package/dist/query/index.js +67 -0
- package/dist/query/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/errors-B82BMmRP.d.cts +0 -343
- package/dist/errors-B82BMmRP.d.ts +0 -343
package/dist/graph/index.cjs
CHANGED
|
@@ -125,49 +125,8 @@ var GraphClient = class {
|
|
|
125
125
|
});
|
|
126
126
|
}
|
|
127
127
|
// ---------------------------------------------------------------------------
|
|
128
|
-
//
|
|
128
|
+
// Code-based Lookups (indexed in GraphDB)
|
|
129
129
|
// ---------------------------------------------------------------------------
|
|
130
|
-
/**
|
|
131
|
-
* Get an entity by its canonical ID.
|
|
132
|
-
*
|
|
133
|
-
* @param canonicalId - Entity UUID
|
|
134
|
-
* @returns Entity data
|
|
135
|
-
* @throws GraphEntityNotFoundError if the entity doesn't exist
|
|
136
|
-
*
|
|
137
|
-
* @example
|
|
138
|
-
* ```typescript
|
|
139
|
-
* const entity = await graph.getEntity('uuid-123');
|
|
140
|
-
* console.log('Entity:', entity.label, entity.type);
|
|
141
|
-
* ```
|
|
142
|
-
*/
|
|
143
|
-
async getEntity(canonicalId) {
|
|
144
|
-
const response = await this.request(
|
|
145
|
-
`/graphdb/entity/${encodeURIComponent(canonicalId)}`
|
|
146
|
-
);
|
|
147
|
-
if (!response.found || !response.entity) {
|
|
148
|
-
throw new GraphEntityNotFoundError(canonicalId);
|
|
149
|
-
}
|
|
150
|
-
return response.entity;
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Check if an entity exists by its canonical ID.
|
|
154
|
-
*
|
|
155
|
-
* @param canonicalId - Entity UUID
|
|
156
|
-
* @returns True if entity exists
|
|
157
|
-
*
|
|
158
|
-
* @example
|
|
159
|
-
* ```typescript
|
|
160
|
-
* if (await graph.entityExists('uuid-123')) {
|
|
161
|
-
* console.log('Entity exists');
|
|
162
|
-
* }
|
|
163
|
-
* ```
|
|
164
|
-
*/
|
|
165
|
-
async entityExists(canonicalId) {
|
|
166
|
-
const response = await this.request(
|
|
167
|
-
`/graphdb/entity/exists/${encodeURIComponent(canonicalId)}`
|
|
168
|
-
);
|
|
169
|
-
return response.exists;
|
|
170
|
-
}
|
|
171
130
|
/**
|
|
172
131
|
* Query entities by code with optional type filter.
|
|
173
132
|
*
|
|
@@ -223,11 +182,14 @@ var GraphClient = class {
|
|
|
223
182
|
// PI-based Operations
|
|
224
183
|
// ---------------------------------------------------------------------------
|
|
225
184
|
/**
|
|
226
|
-
* List entities from a specific PI or multiple PIs.
|
|
185
|
+
* List entities extracted from a specific PI or multiple PIs.
|
|
186
|
+
*
|
|
187
|
+
* This returns knowledge graph entities (persons, places, events, etc.)
|
|
188
|
+
* that were extracted from the given PI(s), not the PI entity itself.
|
|
227
189
|
*
|
|
228
190
|
* @param pi - Single PI or array of PIs
|
|
229
191
|
* @param options - Filter options
|
|
230
|
-
* @returns
|
|
192
|
+
* @returns Extracted entities from the PI(s)
|
|
231
193
|
*
|
|
232
194
|
* @example
|
|
233
195
|
* ```typescript
|
|
@@ -286,13 +248,17 @@ var GraphClient = class {
|
|
|
286
248
|
/**
|
|
287
249
|
* Get the lineage (ancestors and/or descendants) of a PI.
|
|
288
250
|
*
|
|
251
|
+
* This traverses the PI hierarchy (parent_pi/children_pi relationships)
|
|
252
|
+
* which is indexed in GraphDB for fast lookups.
|
|
253
|
+
*
|
|
289
254
|
* @param pi - Source PI
|
|
290
255
|
* @param direction - 'ancestors', 'descendants', or 'both'
|
|
291
|
-
* @
|
|
256
|
+
* @param maxHops - Maximum depth to traverse (default: 10)
|
|
257
|
+
* @returns Lineage data with PIs at each hop level
|
|
292
258
|
*
|
|
293
259
|
* @example
|
|
294
260
|
* ```typescript
|
|
295
|
-
* // Get ancestors
|
|
261
|
+
* // Get ancestors (parent chain)
|
|
296
262
|
* const lineage = await graph.getLineage('01K75HQQXNTDG7BBP7PS9AWYAN', 'ancestors');
|
|
297
263
|
*
|
|
298
264
|
* // Get both directions
|
|
@@ -309,25 +275,53 @@ var GraphClient = class {
|
|
|
309
275
|
// Relationship Operations
|
|
310
276
|
// ---------------------------------------------------------------------------
|
|
311
277
|
/**
|
|
312
|
-
* Get
|
|
278
|
+
* Get relationships for an entity from the GraphDB index.
|
|
279
|
+
*
|
|
280
|
+
* **Important distinction from ContentClient.getRelationships():**
|
|
281
|
+
* - **ContentClient.getRelationships()**: Returns OUTBOUND relationships only
|
|
282
|
+
* (from the entity's relationships.json in IPFS - source of truth)
|
|
283
|
+
* - **GraphClient.getRelationships()**: Returns BOTH inbound AND outbound
|
|
284
|
+
* relationships (from the indexed GraphDB mirror)
|
|
313
285
|
*
|
|
314
|
-
*
|
|
315
|
-
*
|
|
286
|
+
* Use this method when you need to find "what references this entity" (inbound)
|
|
287
|
+
* or want a complete bidirectional view.
|
|
288
|
+
*
|
|
289
|
+
* @param id - Entity identifier (works for both PIs and KG entities)
|
|
290
|
+
* @param direction - Filter by direction: 'outgoing', 'incoming', or 'both' (default)
|
|
291
|
+
* @returns Array of relationships with direction indicator
|
|
316
292
|
*
|
|
317
293
|
* @example
|
|
318
294
|
* ```typescript
|
|
319
|
-
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
295
|
+
* // Get all relationships (both directions)
|
|
296
|
+
* const all = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN');
|
|
297
|
+
*
|
|
298
|
+
* // Get only inbound relationships ("who references this entity?")
|
|
299
|
+
* const incoming = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN', 'incoming');
|
|
300
|
+
*
|
|
301
|
+
* // Get only outbound relationships (similar to IPFS, but from index)
|
|
302
|
+
* const outgoing = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN', 'outgoing');
|
|
303
|
+
*
|
|
304
|
+
* // Process by direction
|
|
305
|
+
* const rels = await graph.getRelationships('entity-id');
|
|
306
|
+
* rels.forEach(r => {
|
|
307
|
+
* if (r.direction === 'incoming') {
|
|
308
|
+
* console.log(`${r.target_label} references this entity via ${r.predicate}`);
|
|
309
|
+
* } else {
|
|
310
|
+
* console.log(`This entity ${r.predicate} -> ${r.target_label}`);
|
|
311
|
+
* }
|
|
322
312
|
* });
|
|
323
313
|
* ```
|
|
324
314
|
*/
|
|
325
|
-
async getRelationships(
|
|
326
|
-
const response = await this.request(`/graphdb/relationships/${encodeURIComponent(
|
|
315
|
+
async getRelationships(id, direction = "both") {
|
|
316
|
+
const response = await this.request(`/graphdb/relationships/${encodeURIComponent(id)}`);
|
|
327
317
|
if (!response.found || !response.relationships) {
|
|
328
318
|
return [];
|
|
329
319
|
}
|
|
330
|
-
|
|
320
|
+
let relationships = response.relationships;
|
|
321
|
+
if (direction !== "both") {
|
|
322
|
+
relationships = relationships.filter((rel) => rel.direction === direction);
|
|
323
|
+
}
|
|
324
|
+
return relationships.map((rel) => ({
|
|
331
325
|
direction: rel.direction,
|
|
332
326
|
predicate: rel.predicate,
|
|
333
327
|
target_id: rel.target_id,
|
|
@@ -353,8 +347,8 @@ var GraphClient = class {
|
|
|
353
347
|
* @example
|
|
354
348
|
* ```typescript
|
|
355
349
|
* const paths = await graph.findPaths(
|
|
356
|
-
* ['
|
|
357
|
-
* ['
|
|
350
|
+
* ['entity-alice'],
|
|
351
|
+
* ['entity-bob'],
|
|
358
352
|
* { max_depth: 4, direction: 'both' }
|
|
359
353
|
* );
|
|
360
354
|
*
|
|
@@ -391,7 +385,7 @@ var GraphClient = class {
|
|
|
391
385
|
* ```typescript
|
|
392
386
|
* // Find all people reachable from an event
|
|
393
387
|
* const people = await graph.findReachable(
|
|
394
|
-
* ['
|
|
388
|
+
* ['event-id'],
|
|
395
389
|
* 'person',
|
|
396
390
|
* { max_depth: 3 }
|
|
397
391
|
* );
|
package/dist/graph/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/graph/index.ts","../../src/graph/errors.ts","../../src/graph/client.ts"],"sourcesContent":["/**\n * Graph package for the Arke SDK\n *\n * Provides read-only access to entity relationships from the GraphDB Gateway service.\n *\n * @example\n * ```typescript\n * import { GraphClient } from '@arke-institute/sdk/graph';\n *\n * const graph = new GraphClient({\n * gatewayUrl: 'https://gateway.arke.institute',\n * });\n *\n * // Get entity by ID\n * const entity = await graph.getEntity('uuid-123');\n *\n * // Get entities with relationships from a PI\n * const entities = await graph.getEntitiesWithRelationships('01K75HQQXNTDG7BBP7PS9AWYAN');\n *\n * // Find paths between entities\n * const paths = await graph.findPaths(['uuid-1'], ['uuid-2']);\n * ```\n */\n\nexport { GraphClient, type GraphClientConfig } from './client.js';\nexport * from './types.js';\nexport * from './errors.js';\n","/**\n * Graph package error classes for the Arke SDK\n */\n\n/**\n * Base error class for graph operations\n */\nexport class GraphError extends Error {\n constructor(\n message: string,\n public code: string = 'GRAPH_ERROR',\n public details?: unknown\n ) {\n super(message);\n this.name = 'GraphError';\n }\n}\n\n/**\n * Thrown when an entity is not found by canonical ID\n */\nexport class GraphEntityNotFoundError extends GraphError {\n constructor(canonicalId: string) {\n super(`Graph entity not found: ${canonicalId}`, 'ENTITY_NOT_FOUND', { canonicalId });\n this.name = 'GraphEntityNotFoundError';\n }\n}\n\n/**\n * Thrown when no paths are found between entities\n */\nexport class NoPathFoundError extends GraphError {\n constructor(sourceIds: string[], targetIds: string[]) {\n super(\n `No path found between sources and targets`,\n 'NO_PATH_FOUND',\n { sourceIds, targetIds }\n );\n this.name = 'NoPathFoundError';\n }\n}\n\n/**\n * Thrown when a network error occurs\n */\nexport class NetworkError extends GraphError {\n constructor(message: string, public statusCode?: number) {\n super(message, 'NETWORK_ERROR', { statusCode });\n this.name = 'NetworkError';\n }\n}\n","import {\n GraphError,\n GraphEntityNotFoundError,\n NetworkError,\n} from './errors.js';\nimport type {\n GraphEntity,\n EntityWithRelationships,\n Relationship,\n Path,\n PathOptions,\n ReachableOptions,\n ListFromPiOptions,\n EntityQueryResponse,\n EntitiesWithRelationshipsResponse,\n PathsResponse,\n LineageResponse,\n} from './types.js';\n\n/**\n * Configuration for GraphClient\n */\nexport interface GraphClientConfig {\n /**\n * Gateway base URL (e.g., https://gateway.arke.institute).\n * The client will call /graphdb/* endpoints for GraphDB Gateway.\n */\n gatewayUrl: string;\n /**\n * Optional custom fetch implementation (useful for testing).\n */\n fetchImpl?: typeof fetch;\n}\n\ntype JsonBody = Record<string, unknown>;\n\n/**\n * Client for querying entity relationships from the Arke knowledge graph.\n *\n * All endpoints are public and do not require authentication.\n *\n * @example\n * ```typescript\n * const graph = new GraphClient({\n * gatewayUrl: 'https://gateway.arke.institute',\n * });\n *\n * // Get entity by ID\n * const entity = await graph.getEntity('uuid-123');\n *\n * // Find entities by code\n * const results = await graph.queryByCode('person_john');\n *\n * // Get entities with relationships from a PI\n * const entities = await graph.getEntitiesWithRelationships('01K75HQQXNTDG7BBP7PS9AWYAN');\n *\n * // Find paths between entities\n * const paths = await graph.findPaths(['uuid-1'], ['uuid-2'], { max_depth: 4 });\n * ```\n */\nexport class GraphClient {\n private baseUrl: string;\n private fetchImpl: typeof fetch;\n\n constructor(config: GraphClientConfig) {\n this.baseUrl = config.gatewayUrl.replace(/\\/$/, '');\n this.fetchImpl = config.fetchImpl ?? fetch;\n }\n\n // ---------------------------------------------------------------------------\n // Request helpers\n // ---------------------------------------------------------------------------\n\n private buildUrl(path: string, query?: Record<string, string | number | boolean | undefined>) {\n const url = new URL(`${this.baseUrl}${path}`);\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n });\n }\n return url.toString();\n }\n\n private async request<T>(\n path: string,\n options: RequestInit & {\n query?: Record<string, string | number | boolean | undefined>;\n } = {}\n ): Promise<T> {\n const url = this.buildUrl(path, options.query);\n const headers = new Headers({ 'Content-Type': 'application/json' });\n if (options.headers) {\n Object.entries(options.headers).forEach(([k, v]) => {\n if (v !== undefined) headers.set(k, v as string);\n });\n }\n\n let response: Response;\n try {\n response = await this.fetchImpl(url, { ...options, headers });\n } catch (err) {\n throw new NetworkError(\n err instanceof Error ? err.message : 'Network request failed'\n );\n }\n\n if (response.ok) {\n const contentType = response.headers.get('content-type') || '';\n if (contentType.includes('application/json')) {\n return (await response.json()) as T;\n }\n return (await response.text()) as unknown as T;\n }\n\n let body: unknown;\n const text = await response.text();\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n\n // Handle 404 specifically\n if (response.status === 404) {\n throw new GraphError(\n (body as JsonBody)?.message as string || 'Not found',\n 'NOT_FOUND',\n body\n );\n }\n\n const message =\n (body as JsonBody)?.error && typeof (body as JsonBody).error === 'string'\n ? ((body as JsonBody).error as string)\n : (body as JsonBody)?.message && typeof (body as JsonBody).message === 'string'\n ? ((body as JsonBody).message as string)\n : `Request failed with status ${response.status}`;\n\n throw new GraphError(message, 'HTTP_ERROR', {\n status: response.status,\n body,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Entity Operations\n // ---------------------------------------------------------------------------\n\n /**\n * Get an entity by its canonical ID.\n *\n * @param canonicalId - Entity UUID\n * @returns Entity data\n * @throws GraphEntityNotFoundError if the entity doesn't exist\n *\n * @example\n * ```typescript\n * const entity = await graph.getEntity('uuid-123');\n * console.log('Entity:', entity.label, entity.type);\n * ```\n */\n async getEntity(canonicalId: string): Promise<GraphEntity> {\n const response = await this.request<{ found: boolean; entity?: GraphEntity }>(\n `/graphdb/entity/${encodeURIComponent(canonicalId)}`\n );\n\n if (!response.found || !response.entity) {\n throw new GraphEntityNotFoundError(canonicalId);\n }\n\n return response.entity;\n }\n\n /**\n * Check if an entity exists by its canonical ID.\n *\n * @param canonicalId - Entity UUID\n * @returns True if entity exists\n *\n * @example\n * ```typescript\n * if (await graph.entityExists('uuid-123')) {\n * console.log('Entity exists');\n * }\n * ```\n */\n async entityExists(canonicalId: string): Promise<boolean> {\n const response = await this.request<{ exists: boolean }>(\n `/graphdb/entity/exists/${encodeURIComponent(canonicalId)}`\n );\n return response.exists;\n }\n\n /**\n * Query entities by code with optional type filter.\n *\n * @param code - Entity code to search for\n * @param type - Optional entity type filter\n * @returns Matching entities\n *\n * @example\n * ```typescript\n * // Find by code\n * const entities = await graph.queryByCode('person_john');\n *\n * // With type filter\n * const people = await graph.queryByCode('john', 'person');\n * ```\n */\n async queryByCode(code: string, type?: string): Promise<GraphEntity[]> {\n const response = await this.request<EntityQueryResponse>(\n '/graphdb/entity/query',\n {\n method: 'POST',\n body: JSON.stringify({ code, type }),\n }\n );\n\n if (!response.found || !response.entity) {\n return [];\n }\n\n return [response.entity];\n }\n\n /**\n * Look up entities by code across all PIs.\n *\n * @param code - Entity code to search for\n * @param type - Optional entity type filter\n * @returns Matching entities\n *\n * @example\n * ```typescript\n * const entities = await graph.lookupByCode('alice_austen', 'person');\n * ```\n */\n async lookupByCode(code: string, type?: string): Promise<GraphEntity[]> {\n const response = await this.request<{ entities: GraphEntity[] }>(\n '/graphdb/entities/lookup-by-code',\n {\n method: 'POST',\n body: JSON.stringify({ code, type }),\n }\n );\n return response.entities || [];\n }\n\n // ---------------------------------------------------------------------------\n // PI-based Operations\n // ---------------------------------------------------------------------------\n\n /**\n * List entities from a specific PI or multiple PIs.\n *\n * @param pi - Single PI or array of PIs\n * @param options - Filter options\n * @returns Entities from the PI(s)\n *\n * @example\n * ```typescript\n * // From single PI\n * const entities = await graph.listEntitiesFromPi('01K75HQQXNTDG7BBP7PS9AWYAN');\n *\n * // With type filter\n * const people = await graph.listEntitiesFromPi('01K75HQQXNTDG7BBP7PS9AWYAN', { type: 'person' });\n *\n * // From multiple PIs\n * const all = await graph.listEntitiesFromPi(['pi-1', 'pi-2']);\n * ```\n */\n async listEntitiesFromPi(\n pi: string | string[],\n options: ListFromPiOptions = {}\n ): Promise<GraphEntity[]> {\n const pis = Array.isArray(pi) ? pi : [pi];\n const response = await this.request<{ entities: GraphEntity[] }>(\n '/graphdb/entities/list',\n {\n method: 'POST',\n body: JSON.stringify({\n pis,\n type: options.type,\n }),\n }\n );\n return response.entities || [];\n }\n\n /**\n * Get entities with their relationships from a PI.\n *\n * This is an optimized query that returns entities along with all their\n * relationship data in a single request.\n *\n * @param pi - Persistent Identifier\n * @param type - Optional entity type filter\n * @returns Entities with relationships\n *\n * @example\n * ```typescript\n * const entities = await graph.getEntitiesWithRelationships('01K75HQQXNTDG7BBP7PS9AWYAN');\n * entities.forEach(e => {\n * console.log(`${e.label} has ${e.relationships.length} relationships`);\n * });\n * ```\n */\n async getEntitiesWithRelationships(\n pi: string,\n type?: string\n ): Promise<EntityWithRelationships[]> {\n const response = await this.request<EntitiesWithRelationshipsResponse>(\n '/graphdb/pi/entities-with-relationships',\n {\n method: 'POST',\n body: JSON.stringify({ pi, type }),\n }\n );\n return response.entities || [];\n }\n\n /**\n * Get the lineage (ancestors and/or descendants) of a PI.\n *\n * @param pi - Source PI\n * @param direction - 'ancestors', 'descendants', or 'both'\n * @returns Lineage data\n *\n * @example\n * ```typescript\n * // Get ancestors\n * const lineage = await graph.getLineage('01K75HQQXNTDG7BBP7PS9AWYAN', 'ancestors');\n *\n * // Get both directions\n * const full = await graph.getLineage('01K75HQQXNTDG7BBP7PS9AWYAN', 'both');\n * ```\n */\n async getLineage(\n pi: string,\n direction: 'ancestors' | 'descendants' | 'both' = 'both',\n maxHops: number = 10\n ): Promise<LineageResponse> {\n return this.request<LineageResponse>('/graphdb/pi/lineage', {\n method: 'POST',\n body: JSON.stringify({ sourcePi: pi, direction, maxHops }),\n });\n }\n\n // ---------------------------------------------------------------------------\n // Relationship Operations\n // ---------------------------------------------------------------------------\n\n /**\n * Get all relationships for an entity.\n *\n * @param canonicalId - Entity UUID\n * @returns Array of relationships\n *\n * @example\n * ```typescript\n * const relationships = await graph.getRelationships('uuid-123');\n * relationships.forEach(r => {\n * console.log(`${r.direction}: ${r.predicate} -> ${r.target_label}`);\n * });\n * ```\n */\n async getRelationships(canonicalId: string): Promise<Relationship[]> {\n const response = await this.request<{\n found: boolean;\n canonical_id?: string;\n relationships?: Array<{\n direction: 'outgoing' | 'incoming';\n predicate: string;\n target_id: string;\n target_code?: string;\n target_label: string;\n target_type: string;\n properties?: Record<string, unknown>;\n source_pi?: string;\n created_at?: string;\n }>;\n }>(`/graphdb/relationships/${encodeURIComponent(canonicalId)}`);\n\n if (!response.found || !response.relationships) {\n return [];\n }\n\n return response.relationships.map(rel => ({\n direction: rel.direction,\n predicate: rel.predicate,\n target_id: rel.target_id,\n target_code: rel.target_code || '',\n target_label: rel.target_label,\n target_type: rel.target_type,\n properties: rel.properties,\n source_pi: rel.source_pi,\n created_at: rel.created_at,\n }));\n }\n\n // ---------------------------------------------------------------------------\n // Path Finding\n // ---------------------------------------------------------------------------\n\n /**\n * Find shortest paths between sets of entities.\n *\n * @param sourceIds - Starting entity IDs\n * @param targetIds - Target entity IDs\n * @param options - Path finding options\n * @returns Found paths\n *\n * @example\n * ```typescript\n * const paths = await graph.findPaths(\n * ['uuid-alice'],\n * ['uuid-bob'],\n * { max_depth: 4, direction: 'both' }\n * );\n *\n * paths.forEach(path => {\n * console.log(`Path of length ${path.length}:`);\n * path.edges.forEach(e => {\n * console.log(` ${e.subject_label} -[${e.predicate}]-> ${e.object_label}`);\n * });\n * });\n * ```\n */\n async findPaths(\n sourceIds: string[],\n targetIds: string[],\n options: PathOptions = {}\n ): Promise<Path[]> {\n const response = await this.request<PathsResponse>('/graphdb/paths/between', {\n method: 'POST',\n body: JSON.stringify({\n source_ids: sourceIds,\n target_ids: targetIds,\n max_depth: options.max_depth,\n direction: options.direction,\n limit: options.limit,\n }),\n });\n return response.paths || [];\n }\n\n /**\n * Find entities of a specific type reachable from starting entities.\n *\n * @param startIds - Starting entity IDs\n * @param targetType - Type of entities to find\n * @param options - Search options\n * @returns Reachable entities of the specified type\n *\n * @example\n * ```typescript\n * // Find all people reachable from an event\n * const people = await graph.findReachable(\n * ['uuid-event'],\n * 'person',\n * { max_depth: 3 }\n * );\n * ```\n */\n async findReachable(\n startIds: string[],\n targetType: string,\n options: ReachableOptions = {}\n ): Promise<GraphEntity[]> {\n const response = await this.request<{ entities: GraphEntity[] }>(\n '/graphdb/paths/reachable',\n {\n method: 'POST',\n body: JSON.stringify({\n start_ids: startIds,\n target_type: targetType,\n max_depth: options.max_depth,\n direction: options.direction,\n limit: options.limit,\n }),\n }\n );\n return response.entities || [];\n }\n\n /**\n * Check the health of the graph service.\n *\n * @returns Health status\n */\n async health(): Promise<{ status: string; service: string; version: string }> {\n return this.request('/graphdb/health', { method: 'GET' });\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/graph/index.ts","../../src/graph/errors.ts","../../src/graph/client.ts"],"sourcesContent":["/**\n * Graph package for the Arke SDK\n *\n * Provides read-only access to the GraphDB Gateway service, which is an indexed\n * mirror of entity data stored in IPFS.\n *\n * Use GraphClient for:\n * - **Bidirectional relationship queries** (IPFS only stores outbound)\n * - **Path finding** between entities\n * - **PI lineage queries** (ancestors/descendants)\n * - **Code-based lookups** (indexed for fast search)\n *\n * For entity CRUD operations, use ContentClient or EditClient (IPFS source of truth).\n *\n * @example\n * ```typescript\n * import { GraphClient } from '@arke-institute/sdk/graph';\n *\n * const graph = new GraphClient({\n * gatewayUrl: 'https://gateway.arke.institute',\n * });\n *\n * // Get ALL relationships (both directions - only GraphDB has inbound)\n * const allRels = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN');\n *\n * // Get only inbound relationships (\"who references this entity?\")\n * const incoming = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN', 'incoming');\n *\n * // Find paths between entities\n * const paths = await graph.findPaths(['entity-1'], ['entity-2']);\n *\n * // Get PI lineage (ancestors/descendants)\n * const lineage = await graph.getLineage('01K75HQQXNTDG7BBP7PS9AWYAN', 'ancestors');\n * ```\n */\n\nexport { GraphClient, type GraphClientConfig } from './client.js';\nexport * from './types.js';\nexport * from './errors.js';\n","/**\n * Graph package error classes for the Arke SDK\n */\n\n/**\n * Base error class for graph operations\n */\nexport class GraphError extends Error {\n constructor(\n message: string,\n public code: string = 'GRAPH_ERROR',\n public details?: unknown\n ) {\n super(message);\n this.name = 'GraphError';\n }\n}\n\n/**\n * Thrown when an entity is not found by canonical ID\n */\nexport class GraphEntityNotFoundError extends GraphError {\n constructor(canonicalId: string) {\n super(`Graph entity not found: ${canonicalId}`, 'ENTITY_NOT_FOUND', { canonicalId });\n this.name = 'GraphEntityNotFoundError';\n }\n}\n\n/**\n * Thrown when no paths are found between entities\n */\nexport class NoPathFoundError extends GraphError {\n constructor(sourceIds: string[], targetIds: string[]) {\n super(\n `No path found between sources and targets`,\n 'NO_PATH_FOUND',\n { sourceIds, targetIds }\n );\n this.name = 'NoPathFoundError';\n }\n}\n\n/**\n * Thrown when a network error occurs\n */\nexport class NetworkError extends GraphError {\n constructor(message: string, public statusCode?: number) {\n super(message, 'NETWORK_ERROR', { statusCode });\n this.name = 'NetworkError';\n }\n}\n","import {\n GraphError,\n NetworkError,\n} from './errors.js';\nimport type {\n GraphEntity,\n EntityWithRelationships,\n Relationship,\n RelationshipDirection,\n Path,\n PathOptions,\n ReachableOptions,\n ListFromPiOptions,\n EntityQueryResponse,\n EntitiesWithRelationshipsResponse,\n PathsResponse,\n LineageResponse,\n} from './types.js';\n\n/**\n * Configuration for GraphClient\n */\nexport interface GraphClientConfig {\n /**\n * Gateway base URL (e.g., https://gateway.arke.institute).\n * The client will call /graphdb/* endpoints for GraphDB Gateway.\n */\n gatewayUrl: string;\n /**\n * Optional custom fetch implementation (useful for testing).\n */\n fetchImpl?: typeof fetch;\n}\n\ntype JsonBody = Record<string, unknown>;\n\n/**\n * Client for querying entity relationships and graph traversal from the Arke knowledge graph.\n *\n * The GraphDB is an indexed mirror of entity data stored in IPFS. Use this client for:\n * - **Bidirectional relationship queries** (IPFS only stores outbound relationships)\n * - **Path finding** between entities\n * - **Lineage queries** (PI ancestors/descendants)\n * - **Code-based lookups** (indexed for fast search)\n * - **Listing extracted entities** from a PI\n *\n * For entity CRUD operations, use ContentClient (source of truth in IPFS).\n * For write operations, use EditClient.\n *\n * All endpoints are public and do not require authentication.\n *\n * @example\n * ```typescript\n * const graph = new GraphClient({\n * gatewayUrl: 'https://gateway.arke.institute',\n * });\n *\n * // Get BOTH inbound and outbound relationships (GraphDB indexed)\n * const allRels = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN');\n *\n * // Get only inbound relationships (\"who references this entity?\")\n * const incoming = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN', 'incoming');\n *\n * // Find paths between entities\n * const paths = await graph.findPaths(['entity-1'], ['entity-2'], { max_depth: 4 });\n *\n * // Get PI lineage\n * const lineage = await graph.getLineage('01K75HQQXNTDG7BBP7PS9AWYAN', 'ancestors');\n * ```\n */\nexport class GraphClient {\n private baseUrl: string;\n private fetchImpl: typeof fetch;\n\n constructor(config: GraphClientConfig) {\n this.baseUrl = config.gatewayUrl.replace(/\\/$/, '');\n this.fetchImpl = config.fetchImpl ?? fetch;\n }\n\n // ---------------------------------------------------------------------------\n // Request helpers\n // ---------------------------------------------------------------------------\n\n private buildUrl(path: string, query?: Record<string, string | number | boolean | undefined>) {\n const url = new URL(`${this.baseUrl}${path}`);\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n });\n }\n return url.toString();\n }\n\n private async request<T>(\n path: string,\n options: RequestInit & {\n query?: Record<string, string | number | boolean | undefined>;\n } = {}\n ): Promise<T> {\n const url = this.buildUrl(path, options.query);\n const headers = new Headers({ 'Content-Type': 'application/json' });\n if (options.headers) {\n Object.entries(options.headers).forEach(([k, v]) => {\n if (v !== undefined) headers.set(k, v as string);\n });\n }\n\n let response: Response;\n try {\n response = await this.fetchImpl(url, { ...options, headers });\n } catch (err) {\n throw new NetworkError(\n err instanceof Error ? err.message : 'Network request failed'\n );\n }\n\n if (response.ok) {\n const contentType = response.headers.get('content-type') || '';\n if (contentType.includes('application/json')) {\n return (await response.json()) as T;\n }\n return (await response.text()) as unknown as T;\n }\n\n let body: unknown;\n const text = await response.text();\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n\n // Handle 404 specifically\n if (response.status === 404) {\n throw new GraphError(\n (body as JsonBody)?.message as string || 'Not found',\n 'NOT_FOUND',\n body\n );\n }\n\n const message =\n (body as JsonBody)?.error && typeof (body as JsonBody).error === 'string'\n ? ((body as JsonBody).error as string)\n : (body as JsonBody)?.message && typeof (body as JsonBody).message === 'string'\n ? ((body as JsonBody).message as string)\n : `Request failed with status ${response.status}`;\n\n throw new GraphError(message, 'HTTP_ERROR', {\n status: response.status,\n body,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Code-based Lookups (indexed in GraphDB)\n // ---------------------------------------------------------------------------\n\n /**\n * Query entities by code with optional type filter.\n *\n * @param code - Entity code to search for\n * @param type - Optional entity type filter\n * @returns Matching entities\n *\n * @example\n * ```typescript\n * // Find by code\n * const entities = await graph.queryByCode('person_john');\n *\n * // With type filter\n * const people = await graph.queryByCode('john', 'person');\n * ```\n */\n async queryByCode(code: string, type?: string): Promise<GraphEntity[]> {\n const response = await this.request<EntityQueryResponse>(\n '/graphdb/entity/query',\n {\n method: 'POST',\n body: JSON.stringify({ code, type }),\n }\n );\n\n if (!response.found || !response.entity) {\n return [];\n }\n\n return [response.entity];\n }\n\n /**\n * Look up entities by code across all PIs.\n *\n * @param code - Entity code to search for\n * @param type - Optional entity type filter\n * @returns Matching entities\n *\n * @example\n * ```typescript\n * const entities = await graph.lookupByCode('alice_austen', 'person');\n * ```\n */\n async lookupByCode(code: string, type?: string): Promise<GraphEntity[]> {\n const response = await this.request<{ entities: GraphEntity[] }>(\n '/graphdb/entities/lookup-by-code',\n {\n method: 'POST',\n body: JSON.stringify({ code, type }),\n }\n );\n return response.entities || [];\n }\n\n // ---------------------------------------------------------------------------\n // PI-based Operations\n // ---------------------------------------------------------------------------\n\n /**\n * List entities extracted from a specific PI or multiple PIs.\n *\n * This returns knowledge graph entities (persons, places, events, etc.)\n * that were extracted from the given PI(s), not the PI entity itself.\n *\n * @param pi - Single PI or array of PIs\n * @param options - Filter options\n * @returns Extracted entities from the PI(s)\n *\n * @example\n * ```typescript\n * // From single PI\n * const entities = await graph.listEntitiesFromPi('01K75HQQXNTDG7BBP7PS9AWYAN');\n *\n * // With type filter\n * const people = await graph.listEntitiesFromPi('01K75HQQXNTDG7BBP7PS9AWYAN', { type: 'person' });\n *\n * // From multiple PIs\n * const all = await graph.listEntitiesFromPi(['pi-1', 'pi-2']);\n * ```\n */\n async listEntitiesFromPi(\n pi: string | string[],\n options: ListFromPiOptions = {}\n ): Promise<GraphEntity[]> {\n const pis = Array.isArray(pi) ? pi : [pi];\n const response = await this.request<{ entities: GraphEntity[] }>(\n '/graphdb/entities/list',\n {\n method: 'POST',\n body: JSON.stringify({\n pis,\n type: options.type,\n }),\n }\n );\n return response.entities || [];\n }\n\n /**\n * Get entities with their relationships from a PI.\n *\n * This is an optimized query that returns entities along with all their\n * relationship data in a single request.\n *\n * @param pi - Persistent Identifier\n * @param type - Optional entity type filter\n * @returns Entities with relationships\n *\n * @example\n * ```typescript\n * const entities = await graph.getEntitiesWithRelationships('01K75HQQXNTDG7BBP7PS9AWYAN');\n * entities.forEach(e => {\n * console.log(`${e.label} has ${e.relationships.length} relationships`);\n * });\n * ```\n */\n async getEntitiesWithRelationships(\n pi: string,\n type?: string\n ): Promise<EntityWithRelationships[]> {\n const response = await this.request<EntitiesWithRelationshipsResponse>(\n '/graphdb/pi/entities-with-relationships',\n {\n method: 'POST',\n body: JSON.stringify({ pi, type }),\n }\n );\n return response.entities || [];\n }\n\n /**\n * Get the lineage (ancestors and/or descendants) of a PI.\n *\n * This traverses the PI hierarchy (parent_pi/children_pi relationships)\n * which is indexed in GraphDB for fast lookups.\n *\n * @param pi - Source PI\n * @param direction - 'ancestors', 'descendants', or 'both'\n * @param maxHops - Maximum depth to traverse (default: 10)\n * @returns Lineage data with PIs at each hop level\n *\n * @example\n * ```typescript\n * // Get ancestors (parent chain)\n * const lineage = await graph.getLineage('01K75HQQXNTDG7BBP7PS9AWYAN', 'ancestors');\n *\n * // Get both directions\n * const full = await graph.getLineage('01K75HQQXNTDG7BBP7PS9AWYAN', 'both');\n * ```\n */\n async getLineage(\n pi: string,\n direction: 'ancestors' | 'descendants' | 'both' = 'both',\n maxHops: number = 10\n ): Promise<LineageResponse> {\n return this.request<LineageResponse>('/graphdb/pi/lineage', {\n method: 'POST',\n body: JSON.stringify({ sourcePi: pi, direction, maxHops }),\n });\n }\n\n // ---------------------------------------------------------------------------\n // Relationship Operations\n // ---------------------------------------------------------------------------\n\n /**\n * Get relationships for an entity from the GraphDB index.\n *\n * **Important distinction from ContentClient.getRelationships():**\n * - **ContentClient.getRelationships()**: Returns OUTBOUND relationships only\n * (from the entity's relationships.json in IPFS - source of truth)\n * - **GraphClient.getRelationships()**: Returns BOTH inbound AND outbound\n * relationships (from the indexed GraphDB mirror)\n *\n * Use this method when you need to find \"what references this entity\" (inbound)\n * or want a complete bidirectional view.\n *\n * @param id - Entity identifier (works for both PIs and KG entities)\n * @param direction - Filter by direction: 'outgoing', 'incoming', or 'both' (default)\n * @returns Array of relationships with direction indicator\n *\n * @example\n * ```typescript\n * // Get all relationships (both directions)\n * const all = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN');\n *\n * // Get only inbound relationships (\"who references this entity?\")\n * const incoming = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN', 'incoming');\n *\n * // Get only outbound relationships (similar to IPFS, but from index)\n * const outgoing = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN', 'outgoing');\n *\n * // Process by direction\n * const rels = await graph.getRelationships('entity-id');\n * rels.forEach(r => {\n * if (r.direction === 'incoming') {\n * console.log(`${r.target_label} references this entity via ${r.predicate}`);\n * } else {\n * console.log(`This entity ${r.predicate} -> ${r.target_label}`);\n * }\n * });\n * ```\n */\n async getRelationships(\n id: string,\n direction: RelationshipDirection = 'both'\n ): Promise<Relationship[]> {\n const response = await this.request<{\n found: boolean;\n canonical_id?: string;\n relationships?: Array<{\n direction: 'outgoing' | 'incoming';\n predicate: string;\n target_id: string;\n target_code?: string;\n target_label: string;\n target_type: string;\n properties?: Record<string, unknown>;\n source_pi?: string;\n created_at?: string;\n }>;\n }>(`/graphdb/relationships/${encodeURIComponent(id)}`);\n\n if (!response.found || !response.relationships) {\n return [];\n }\n\n let relationships = response.relationships;\n\n // Filter by direction if specified\n if (direction !== 'both') {\n relationships = relationships.filter(rel => rel.direction === direction);\n }\n\n return relationships.map(rel => ({\n direction: rel.direction,\n predicate: rel.predicate,\n target_id: rel.target_id,\n target_code: rel.target_code || '',\n target_label: rel.target_label,\n target_type: rel.target_type,\n properties: rel.properties,\n source_pi: rel.source_pi,\n created_at: rel.created_at,\n }));\n }\n\n // ---------------------------------------------------------------------------\n // Path Finding\n // ---------------------------------------------------------------------------\n\n /**\n * Find shortest paths between sets of entities.\n *\n * @param sourceIds - Starting entity IDs\n * @param targetIds - Target entity IDs\n * @param options - Path finding options\n * @returns Found paths\n *\n * @example\n * ```typescript\n * const paths = await graph.findPaths(\n * ['entity-alice'],\n * ['entity-bob'],\n * { max_depth: 4, direction: 'both' }\n * );\n *\n * paths.forEach(path => {\n * console.log(`Path of length ${path.length}:`);\n * path.edges.forEach(e => {\n * console.log(` ${e.subject_label} -[${e.predicate}]-> ${e.object_label}`);\n * });\n * });\n * ```\n */\n async findPaths(\n sourceIds: string[],\n targetIds: string[],\n options: PathOptions = {}\n ): Promise<Path[]> {\n const response = await this.request<PathsResponse>('/graphdb/paths/between', {\n method: 'POST',\n body: JSON.stringify({\n source_ids: sourceIds,\n target_ids: targetIds,\n max_depth: options.max_depth,\n direction: options.direction,\n limit: options.limit,\n }),\n });\n return response.paths || [];\n }\n\n /**\n * Find entities of a specific type reachable from starting entities.\n *\n * @param startIds - Starting entity IDs\n * @param targetType - Type of entities to find\n * @param options - Search options\n * @returns Reachable entities of the specified type\n *\n * @example\n * ```typescript\n * // Find all people reachable from an event\n * const people = await graph.findReachable(\n * ['event-id'],\n * 'person',\n * { max_depth: 3 }\n * );\n * ```\n */\n async findReachable(\n startIds: string[],\n targetType: string,\n options: ReachableOptions = {}\n ): Promise<GraphEntity[]> {\n const response = await this.request<{ entities: GraphEntity[] }>(\n '/graphdb/paths/reachable',\n {\n method: 'POST',\n body: JSON.stringify({\n start_ids: startIds,\n target_type: targetType,\n max_depth: options.max_depth,\n direction: options.direction,\n limit: options.limit,\n }),\n }\n );\n return response.entities || [];\n }\n\n /**\n * Check the health of the graph service.\n *\n * @returns Health status\n */\n async health(): Promise<{ status: string; service: string; version: string }> {\n return this.request('/graphdb/health', { method: 'GET' });\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/graph/index.d.cts
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Graph package types for the Arke SDK
|
|
3
3
|
*
|
|
4
|
-
* Types for interacting with
|
|
4
|
+
* Types for interacting with the GraphDB Gateway service.
|
|
5
|
+
*
|
|
6
|
+
* The GraphDB is an indexed mirror of entity data stored in IPFS. Entity IDs
|
|
7
|
+
* are consistent across both systems - the same ID works in ContentClient
|
|
8
|
+
* (IPFS source of truth) and GraphClient (indexed mirror).
|
|
9
|
+
*
|
|
10
|
+
* Key distinction:
|
|
11
|
+
* - IPFS stores only OUTBOUND relationships (in relationships.json)
|
|
12
|
+
* - GraphDB indexes BOTH inbound AND outbound relationships for fast bidirectional queries
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Direction filter for relationship queries
|
|
16
|
+
*
|
|
17
|
+
* - 'outgoing': Relationships where this entity is the source
|
|
18
|
+
* - 'incoming': Relationships where this entity is the target (only available via GraphDB)
|
|
19
|
+
* - 'both': All relationships in both directions
|
|
5
20
|
*/
|
|
21
|
+
type RelationshipDirection = 'outgoing' | 'incoming' | 'both';
|
|
6
22
|
/**
|
|
7
|
-
* Entity from the knowledge graph
|
|
23
|
+
* Entity from the knowledge graph (as indexed in GraphDB)
|
|
8
24
|
*/
|
|
9
25
|
interface GraphEntity {
|
|
10
|
-
/** Unique identifier (
|
|
26
|
+
/** Unique identifier (consistent with IPFS entity IDs) */
|
|
11
27
|
canonical_id: string;
|
|
12
28
|
/** Entity code (e.g., 'person_john', 'event_123') */
|
|
13
29
|
code: string;
|
|
@@ -208,7 +224,17 @@ interface GraphClientConfig {
|
|
|
208
224
|
fetchImpl?: typeof fetch;
|
|
209
225
|
}
|
|
210
226
|
/**
|
|
211
|
-
* Client for querying entity relationships from the Arke knowledge graph.
|
|
227
|
+
* Client for querying entity relationships and graph traversal from the Arke knowledge graph.
|
|
228
|
+
*
|
|
229
|
+
* The GraphDB is an indexed mirror of entity data stored in IPFS. Use this client for:
|
|
230
|
+
* - **Bidirectional relationship queries** (IPFS only stores outbound relationships)
|
|
231
|
+
* - **Path finding** between entities
|
|
232
|
+
* - **Lineage queries** (PI ancestors/descendants)
|
|
233
|
+
* - **Code-based lookups** (indexed for fast search)
|
|
234
|
+
* - **Listing extracted entities** from a PI
|
|
235
|
+
*
|
|
236
|
+
* For entity CRUD operations, use ContentClient (source of truth in IPFS).
|
|
237
|
+
* For write operations, use EditClient.
|
|
212
238
|
*
|
|
213
239
|
* All endpoints are public and do not require authentication.
|
|
214
240
|
*
|
|
@@ -218,17 +244,17 @@ interface GraphClientConfig {
|
|
|
218
244
|
* gatewayUrl: 'https://gateway.arke.institute',
|
|
219
245
|
* });
|
|
220
246
|
*
|
|
221
|
-
* // Get
|
|
222
|
-
* const
|
|
223
|
-
*
|
|
224
|
-
* // Find entities by code
|
|
225
|
-
* const results = await graph.queryByCode('person_john');
|
|
247
|
+
* // Get BOTH inbound and outbound relationships (GraphDB indexed)
|
|
248
|
+
* const allRels = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN');
|
|
226
249
|
*
|
|
227
|
-
* // Get
|
|
228
|
-
* const
|
|
250
|
+
* // Get only inbound relationships ("who references this entity?")
|
|
251
|
+
* const incoming = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN', 'incoming');
|
|
229
252
|
*
|
|
230
253
|
* // Find paths between entities
|
|
231
|
-
* const paths = await graph.findPaths(['
|
|
254
|
+
* const paths = await graph.findPaths(['entity-1'], ['entity-2'], { max_depth: 4 });
|
|
255
|
+
*
|
|
256
|
+
* // Get PI lineage
|
|
257
|
+
* const lineage = await graph.getLineage('01K75HQQXNTDG7BBP7PS9AWYAN', 'ancestors');
|
|
232
258
|
* ```
|
|
233
259
|
*/
|
|
234
260
|
declare class GraphClient {
|
|
@@ -237,34 +263,6 @@ declare class GraphClient {
|
|
|
237
263
|
constructor(config: GraphClientConfig);
|
|
238
264
|
private buildUrl;
|
|
239
265
|
private request;
|
|
240
|
-
/**
|
|
241
|
-
* Get an entity by its canonical ID.
|
|
242
|
-
*
|
|
243
|
-
* @param canonicalId - Entity UUID
|
|
244
|
-
* @returns Entity data
|
|
245
|
-
* @throws GraphEntityNotFoundError if the entity doesn't exist
|
|
246
|
-
*
|
|
247
|
-
* @example
|
|
248
|
-
* ```typescript
|
|
249
|
-
* const entity = await graph.getEntity('uuid-123');
|
|
250
|
-
* console.log('Entity:', entity.label, entity.type);
|
|
251
|
-
* ```
|
|
252
|
-
*/
|
|
253
|
-
getEntity(canonicalId: string): Promise<GraphEntity>;
|
|
254
|
-
/**
|
|
255
|
-
* Check if an entity exists by its canonical ID.
|
|
256
|
-
*
|
|
257
|
-
* @param canonicalId - Entity UUID
|
|
258
|
-
* @returns True if entity exists
|
|
259
|
-
*
|
|
260
|
-
* @example
|
|
261
|
-
* ```typescript
|
|
262
|
-
* if (await graph.entityExists('uuid-123')) {
|
|
263
|
-
* console.log('Entity exists');
|
|
264
|
-
* }
|
|
265
|
-
* ```
|
|
266
|
-
*/
|
|
267
|
-
entityExists(canonicalId: string): Promise<boolean>;
|
|
268
266
|
/**
|
|
269
267
|
* Query entities by code with optional type filter.
|
|
270
268
|
*
|
|
@@ -296,11 +294,14 @@ declare class GraphClient {
|
|
|
296
294
|
*/
|
|
297
295
|
lookupByCode(code: string, type?: string): Promise<GraphEntity[]>;
|
|
298
296
|
/**
|
|
299
|
-
* List entities from a specific PI or multiple PIs.
|
|
297
|
+
* List entities extracted from a specific PI or multiple PIs.
|
|
298
|
+
*
|
|
299
|
+
* This returns knowledge graph entities (persons, places, events, etc.)
|
|
300
|
+
* that were extracted from the given PI(s), not the PI entity itself.
|
|
300
301
|
*
|
|
301
302
|
* @param pi - Single PI or array of PIs
|
|
302
303
|
* @param options - Filter options
|
|
303
|
-
* @returns
|
|
304
|
+
* @returns Extracted entities from the PI(s)
|
|
304
305
|
*
|
|
305
306
|
* @example
|
|
306
307
|
* ```typescript
|
|
@@ -337,13 +338,17 @@ declare class GraphClient {
|
|
|
337
338
|
/**
|
|
338
339
|
* Get the lineage (ancestors and/or descendants) of a PI.
|
|
339
340
|
*
|
|
341
|
+
* This traverses the PI hierarchy (parent_pi/children_pi relationships)
|
|
342
|
+
* which is indexed in GraphDB for fast lookups.
|
|
343
|
+
*
|
|
340
344
|
* @param pi - Source PI
|
|
341
345
|
* @param direction - 'ancestors', 'descendants', or 'both'
|
|
342
|
-
* @
|
|
346
|
+
* @param maxHops - Maximum depth to traverse (default: 10)
|
|
347
|
+
* @returns Lineage data with PIs at each hop level
|
|
343
348
|
*
|
|
344
349
|
* @example
|
|
345
350
|
* ```typescript
|
|
346
|
-
* // Get ancestors
|
|
351
|
+
* // Get ancestors (parent chain)
|
|
347
352
|
* const lineage = await graph.getLineage('01K75HQQXNTDG7BBP7PS9AWYAN', 'ancestors');
|
|
348
353
|
*
|
|
349
354
|
* // Get both directions
|
|
@@ -352,20 +357,44 @@ declare class GraphClient {
|
|
|
352
357
|
*/
|
|
353
358
|
getLineage(pi: string, direction?: 'ancestors' | 'descendants' | 'both', maxHops?: number): Promise<LineageResponse>;
|
|
354
359
|
/**
|
|
355
|
-
* Get
|
|
360
|
+
* Get relationships for an entity from the GraphDB index.
|
|
361
|
+
*
|
|
362
|
+
* **Important distinction from ContentClient.getRelationships():**
|
|
363
|
+
* - **ContentClient.getRelationships()**: Returns OUTBOUND relationships only
|
|
364
|
+
* (from the entity's relationships.json in IPFS - source of truth)
|
|
365
|
+
* - **GraphClient.getRelationships()**: Returns BOTH inbound AND outbound
|
|
366
|
+
* relationships (from the indexed GraphDB mirror)
|
|
367
|
+
*
|
|
368
|
+
* Use this method when you need to find "what references this entity" (inbound)
|
|
369
|
+
* or want a complete bidirectional view.
|
|
356
370
|
*
|
|
357
|
-
* @param
|
|
358
|
-
* @
|
|
371
|
+
* @param id - Entity identifier (works for both PIs and KG entities)
|
|
372
|
+
* @param direction - Filter by direction: 'outgoing', 'incoming', or 'both' (default)
|
|
373
|
+
* @returns Array of relationships with direction indicator
|
|
359
374
|
*
|
|
360
375
|
* @example
|
|
361
376
|
* ```typescript
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
*
|
|
377
|
+
* // Get all relationships (both directions)
|
|
378
|
+
* const all = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN');
|
|
379
|
+
*
|
|
380
|
+
* // Get only inbound relationships ("who references this entity?")
|
|
381
|
+
* const incoming = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN', 'incoming');
|
|
382
|
+
*
|
|
383
|
+
* // Get only outbound relationships (similar to IPFS, but from index)
|
|
384
|
+
* const outgoing = await graph.getRelationships('01K75HQQXNTDG7BBP7PS9AWYAN', 'outgoing');
|
|
385
|
+
*
|
|
386
|
+
* // Process by direction
|
|
387
|
+
* const rels = await graph.getRelationships('entity-id');
|
|
388
|
+
* rels.forEach(r => {
|
|
389
|
+
* if (r.direction === 'incoming') {
|
|
390
|
+
* console.log(`${r.target_label} references this entity via ${r.predicate}`);
|
|
391
|
+
* } else {
|
|
392
|
+
* console.log(`This entity ${r.predicate} -> ${r.target_label}`);
|
|
393
|
+
* }
|
|
365
394
|
* });
|
|
366
395
|
* ```
|
|
367
396
|
*/
|
|
368
|
-
getRelationships(
|
|
397
|
+
getRelationships(id: string, direction?: RelationshipDirection): Promise<Relationship[]>;
|
|
369
398
|
/**
|
|
370
399
|
* Find shortest paths between sets of entities.
|
|
371
400
|
*
|
|
@@ -377,8 +406,8 @@ declare class GraphClient {
|
|
|
377
406
|
* @example
|
|
378
407
|
* ```typescript
|
|
379
408
|
* const paths = await graph.findPaths(
|
|
380
|
-
* ['
|
|
381
|
-
* ['
|
|
409
|
+
* ['entity-alice'],
|
|
410
|
+
* ['entity-bob'],
|
|
382
411
|
* { max_depth: 4, direction: 'both' }
|
|
383
412
|
* );
|
|
384
413
|
*
|
|
@@ -403,7 +432,7 @@ declare class GraphClient {
|
|
|
403
432
|
* ```typescript
|
|
404
433
|
* // Find all people reachable from an event
|
|
405
434
|
* const people = await graph.findReachable(
|
|
406
|
-
* ['
|
|
435
|
+
* ['event-id'],
|
|
407
436
|
* 'person',
|
|
408
437
|
* { max_depth: 3 }
|
|
409
438
|
* );
|
|
@@ -453,4 +482,4 @@ declare class NetworkError extends GraphError {
|
|
|
453
482
|
constructor(message: string, statusCode?: number | undefined);
|
|
454
483
|
}
|
|
455
484
|
|
|
456
|
-
export { type EntitiesWithRelationshipsResponse, type EntityQueryResponse, type EntityWithRelationships, GraphClient, type GraphClientConfig, type GraphEntity, GraphEntityNotFoundError, GraphError, type LineagePiEntry, type LineageResponse, type LineageResultSet, type ListFromPiOptions, NetworkError, NoPathFoundError, type Path, type PathEdge, type PathOptions, type PathsResponse, type ReachableOptions, type Relationship };
|
|
485
|
+
export { type EntitiesWithRelationshipsResponse, type EntityQueryResponse, type EntityWithRelationships, GraphClient, type GraphClientConfig, type GraphEntity, GraphEntityNotFoundError, GraphError, type LineagePiEntry, type LineageResponse, type LineageResultSet, type ListFromPiOptions, NetworkError, NoPathFoundError, type Path, type PathEdge, type PathOptions, type PathsResponse, type ReachableOptions, type Relationship, type RelationshipDirection };
|