@neat.is/core 0.6.4 → 0.7.1
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/{chunk-7QXN726V.js → chunk-6H757ZNM.js} +2 -2
- package/dist/chunk-MDBE23Y3.js +840 -0
- package/dist/chunk-MDBE23Y3.js.map +1 -0
- package/dist/{chunk-ZLAZ7PLC.js → chunk-P2ZEKJ35.js} +45 -2
- package/dist/chunk-P2ZEKJ35.js.map +1 -0
- package/dist/{chunk-UCDXHLCJ.js → chunk-RR4LWQQB.js} +3929 -677
- package/dist/chunk-RR4LWQQB.js.map +1 -0
- package/dist/cli.cjs +5030 -3535
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +284 -136
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +4554 -3210
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +121 -106
- package/dist/index.d.ts +121 -106
- package/dist/index.js +4 -4
- package/dist/neatd.cjs +4579 -3235
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +3 -3
- package/dist/{otel-grpc-WXKM7YBW.js → otel-grpc-APVZSB6W.js} +3 -3
- package/dist/server.cjs +4103 -884
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +3 -3
- package/package.json +3 -2
- package/dist/chunk-22X2YM5H.js +0 -2810
- package/dist/chunk-22X2YM5H.js.map +0 -1
- package/dist/chunk-UCDXHLCJ.js.map +0 -1
- package/dist/chunk-ZLAZ7PLC.js.map +0 -1
- /package/dist/{chunk-7QXN726V.js.map → chunk-6H757ZNM.js.map} +0 -0
- /package/dist/{otel-grpc-WXKM7YBW.js.map → otel-grpc-APVZSB6W.js.map} +0 -0
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MultiDirectedGraph } from 'graphology';
|
|
2
|
-
import { GraphNode, GraphEdge, StaleEvent, ErrorEvent, BlastRadiusResult, RootCauseResult,
|
|
2
|
+
import { GraphNode, GraphEdge, EdgeTypeValue, StaleEvent, ErrorEvent, BlastRadiusResult, RootCauseResult, RegistryEntry, RegistryStatus, RegistryFile } from '@neat.is/types';
|
|
3
3
|
export { StaleEvent } from '@neat.is/types';
|
|
4
4
|
import { FastifyInstance } from 'fastify';
|
|
5
5
|
|
|
@@ -110,6 +110,124 @@ declare class Projects {
|
|
|
110
110
|
attachSearchIndex(name: string, index: SearchIndex | undefined): void;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
/**
|
|
114
|
+
* A connector implements exactly one method. Everything downstream of
|
|
115
|
+
* `poll()` — resolving a static call site, minting the OBSERVED edge — is
|
|
116
|
+
* shared, generic code in connectors/index.ts.
|
|
117
|
+
*/
|
|
118
|
+
interface ObservedConnector {
|
|
119
|
+
readonly provider: string;
|
|
120
|
+
poll(ctx: ConnectorContext): Promise<ObservedSignal[]>;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Everything a connector's `poll()` needs, resolved once at connector setup
|
|
124
|
+
* — never re-derived at poll time.
|
|
125
|
+
*
|
|
126
|
+
* `credentials` is opaque here on purpose: its shape is entirely provider-
|
|
127
|
+
* and profile-defined (local vs hosted — docs/contracts/connectors.md §3).
|
|
128
|
+
* It flows through to `poll()` only. Never log it, never write it into a
|
|
129
|
+
* node or edge, never let it reach the graph snapshot (contract §6, and the
|
|
130
|
+
* `.env`-contents rule docs/contracts.md Rule 4 already states for local
|
|
131
|
+
* config).
|
|
132
|
+
*/
|
|
133
|
+
interface ConnectorContext {
|
|
134
|
+
projectDir: string;
|
|
135
|
+
credentials: Record<string, unknown>;
|
|
136
|
+
since?: string;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* `file:line` the provider's own signal carries, when it does (rare — see
|
|
140
|
+
* docs/connectors/README.md §Provider interface, which notes this is
|
|
141
|
+
* "usually resolved by the mapping layer below, not here"). Reconciled onto
|
|
142
|
+
* the EXTRACTED service-relative path by the shared fuse step the same way
|
|
143
|
+
* an OTel span's call site is (file-awareness.md §4).
|
|
144
|
+
*/
|
|
145
|
+
interface ConnectorCallSite {
|
|
146
|
+
file: string;
|
|
147
|
+
line: number;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* One provider-agnostic observation. `targetKind`/`targetName` are the
|
|
151
|
+
* provider's own vocabulary (`'supabase-table'`/`'orders'`,
|
|
152
|
+
* `'route'`/`'GET /users/:id'`, ...) — resolving that pair to a NEAT node id
|
|
153
|
+
* is the one genuinely provider-specific step (README.md's pipeline
|
|
154
|
+
* diagram), supplied to `runConnectorPoll` (connectors/index.ts) as a
|
|
155
|
+
* `resolveTarget` callback. Everything downstream of that resolution — file
|
|
156
|
+
* grain fusion, OBSERVED mint — is shared.
|
|
157
|
+
*/
|
|
158
|
+
interface ObservedSignal {
|
|
159
|
+
targetKind: string;
|
|
160
|
+
targetName: string;
|
|
161
|
+
callCount: number;
|
|
162
|
+
errorCount: number;
|
|
163
|
+
lastObservedIso: string;
|
|
164
|
+
callSite?: ConnectorCallSite;
|
|
165
|
+
columns?: string[];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* What a provider's target-resolution step hands back for one signal. The
|
|
170
|
+
* generic pipeline needs both endpoints of the edge it's about to mint:
|
|
171
|
+
*
|
|
172
|
+
* - `serviceName` is the NEAT manifest service whose code produced the
|
|
173
|
+
* signal — the edge's source. The shared pipeline turns it into a plain
|
|
174
|
+
* ServiceNode id, or a FileNode id once the fuse step below resolves the
|
|
175
|
+
* signal's callSite against it.
|
|
176
|
+
* - `targetNodeId` is the id the provider's own mapping already resolved —
|
|
177
|
+
* an `infraId(...)` sub-resource, a RouteNode, a ServiceNode, whatever
|
|
178
|
+
* (see each provider's docs/connectors/<provider>.md §Fusion).
|
|
179
|
+
*
|
|
180
|
+
* Returning `null` skips the signal honestly: an unresolvable target never
|
|
181
|
+
* fabricates a node or edge (the same discipline file-awareness.md §6
|
|
182
|
+
* states for OTel ingest).
|
|
183
|
+
*/
|
|
184
|
+
interface ResolvedConnectorTarget {
|
|
185
|
+
targetNodeId: string;
|
|
186
|
+
serviceName: string;
|
|
187
|
+
edgeType: EdgeTypeValue;
|
|
188
|
+
/**
|
|
189
|
+
* Set when `targetNodeId` names an InfraNode no static extractor has (yet)
|
|
190
|
+
* declared — the honest "observed but undeclared" fallback
|
|
191
|
+
* (docs/contracts/connectors.md §4a, ADR-133). A provider's `resolveTarget`
|
|
192
|
+
* has no mutation authority of its own (ADR-030), so it declares the need
|
|
193
|
+
* here instead of creating the node itself; the generic pipeline below
|
|
194
|
+
* calls `ensureInfraNode` before minting the edge. `targetNodeId` MUST equal
|
|
195
|
+
* `infraId(kind, name)` when this is set.
|
|
196
|
+
*/
|
|
197
|
+
ensureInfraNode?: {
|
|
198
|
+
kind: string;
|
|
199
|
+
name: string;
|
|
200
|
+
provider: string;
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
type ResolveConnectorTarget = (signal: ObservedSignal, ctx: ConnectorContext) => ResolvedConnectorTarget | null;
|
|
204
|
+
interface ConnectorPollResult {
|
|
205
|
+
signalCount: number;
|
|
206
|
+
edgesCreated: number;
|
|
207
|
+
edgesUpdated: number;
|
|
208
|
+
unresolved: number;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* One poll cycle: fetch, map, fuse, mint. Pure with respect to `ctx` — the
|
|
212
|
+
* caller (`startConnectorPollLoop` below, or a one-shot `neat sync`) owns
|
|
213
|
+
* advancing `ctx.since` between calls.
|
|
214
|
+
*/
|
|
215
|
+
declare function runConnectorPoll(connector: ObservedConnector, ctx: ConnectorContext, graph: NeatGraph, resolveTarget: ResolveConnectorTarget): Promise<ConnectorPollResult>;
|
|
216
|
+
/**
|
|
217
|
+
* One project's registered connector, ready for `daemon.ts` to poll on an
|
|
218
|
+
* interval. Deliberately thin — no config-loading or credential-broker logic
|
|
219
|
+
* lives here (that's provider- and profile-specific, later work per
|
|
220
|
+
* docs/contracts/connectors.md §3); this is just the seam a daemon slot
|
|
221
|
+
* wires a connector through.
|
|
222
|
+
*/
|
|
223
|
+
interface ConnectorRegistration {
|
|
224
|
+
id?: string;
|
|
225
|
+
connector: ObservedConnector;
|
|
226
|
+
credentials: Record<string, unknown>;
|
|
227
|
+
resolveTarget: ResolveConnectorTarget;
|
|
228
|
+
intervalMs?: number;
|
|
229
|
+
}
|
|
230
|
+
|
|
113
231
|
interface BuildApiOptions {
|
|
114
232
|
projects?: Projects;
|
|
115
233
|
startedAt?: number;
|
|
@@ -134,6 +252,7 @@ interface BuildApiOptions {
|
|
|
134
252
|
path: string;
|
|
135
253
|
};
|
|
136
254
|
connectorsHome?: string;
|
|
255
|
+
runPoll?: typeof runConnectorPoll;
|
|
137
256
|
}
|
|
138
257
|
declare function buildApi(opts: BuildApiOptions): Promise<FastifyInstance>;
|
|
139
258
|
|
|
@@ -155,6 +274,7 @@ interface ParsedSpan {
|
|
|
155
274
|
dbName?: string;
|
|
156
275
|
dbCollection?: string;
|
|
157
276
|
dbTable?: string;
|
|
277
|
+
dbColumns?: string[];
|
|
158
278
|
httpRoute?: string;
|
|
159
279
|
httpMethod?: string;
|
|
160
280
|
messagingSystem?: string;
|
|
@@ -349,111 +469,6 @@ interface GraphDiff {
|
|
|
349
469
|
declare function loadSnapshotForDiff(target: string): Promise<PersistedSnapshot>;
|
|
350
470
|
declare function computeGraphDiff(liveGraph: NeatGraph, baseSnapshot: PersistedSnapshot, currentExportedAt?: string): GraphDiff;
|
|
351
471
|
|
|
352
|
-
/**
|
|
353
|
-
* A connector implements exactly one method. Everything downstream of
|
|
354
|
-
* `poll()` — resolving a static call site, minting the OBSERVED edge — is
|
|
355
|
-
* shared, generic code in connectors/index.ts.
|
|
356
|
-
*/
|
|
357
|
-
interface ObservedConnector {
|
|
358
|
-
readonly provider: string;
|
|
359
|
-
poll(ctx: ConnectorContext): Promise<ObservedSignal[]>;
|
|
360
|
-
}
|
|
361
|
-
/**
|
|
362
|
-
* Everything a connector's `poll()` needs, resolved once at connector setup
|
|
363
|
-
* — never re-derived at poll time.
|
|
364
|
-
*
|
|
365
|
-
* `credentials` is opaque here on purpose: its shape is entirely provider-
|
|
366
|
-
* and profile-defined (local vs hosted — docs/contracts/connectors.md §3).
|
|
367
|
-
* It flows through to `poll()` only. Never log it, never write it into a
|
|
368
|
-
* node or edge, never let it reach the graph snapshot (contract §6, and the
|
|
369
|
-
* `.env`-contents rule docs/contracts.md Rule 4 already states for local
|
|
370
|
-
* config).
|
|
371
|
-
*/
|
|
372
|
-
interface ConnectorContext {
|
|
373
|
-
projectDir: string;
|
|
374
|
-
credentials: Record<string, unknown>;
|
|
375
|
-
since?: string;
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* `file:line` the provider's own signal carries, when it does (rare — see
|
|
379
|
-
* docs/connectors/README.md §Provider interface, which notes this is
|
|
380
|
-
* "usually resolved by the mapping layer below, not here"). Reconciled onto
|
|
381
|
-
* the EXTRACTED service-relative path by the shared fuse step the same way
|
|
382
|
-
* an OTel span's call site is (file-awareness.md §4).
|
|
383
|
-
*/
|
|
384
|
-
interface ConnectorCallSite {
|
|
385
|
-
file: string;
|
|
386
|
-
line: number;
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* One provider-agnostic observation. `targetKind`/`targetName` are the
|
|
390
|
-
* provider's own vocabulary (`'supabase-table'`/`'orders'`,
|
|
391
|
-
* `'route'`/`'GET /users/:id'`, ...) — resolving that pair to a NEAT node id
|
|
392
|
-
* is the one genuinely provider-specific step (README.md's pipeline
|
|
393
|
-
* diagram), supplied to `runConnectorPoll` (connectors/index.ts) as a
|
|
394
|
-
* `resolveTarget` callback. Everything downstream of that resolution — file
|
|
395
|
-
* grain fusion, OBSERVED mint — is shared.
|
|
396
|
-
*/
|
|
397
|
-
interface ObservedSignal {
|
|
398
|
-
targetKind: string;
|
|
399
|
-
targetName: string;
|
|
400
|
-
callCount: number;
|
|
401
|
-
errorCount: number;
|
|
402
|
-
lastObservedIso: string;
|
|
403
|
-
callSite?: ConnectorCallSite;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
/**
|
|
407
|
-
* What a provider's target-resolution step hands back for one signal. The
|
|
408
|
-
* generic pipeline needs both endpoints of the edge it's about to mint:
|
|
409
|
-
*
|
|
410
|
-
* - `serviceName` is the NEAT manifest service whose code produced the
|
|
411
|
-
* signal — the edge's source. The shared pipeline turns it into a plain
|
|
412
|
-
* ServiceNode id, or a FileNode id once the fuse step below resolves the
|
|
413
|
-
* signal's callSite against it.
|
|
414
|
-
* - `targetNodeId` is the id the provider's own mapping already resolved —
|
|
415
|
-
* an `infraId(...)` sub-resource, a RouteNode, a ServiceNode, whatever
|
|
416
|
-
* (see each provider's docs/connectors/<provider>.md §Fusion).
|
|
417
|
-
*
|
|
418
|
-
* Returning `null` skips the signal honestly: an unresolvable target never
|
|
419
|
-
* fabricates a node or edge (the same discipline file-awareness.md §6
|
|
420
|
-
* states for OTel ingest).
|
|
421
|
-
*/
|
|
422
|
-
interface ResolvedConnectorTarget {
|
|
423
|
-
targetNodeId: string;
|
|
424
|
-
serviceName: string;
|
|
425
|
-
edgeType: EdgeTypeValue;
|
|
426
|
-
/**
|
|
427
|
-
* Set when `targetNodeId` names an InfraNode no static extractor has (yet)
|
|
428
|
-
* declared — the honest "observed but undeclared" fallback
|
|
429
|
-
* (docs/contracts/connectors.md §4a, ADR-133). A provider's `resolveTarget`
|
|
430
|
-
* has no mutation authority of its own (ADR-030), so it declares the need
|
|
431
|
-
* here instead of creating the node itself; the generic pipeline below
|
|
432
|
-
* calls `ensureInfraNode` before minting the edge. `targetNodeId` MUST equal
|
|
433
|
-
* `infraId(kind, name)` when this is set.
|
|
434
|
-
*/
|
|
435
|
-
ensureInfraNode?: {
|
|
436
|
-
kind: string;
|
|
437
|
-
name: string;
|
|
438
|
-
provider: string;
|
|
439
|
-
};
|
|
440
|
-
}
|
|
441
|
-
type ResolveConnectorTarget = (signal: ObservedSignal, ctx: ConnectorContext) => ResolvedConnectorTarget | null;
|
|
442
|
-
/**
|
|
443
|
-
* One project's registered connector, ready for `daemon.ts` to poll on an
|
|
444
|
-
* interval. Deliberately thin — no config-loading or credential-broker logic
|
|
445
|
-
* lives here (that's provider- and profile-specific, later work per
|
|
446
|
-
* docs/contracts/connectors.md §3); this is just the seam a daemon slot
|
|
447
|
-
* wires a connector through.
|
|
448
|
-
*/
|
|
449
|
-
interface ConnectorRegistration {
|
|
450
|
-
id?: string;
|
|
451
|
-
connector: ObservedConnector;
|
|
452
|
-
credentials: Record<string, unknown>;
|
|
453
|
-
resolveTarget: ResolveConnectorTarget;
|
|
454
|
-
intervalMs?: number;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
472
|
/**
|
|
458
473
|
* Multi-project daemon (ADR-049).
|
|
459
474
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MultiDirectedGraph } from 'graphology';
|
|
2
|
-
import { GraphNode, GraphEdge, StaleEvent, ErrorEvent, BlastRadiusResult, RootCauseResult,
|
|
2
|
+
import { GraphNode, GraphEdge, EdgeTypeValue, StaleEvent, ErrorEvent, BlastRadiusResult, RootCauseResult, RegistryEntry, RegistryStatus, RegistryFile } from '@neat.is/types';
|
|
3
3
|
export { StaleEvent } from '@neat.is/types';
|
|
4
4
|
import { FastifyInstance } from 'fastify';
|
|
5
5
|
|
|
@@ -110,6 +110,124 @@ declare class Projects {
|
|
|
110
110
|
attachSearchIndex(name: string, index: SearchIndex | undefined): void;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
/**
|
|
114
|
+
* A connector implements exactly one method. Everything downstream of
|
|
115
|
+
* `poll()` — resolving a static call site, minting the OBSERVED edge — is
|
|
116
|
+
* shared, generic code in connectors/index.ts.
|
|
117
|
+
*/
|
|
118
|
+
interface ObservedConnector {
|
|
119
|
+
readonly provider: string;
|
|
120
|
+
poll(ctx: ConnectorContext): Promise<ObservedSignal[]>;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Everything a connector's `poll()` needs, resolved once at connector setup
|
|
124
|
+
* — never re-derived at poll time.
|
|
125
|
+
*
|
|
126
|
+
* `credentials` is opaque here on purpose: its shape is entirely provider-
|
|
127
|
+
* and profile-defined (local vs hosted — docs/contracts/connectors.md §3).
|
|
128
|
+
* It flows through to `poll()` only. Never log it, never write it into a
|
|
129
|
+
* node or edge, never let it reach the graph snapshot (contract §6, and the
|
|
130
|
+
* `.env`-contents rule docs/contracts.md Rule 4 already states for local
|
|
131
|
+
* config).
|
|
132
|
+
*/
|
|
133
|
+
interface ConnectorContext {
|
|
134
|
+
projectDir: string;
|
|
135
|
+
credentials: Record<string, unknown>;
|
|
136
|
+
since?: string;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* `file:line` the provider's own signal carries, when it does (rare — see
|
|
140
|
+
* docs/connectors/README.md §Provider interface, which notes this is
|
|
141
|
+
* "usually resolved by the mapping layer below, not here"). Reconciled onto
|
|
142
|
+
* the EXTRACTED service-relative path by the shared fuse step the same way
|
|
143
|
+
* an OTel span's call site is (file-awareness.md §4).
|
|
144
|
+
*/
|
|
145
|
+
interface ConnectorCallSite {
|
|
146
|
+
file: string;
|
|
147
|
+
line: number;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* One provider-agnostic observation. `targetKind`/`targetName` are the
|
|
151
|
+
* provider's own vocabulary (`'supabase-table'`/`'orders'`,
|
|
152
|
+
* `'route'`/`'GET /users/:id'`, ...) — resolving that pair to a NEAT node id
|
|
153
|
+
* is the one genuinely provider-specific step (README.md's pipeline
|
|
154
|
+
* diagram), supplied to `runConnectorPoll` (connectors/index.ts) as a
|
|
155
|
+
* `resolveTarget` callback. Everything downstream of that resolution — file
|
|
156
|
+
* grain fusion, OBSERVED mint — is shared.
|
|
157
|
+
*/
|
|
158
|
+
interface ObservedSignal {
|
|
159
|
+
targetKind: string;
|
|
160
|
+
targetName: string;
|
|
161
|
+
callCount: number;
|
|
162
|
+
errorCount: number;
|
|
163
|
+
lastObservedIso: string;
|
|
164
|
+
callSite?: ConnectorCallSite;
|
|
165
|
+
columns?: string[];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* What a provider's target-resolution step hands back for one signal. The
|
|
170
|
+
* generic pipeline needs both endpoints of the edge it's about to mint:
|
|
171
|
+
*
|
|
172
|
+
* - `serviceName` is the NEAT manifest service whose code produced the
|
|
173
|
+
* signal — the edge's source. The shared pipeline turns it into a plain
|
|
174
|
+
* ServiceNode id, or a FileNode id once the fuse step below resolves the
|
|
175
|
+
* signal's callSite against it.
|
|
176
|
+
* - `targetNodeId` is the id the provider's own mapping already resolved —
|
|
177
|
+
* an `infraId(...)` sub-resource, a RouteNode, a ServiceNode, whatever
|
|
178
|
+
* (see each provider's docs/connectors/<provider>.md §Fusion).
|
|
179
|
+
*
|
|
180
|
+
* Returning `null` skips the signal honestly: an unresolvable target never
|
|
181
|
+
* fabricates a node or edge (the same discipline file-awareness.md §6
|
|
182
|
+
* states for OTel ingest).
|
|
183
|
+
*/
|
|
184
|
+
interface ResolvedConnectorTarget {
|
|
185
|
+
targetNodeId: string;
|
|
186
|
+
serviceName: string;
|
|
187
|
+
edgeType: EdgeTypeValue;
|
|
188
|
+
/**
|
|
189
|
+
* Set when `targetNodeId` names an InfraNode no static extractor has (yet)
|
|
190
|
+
* declared — the honest "observed but undeclared" fallback
|
|
191
|
+
* (docs/contracts/connectors.md §4a, ADR-133). A provider's `resolveTarget`
|
|
192
|
+
* has no mutation authority of its own (ADR-030), so it declares the need
|
|
193
|
+
* here instead of creating the node itself; the generic pipeline below
|
|
194
|
+
* calls `ensureInfraNode` before minting the edge. `targetNodeId` MUST equal
|
|
195
|
+
* `infraId(kind, name)` when this is set.
|
|
196
|
+
*/
|
|
197
|
+
ensureInfraNode?: {
|
|
198
|
+
kind: string;
|
|
199
|
+
name: string;
|
|
200
|
+
provider: string;
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
type ResolveConnectorTarget = (signal: ObservedSignal, ctx: ConnectorContext) => ResolvedConnectorTarget | null;
|
|
204
|
+
interface ConnectorPollResult {
|
|
205
|
+
signalCount: number;
|
|
206
|
+
edgesCreated: number;
|
|
207
|
+
edgesUpdated: number;
|
|
208
|
+
unresolved: number;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* One poll cycle: fetch, map, fuse, mint. Pure with respect to `ctx` — the
|
|
212
|
+
* caller (`startConnectorPollLoop` below, or a one-shot `neat sync`) owns
|
|
213
|
+
* advancing `ctx.since` between calls.
|
|
214
|
+
*/
|
|
215
|
+
declare function runConnectorPoll(connector: ObservedConnector, ctx: ConnectorContext, graph: NeatGraph, resolveTarget: ResolveConnectorTarget): Promise<ConnectorPollResult>;
|
|
216
|
+
/**
|
|
217
|
+
* One project's registered connector, ready for `daemon.ts` to poll on an
|
|
218
|
+
* interval. Deliberately thin — no config-loading or credential-broker logic
|
|
219
|
+
* lives here (that's provider- and profile-specific, later work per
|
|
220
|
+
* docs/contracts/connectors.md §3); this is just the seam a daemon slot
|
|
221
|
+
* wires a connector through.
|
|
222
|
+
*/
|
|
223
|
+
interface ConnectorRegistration {
|
|
224
|
+
id?: string;
|
|
225
|
+
connector: ObservedConnector;
|
|
226
|
+
credentials: Record<string, unknown>;
|
|
227
|
+
resolveTarget: ResolveConnectorTarget;
|
|
228
|
+
intervalMs?: number;
|
|
229
|
+
}
|
|
230
|
+
|
|
113
231
|
interface BuildApiOptions {
|
|
114
232
|
projects?: Projects;
|
|
115
233
|
startedAt?: number;
|
|
@@ -134,6 +252,7 @@ interface BuildApiOptions {
|
|
|
134
252
|
path: string;
|
|
135
253
|
};
|
|
136
254
|
connectorsHome?: string;
|
|
255
|
+
runPoll?: typeof runConnectorPoll;
|
|
137
256
|
}
|
|
138
257
|
declare function buildApi(opts: BuildApiOptions): Promise<FastifyInstance>;
|
|
139
258
|
|
|
@@ -155,6 +274,7 @@ interface ParsedSpan {
|
|
|
155
274
|
dbName?: string;
|
|
156
275
|
dbCollection?: string;
|
|
157
276
|
dbTable?: string;
|
|
277
|
+
dbColumns?: string[];
|
|
158
278
|
httpRoute?: string;
|
|
159
279
|
httpMethod?: string;
|
|
160
280
|
messagingSystem?: string;
|
|
@@ -349,111 +469,6 @@ interface GraphDiff {
|
|
|
349
469
|
declare function loadSnapshotForDiff(target: string): Promise<PersistedSnapshot>;
|
|
350
470
|
declare function computeGraphDiff(liveGraph: NeatGraph, baseSnapshot: PersistedSnapshot, currentExportedAt?: string): GraphDiff;
|
|
351
471
|
|
|
352
|
-
/**
|
|
353
|
-
* A connector implements exactly one method. Everything downstream of
|
|
354
|
-
* `poll()` — resolving a static call site, minting the OBSERVED edge — is
|
|
355
|
-
* shared, generic code in connectors/index.ts.
|
|
356
|
-
*/
|
|
357
|
-
interface ObservedConnector {
|
|
358
|
-
readonly provider: string;
|
|
359
|
-
poll(ctx: ConnectorContext): Promise<ObservedSignal[]>;
|
|
360
|
-
}
|
|
361
|
-
/**
|
|
362
|
-
* Everything a connector's `poll()` needs, resolved once at connector setup
|
|
363
|
-
* — never re-derived at poll time.
|
|
364
|
-
*
|
|
365
|
-
* `credentials` is opaque here on purpose: its shape is entirely provider-
|
|
366
|
-
* and profile-defined (local vs hosted — docs/contracts/connectors.md §3).
|
|
367
|
-
* It flows through to `poll()` only. Never log it, never write it into a
|
|
368
|
-
* node or edge, never let it reach the graph snapshot (contract §6, and the
|
|
369
|
-
* `.env`-contents rule docs/contracts.md Rule 4 already states for local
|
|
370
|
-
* config).
|
|
371
|
-
*/
|
|
372
|
-
interface ConnectorContext {
|
|
373
|
-
projectDir: string;
|
|
374
|
-
credentials: Record<string, unknown>;
|
|
375
|
-
since?: string;
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* `file:line` the provider's own signal carries, when it does (rare — see
|
|
379
|
-
* docs/connectors/README.md §Provider interface, which notes this is
|
|
380
|
-
* "usually resolved by the mapping layer below, not here"). Reconciled onto
|
|
381
|
-
* the EXTRACTED service-relative path by the shared fuse step the same way
|
|
382
|
-
* an OTel span's call site is (file-awareness.md §4).
|
|
383
|
-
*/
|
|
384
|
-
interface ConnectorCallSite {
|
|
385
|
-
file: string;
|
|
386
|
-
line: number;
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* One provider-agnostic observation. `targetKind`/`targetName` are the
|
|
390
|
-
* provider's own vocabulary (`'supabase-table'`/`'orders'`,
|
|
391
|
-
* `'route'`/`'GET /users/:id'`, ...) — resolving that pair to a NEAT node id
|
|
392
|
-
* is the one genuinely provider-specific step (README.md's pipeline
|
|
393
|
-
* diagram), supplied to `runConnectorPoll` (connectors/index.ts) as a
|
|
394
|
-
* `resolveTarget` callback. Everything downstream of that resolution — file
|
|
395
|
-
* grain fusion, OBSERVED mint — is shared.
|
|
396
|
-
*/
|
|
397
|
-
interface ObservedSignal {
|
|
398
|
-
targetKind: string;
|
|
399
|
-
targetName: string;
|
|
400
|
-
callCount: number;
|
|
401
|
-
errorCount: number;
|
|
402
|
-
lastObservedIso: string;
|
|
403
|
-
callSite?: ConnectorCallSite;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
/**
|
|
407
|
-
* What a provider's target-resolution step hands back for one signal. The
|
|
408
|
-
* generic pipeline needs both endpoints of the edge it's about to mint:
|
|
409
|
-
*
|
|
410
|
-
* - `serviceName` is the NEAT manifest service whose code produced the
|
|
411
|
-
* signal — the edge's source. The shared pipeline turns it into a plain
|
|
412
|
-
* ServiceNode id, or a FileNode id once the fuse step below resolves the
|
|
413
|
-
* signal's callSite against it.
|
|
414
|
-
* - `targetNodeId` is the id the provider's own mapping already resolved —
|
|
415
|
-
* an `infraId(...)` sub-resource, a RouteNode, a ServiceNode, whatever
|
|
416
|
-
* (see each provider's docs/connectors/<provider>.md §Fusion).
|
|
417
|
-
*
|
|
418
|
-
* Returning `null` skips the signal honestly: an unresolvable target never
|
|
419
|
-
* fabricates a node or edge (the same discipline file-awareness.md §6
|
|
420
|
-
* states for OTel ingest).
|
|
421
|
-
*/
|
|
422
|
-
interface ResolvedConnectorTarget {
|
|
423
|
-
targetNodeId: string;
|
|
424
|
-
serviceName: string;
|
|
425
|
-
edgeType: EdgeTypeValue;
|
|
426
|
-
/**
|
|
427
|
-
* Set when `targetNodeId` names an InfraNode no static extractor has (yet)
|
|
428
|
-
* declared — the honest "observed but undeclared" fallback
|
|
429
|
-
* (docs/contracts/connectors.md §4a, ADR-133). A provider's `resolveTarget`
|
|
430
|
-
* has no mutation authority of its own (ADR-030), so it declares the need
|
|
431
|
-
* here instead of creating the node itself; the generic pipeline below
|
|
432
|
-
* calls `ensureInfraNode` before minting the edge. `targetNodeId` MUST equal
|
|
433
|
-
* `infraId(kind, name)` when this is set.
|
|
434
|
-
*/
|
|
435
|
-
ensureInfraNode?: {
|
|
436
|
-
kind: string;
|
|
437
|
-
name: string;
|
|
438
|
-
provider: string;
|
|
439
|
-
};
|
|
440
|
-
}
|
|
441
|
-
type ResolveConnectorTarget = (signal: ObservedSignal, ctx: ConnectorContext) => ResolvedConnectorTarget | null;
|
|
442
|
-
/**
|
|
443
|
-
* One project's registered connector, ready for `daemon.ts` to poll on an
|
|
444
|
-
* interval. Deliberately thin — no config-loading or credential-broker logic
|
|
445
|
-
* lives here (that's provider- and profile-specific, later work per
|
|
446
|
-
* docs/contracts/connectors.md §3); this is just the seam a daemon slot
|
|
447
|
-
* wires a connector through.
|
|
448
|
-
*/
|
|
449
|
-
interface ConnectorRegistration {
|
|
450
|
-
id?: string;
|
|
451
|
-
connector: ObservedConnector;
|
|
452
|
-
credentials: Record<string, unknown>;
|
|
453
|
-
resolveTarget: ResolveConnectorTarget;
|
|
454
|
-
intervalMs?: number;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
472
|
/**
|
|
458
473
|
* Multi-project daemon (ADR-049).
|
|
459
474
|
*
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
routeSpanToProject,
|
|
3
3
|
startDaemon
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-MDBE23Y3.js";
|
|
5
5
|
import {
|
|
6
6
|
ProjectNameCollisionError,
|
|
7
7
|
addProject,
|
|
@@ -37,15 +37,15 @@ import {
|
|
|
37
37
|
thresholdForEdgeType,
|
|
38
38
|
touchLastSeen,
|
|
39
39
|
writeAtomically
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-RR4LWQQB.js";
|
|
41
41
|
import {
|
|
42
42
|
startOtelGrpcReceiver
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-6H757ZNM.js";
|
|
44
44
|
import {
|
|
45
45
|
buildOtelReceiver,
|
|
46
46
|
logSpanHandler,
|
|
47
47
|
parseOtlpRequest
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-P2ZEKJ35.js";
|
|
49
49
|
export {
|
|
50
50
|
ProjectNameCollisionError,
|
|
51
51
|
addProject,
|