@grafema/types 0.2.5-beta → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -9
- package/dist/branded.d.ts +0 -7
- package/dist/branded.d.ts.map +1 -1
- package/dist/branded.js +0 -9
- package/dist/branded.js.map +1 -1
- package/dist/edges.d.ts +12 -0
- package/dist/edges.d.ts.map +1 -1
- package/dist/edges.js +15 -0
- package/dist/edges.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -2
- package/dist/index.js.map +1 -1
- package/dist/infrastructure.d.ts +169 -0
- package/dist/infrastructure.d.ts.map +1 -0
- package/dist/infrastructure.js +17 -0
- package/dist/infrastructure.js.map +1 -0
- package/dist/nodes.d.ts +33 -1
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +6 -1
- package/dist/nodes.js.map +1 -1
- package/dist/plugins.d.ts +40 -12
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js.map +1 -1
- package/dist/resources.d.ts +54 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +17 -0
- package/dist/resources.js.map +1 -0
- package/dist/rfdb.d.ts +129 -1
- package/dist/rfdb.d.ts.map +1 -1
- package/dist/routing.d.ts +85 -0
- package/dist/routing.d.ts.map +1 -0
- package/dist/routing.js +10 -0
- package/dist/routing.js.map +1 -0
- package/package.json +1 -1
- package/src/branded.ts +1 -11
- package/src/edges.ts +16 -0
- package/src/index.ts +12 -1
- package/src/infrastructure.ts +262 -0
- package/src/nodes.ts +47 -1
- package/src/plugins.ts +46 -14
- package/src/resources.ts +58 -0
- package/src/rfdb.ts +158 -1
- package/src/routing.ts +96 -0
package/src/rfdb.ts
CHANGED
|
@@ -46,6 +46,7 @@ export type RFDBCommand =
|
|
|
46
46
|
| 'datalogClearRules'
|
|
47
47
|
| 'datalogQuery'
|
|
48
48
|
| 'checkGuarantee'
|
|
49
|
+
| 'executeDatalog'
|
|
49
50
|
// Protocol v2 - Multi-Database Commands
|
|
50
51
|
| 'hello'
|
|
51
52
|
| 'createDatabase'
|
|
@@ -55,7 +56,14 @@ export type RFDBCommand =
|
|
|
55
56
|
| 'listDatabases'
|
|
56
57
|
| 'currentDatabase'
|
|
57
58
|
// Schema declaration
|
|
58
|
-
| 'declareFields'
|
|
59
|
+
| 'declareFields'
|
|
60
|
+
// Snapshot operations
|
|
61
|
+
| 'diffSnapshots'
|
|
62
|
+
| 'tagSnapshot'
|
|
63
|
+
| 'findSnapshot'
|
|
64
|
+
| 'listSnapshots'
|
|
65
|
+
// Batch operations
|
|
66
|
+
| 'commitBatch';
|
|
59
67
|
|
|
60
68
|
// === WIRE FORMAT ===
|
|
61
69
|
// Nodes as sent over the wire
|
|
@@ -66,6 +74,7 @@ export interface WireNode {
|
|
|
66
74
|
file: string;
|
|
67
75
|
exported: boolean;
|
|
68
76
|
metadata: string; // JSON string
|
|
77
|
+
semanticId?: string; // Protocol v3: human-readable semantic ID
|
|
69
78
|
}
|
|
70
79
|
|
|
71
80
|
// Edges as sent over the wire
|
|
@@ -79,6 +88,7 @@ export interface WireEdge {
|
|
|
79
88
|
// === REQUEST TYPES ===
|
|
80
89
|
export interface RFDBRequest {
|
|
81
90
|
cmd: RFDBCommand;
|
|
91
|
+
requestId?: string;
|
|
82
92
|
[key: string]: unknown;
|
|
83
93
|
}
|
|
84
94
|
|
|
@@ -170,6 +180,7 @@ export interface CountEdgesByTypeRequest extends RFDBRequest {
|
|
|
170
180
|
|
|
171
181
|
// === RESPONSE TYPES ===
|
|
172
182
|
export interface RFDBResponse {
|
|
183
|
+
requestId?: string;
|
|
173
184
|
error?: string;
|
|
174
185
|
[key: string]: unknown;
|
|
175
186
|
}
|
|
@@ -227,6 +238,52 @@ export interface PingResponse extends RFDBResponse {
|
|
|
227
238
|
version: string;
|
|
228
239
|
}
|
|
229
240
|
|
|
241
|
+
// === STREAMING RESPONSE TYPES ===
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* A chunk of nodes in a streaming QueryNodes response.
|
|
245
|
+
*
|
|
246
|
+
* Sent by the server when the result set exceeds the streaming threshold
|
|
247
|
+
* and the client negotiated protocol version >= 3.
|
|
248
|
+
* Multiple NodesChunk messages share the same requestId. The client
|
|
249
|
+
* accumulates chunks until `done === true`.
|
|
250
|
+
*
|
|
251
|
+
* Discrimination: if a response has a `done` field, it is a streaming chunk.
|
|
252
|
+
* If it does not, it is a legacy single-shot `Nodes { nodes }` response.
|
|
253
|
+
*/
|
|
254
|
+
export interface NodesChunkResponse extends RFDBResponse {
|
|
255
|
+
nodes: WireNode[];
|
|
256
|
+
/** true = last chunk for this requestId; false = more chunks coming */
|
|
257
|
+
done: boolean;
|
|
258
|
+
/** 0-based chunk index for ordering verification */
|
|
259
|
+
chunkIndex: number;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// === BATCH OPERATIONS ===
|
|
263
|
+
|
|
264
|
+
export interface CommitDelta {
|
|
265
|
+
changedFiles: string[];
|
|
266
|
+
nodesAdded: number;
|
|
267
|
+
nodesRemoved: number;
|
|
268
|
+
edgesAdded: number;
|
|
269
|
+
edgesRemoved: number;
|
|
270
|
+
changedNodeTypes: string[];
|
|
271
|
+
changedEdgeTypes: string[];
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export interface CommitBatchRequest extends RFDBRequest {
|
|
275
|
+
cmd: 'commitBatch';
|
|
276
|
+
changedFiles: string[];
|
|
277
|
+
nodes: WireNode[];
|
|
278
|
+
edges: WireEdge[];
|
|
279
|
+
tags?: string[];
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export interface CommitBatchResponse extends RFDBResponse {
|
|
283
|
+
ok: boolean;
|
|
284
|
+
delta: CommitDelta;
|
|
285
|
+
}
|
|
286
|
+
|
|
230
287
|
// === PROTOCOL V2 - MULTI-DATABASE RESPONSES ===
|
|
231
288
|
|
|
232
289
|
export interface HelloResponse extends RFDBResponse {
|
|
@@ -274,6 +331,7 @@ export interface AttrQuery {
|
|
|
274
331
|
name?: string;
|
|
275
332
|
file?: string;
|
|
276
333
|
exported?: boolean;
|
|
334
|
+
/** @deprecated Node-level version filter is legacy. In v2, use snapshot/tag APIs for history. */
|
|
277
335
|
version?: string;
|
|
278
336
|
/** Extra fields are matched against node metadata JSON (e.g. object, method, async) */
|
|
279
337
|
[key: string]: string | boolean | number | undefined;
|
|
@@ -299,10 +357,94 @@ export interface DatalogResult {
|
|
|
299
357
|
bindings: DatalogBinding;
|
|
300
358
|
}
|
|
301
359
|
|
|
360
|
+
// === SNAPSHOT TYPES ===
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Reference to a snapshot — either by version number or by tag key/value pair.
|
|
364
|
+
*
|
|
365
|
+
* When used as a number, refers to the snapshot at that version.
|
|
366
|
+
* When used as an object, resolves the snapshot tagged with the given key/value.
|
|
367
|
+
*/
|
|
368
|
+
export type SnapshotRef = number | { tag: string; value: string };
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Aggregate statistics for a snapshot (mirrors Rust ManifestStats).
|
|
372
|
+
*
|
|
373
|
+
* Wire format: camelCase (Rust snake_case fields mapped via serde rename).
|
|
374
|
+
*/
|
|
375
|
+
export interface SnapshotStats {
|
|
376
|
+
totalNodes: number;
|
|
377
|
+
totalEdges: number;
|
|
378
|
+
nodeSegmentCount: number;
|
|
379
|
+
edgeSegmentCount: number;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Segment descriptor — describes a single data segment in a snapshot.
|
|
384
|
+
*
|
|
385
|
+
* Simplified view of Rust SegmentDescriptor. Exposes fields relevant to
|
|
386
|
+
* client-side diff analysis. Internal fields (segmentType, shardId) omitted.
|
|
387
|
+
*
|
|
388
|
+
* Wire format: camelCase. HashSet<String> serializes as string[].
|
|
389
|
+
*/
|
|
390
|
+
export interface SegmentInfo {
|
|
391
|
+
segmentId: number;
|
|
392
|
+
recordCount: number;
|
|
393
|
+
byteSize: number;
|
|
394
|
+
nodeTypes: string[];
|
|
395
|
+
filePaths: string[];
|
|
396
|
+
edgeTypes: string[];
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Diff between two snapshots (from -> to).
|
|
401
|
+
*
|
|
402
|
+
* Shows which segments were added/removed and stats for both versions.
|
|
403
|
+
* Mirrors Rust SnapshotDiff (storage_v2/manifest.rs).
|
|
404
|
+
*/
|
|
405
|
+
export interface SnapshotDiff {
|
|
406
|
+
fromVersion: number;
|
|
407
|
+
toVersion: number;
|
|
408
|
+
addedNodeSegments: SegmentInfo[];
|
|
409
|
+
removedNodeSegments: SegmentInfo[];
|
|
410
|
+
addedEdgeSegments: SegmentInfo[];
|
|
411
|
+
removedEdgeSegments: SegmentInfo[];
|
|
412
|
+
statsFrom: SnapshotStats;
|
|
413
|
+
statsTo: SnapshotStats;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Lightweight snapshot information for list operations.
|
|
418
|
+
*
|
|
419
|
+
* Mirrors Rust SnapshotInfo (storage_v2/manifest.rs).
|
|
420
|
+
* createdAt is Unix epoch seconds (u64 in Rust).
|
|
421
|
+
*/
|
|
422
|
+
export interface SnapshotInfo {
|
|
423
|
+
version: number;
|
|
424
|
+
createdAt: number;
|
|
425
|
+
tags: Record<string, string>;
|
|
426
|
+
stats: SnapshotStats;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// Snapshot response types
|
|
430
|
+
|
|
431
|
+
export interface DiffSnapshotsResponse extends RFDBResponse {
|
|
432
|
+
diff: SnapshotDiff;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export interface FindSnapshotResponse extends RFDBResponse {
|
|
436
|
+
version: number | null;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export interface ListSnapshotsResponse extends RFDBResponse {
|
|
440
|
+
snapshots: SnapshotInfo[];
|
|
441
|
+
}
|
|
442
|
+
|
|
302
443
|
// === CLIENT INTERFACE ===
|
|
303
444
|
export interface IRFDBClient {
|
|
304
445
|
readonly socketPath: string;
|
|
305
446
|
readonly connected: boolean;
|
|
447
|
+
readonly supportsStreaming: boolean;
|
|
306
448
|
|
|
307
449
|
// Connection
|
|
308
450
|
connect(): Promise<void>;
|
|
@@ -325,6 +467,7 @@ export interface IRFDBClient {
|
|
|
325
467
|
findByType(nodeType: NodeType): Promise<string[]>;
|
|
326
468
|
findByAttr(query: Record<string, unknown>): Promise<string[]>;
|
|
327
469
|
queryNodes(query: AttrQuery): AsyncGenerator<WireNode, void, unknown>;
|
|
470
|
+
queryNodesStream(query: AttrQuery): AsyncGenerator<WireNode, void, unknown>;
|
|
328
471
|
getAllNodes(query?: AttrQuery): Promise<WireNode[]>;
|
|
329
472
|
getAllEdges(): Promise<WireEdge[]>;
|
|
330
473
|
isEndpoint(id: string): Promise<boolean>;
|
|
@@ -353,6 +496,14 @@ export interface IRFDBClient {
|
|
|
353
496
|
datalogClearRules(): Promise<RFDBResponse>;
|
|
354
497
|
datalogQuery(query: string): Promise<DatalogResult[]>;
|
|
355
498
|
checkGuarantee(ruleSource: string): Promise<DatalogResult[]>;
|
|
499
|
+
executeDatalog(source: string): Promise<DatalogResult[]>;
|
|
500
|
+
|
|
501
|
+
// Batch operations
|
|
502
|
+
beginBatch(): void;
|
|
503
|
+
commitBatch(tags?: string[]): Promise<CommitDelta>;
|
|
504
|
+
abortBatch(): void;
|
|
505
|
+
isBatching(): boolean;
|
|
506
|
+
findDependentFiles(changedFiles: string[]): Promise<string[]>;
|
|
356
507
|
|
|
357
508
|
// Protocol v2 - Multi-Database
|
|
358
509
|
hello(protocolVersion?: number): Promise<HelloResponse>;
|
|
@@ -362,4 +513,10 @@ export interface IRFDBClient {
|
|
|
362
513
|
dropDatabase(name: string): Promise<RFDBResponse>;
|
|
363
514
|
listDatabases(): Promise<ListDatabasesResponse>;
|
|
364
515
|
currentDatabase(): Promise<CurrentDatabaseResponse>;
|
|
516
|
+
|
|
517
|
+
// Snapshot operations
|
|
518
|
+
diffSnapshots(from: SnapshotRef, to: SnapshotRef): Promise<SnapshotDiff>;
|
|
519
|
+
tagSnapshot(version: number, tags: Record<string, string>): Promise<void>;
|
|
520
|
+
findSnapshot(tagKey: string, tagValue: string): Promise<number | null>;
|
|
521
|
+
listSnapshots(filterTag?: string): Promise<SnapshotInfo[]>;
|
|
365
522
|
}
|
package/src/routing.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Routing Types — cross-service URL mapping for infrastructure-level routing.
|
|
3
|
+
*
|
|
4
|
+
* The RoutingMap is source-agnostic. It doesn't know where rules came from
|
|
5
|
+
* (config.yaml, nginx.conf, k8s manifests). It only knows:
|
|
6
|
+
* "request from service A with path P routes to service B with path P'"
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { Resource } from './resources.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A routing rule describes how requests are transformed between services.
|
|
13
|
+
* Source-agnostic — can come from config.yaml, nginx.conf, k8s, etc.
|
|
14
|
+
*/
|
|
15
|
+
export interface RoutingRule {
|
|
16
|
+
/** Service where requests originate (matches ServiceDefinition.name) */
|
|
17
|
+
from: string;
|
|
18
|
+
/** Service where routes are defined (matches ServiceDefinition.name) */
|
|
19
|
+
to: string;
|
|
20
|
+
/** Path prefix to strip from request URL before matching.
|
|
21
|
+
* e.g., stripPrefix: '/api' transforms '/api/users' -> '/users' */
|
|
22
|
+
stripPrefix?: string;
|
|
23
|
+
/** Path prefix to add to request URL before matching.
|
|
24
|
+
* e.g., addPrefix: '/v2' transforms '/users' -> '/v2/users' */
|
|
25
|
+
addPrefix?: string;
|
|
26
|
+
/** Source of this rule (for debugging/traceability) */
|
|
27
|
+
source?: string;
|
|
28
|
+
/** Priority — lower numbers match first. Default: 0 */
|
|
29
|
+
priority?: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Context for matching a request against the routing map.
|
|
34
|
+
*/
|
|
35
|
+
export interface MatchContext {
|
|
36
|
+
/** Service name where the request originates */
|
|
37
|
+
fromService: string;
|
|
38
|
+
/** Original request URL (before any transformation) */
|
|
39
|
+
requestUrl: string;
|
|
40
|
+
/** HTTP method (optional, for future method-based routing) */
|
|
41
|
+
method?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Result of a routing match — the transformed URL to use for matching.
|
|
46
|
+
*/
|
|
47
|
+
export interface MatchResult {
|
|
48
|
+
/** Transformed URL to match against route paths */
|
|
49
|
+
transformedUrl: string;
|
|
50
|
+
/** Service name where the route should be found */
|
|
51
|
+
targetService: string;
|
|
52
|
+
/** The rule that matched */
|
|
53
|
+
rule: RoutingRule;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* RoutingMap Resource — abstract routing table built by multiple builder plugins.
|
|
58
|
+
*
|
|
59
|
+
* Resource ID: 'routing:map'
|
|
60
|
+
*/
|
|
61
|
+
export interface RoutingMap extends Resource {
|
|
62
|
+
readonly id: 'routing:map';
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Add a routing rule. Called by builder plugins during ENRICHMENT phase.
|
|
66
|
+
* Duplicate rules (same from/to/strip/add) are silently deduplicated.
|
|
67
|
+
*/
|
|
68
|
+
addRule(rule: RoutingRule): void;
|
|
69
|
+
|
|
70
|
+
/** Add multiple rules at once. */
|
|
71
|
+
addRules(rules: RoutingRule[]): void;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Find matching route transformation for a request context.
|
|
75
|
+
*
|
|
76
|
+
* If multiple rules match, returns the most specific one:
|
|
77
|
+
* 1. Rules with longer stripPrefix match first (more specific)
|
|
78
|
+
* 2. Among equal-length prefixes, lower priority number wins
|
|
79
|
+
* 3. If still tied, first-added wins
|
|
80
|
+
*
|
|
81
|
+
* @returns MatchResult if a rule matches, null if no rule applies
|
|
82
|
+
*/
|
|
83
|
+
findMatch(context: MatchContext): MatchResult | null;
|
|
84
|
+
|
|
85
|
+
/** Find ALL matching rules for a from/to service pair. */
|
|
86
|
+
findRulesForPair(fromService: string, toService: string): RoutingRule[];
|
|
87
|
+
|
|
88
|
+
/** Get all rules (for debugging/logging). */
|
|
89
|
+
getAllRules(): RoutingRule[];
|
|
90
|
+
|
|
91
|
+
/** Get count of rules (for metrics). */
|
|
92
|
+
get ruleCount(): number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Well-known Resource ID for the RoutingMap */
|
|
96
|
+
export const ROUTING_MAP_RESOURCE_ID = 'routing:map' as const;
|