@saptools/service-flow 0.1.69 → 0.1.72
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/CHANGELOG.md +17 -0
- package/README.md +9 -5
- package/TECHNICAL-NOTE.md +17 -0
- package/dist/{chunk-3N3B5KHV.js → chunk-Z6D433R5.js} +8766 -6546
- package/dist/chunk-Z6D433R5.js.map +1 -0
- package/dist/cli.js +703 -160
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +53 -14
- package/dist/index.js +2 -23
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/doctor-event-quality.ts +371 -0
- package/src/cli/{002-doctor-lifecycle.ts → doctor-lifecycle.ts} +1 -1
- package/src/cli/{001-doctor-projection.ts → doctor-projection.ts} +1 -1
- package/src/cli/doctor.ts +9 -11
- package/src/cli.ts +6 -6
- package/src/db/{009-binding-fact-semantics.ts → binding-fact-semantics.ts} +2 -2
- package/src/db/{000-call-fact-repository.ts → call-fact-repository.ts} +12 -9
- package/src/db/{003-current-fact-semantics.ts → current-fact-semantics.ts} +8 -8
- package/src/db/event-fact-semantics.ts +347 -0
- package/src/db/event-surface-invalidation.ts +38 -0
- package/src/db/{002-fact-json-inventory.ts → fact-json-inventory.ts} +16 -0
- package/src/db/{001-fact-lifecycle.ts → fact-lifecycle.ts} +3 -3
- package/src/db/migrations.ts +12 -1
- package/src/db/{007-package-fact-semantics.ts → package-fact-semantics.ts} +6 -6
- package/src/db/{010-package-symbol-surface-semantics.ts → package-symbol-surface-semantics.ts} +2 -2
- package/src/db/{004-package-target-invalidation.ts → package-target-invalidation.ts} +80 -1
- package/src/db/{008-relative-fact-semantics.ts → relative-fact-semantics.ts} +3 -3
- package/src/db/{006-relative-symbol-resolution.ts → relative-symbol-resolution.ts} +1 -1
- package/src/db/repositories.ts +31 -5
- package/src/db/{005-schema-structure.ts → schema-structure.ts} +41 -1
- package/src/db/schema.ts +6 -2
- package/src/db/{011-symbol-call-semantics.ts → symbol-call-semantics.ts} +1 -1
- package/src/index.ts +3 -3
- package/src/indexer/repository-indexer.ts +50 -11
- package/src/indexer/workspace-indexer.ts +3 -3
- package/src/linker/{007-call-edge-insertion.ts → call-edge-insertion.ts} +2 -2
- package/src/linker/{002-call-evidence.ts → call-evidence.ts} +2 -2
- package/src/linker/cross-repo-linker.ts +30 -8
- package/src/linker/dynamic-edge-resolver.ts +1 -1
- package/src/linker/event-environment-link.ts +211 -0
- package/src/linker/event-shape-candidate-linker.ts +161 -0
- package/src/linker/{004-event-subscription-handler-linker.ts → event-subscription-handler-linker.ts} +124 -20
- package/src/linker/{006-event-template-link.ts → event-template-link.ts} +40 -6
- package/src/linker/external-http-target.ts +1 -1
- package/src/linker/helper-package-linker.ts +1 -1
- package/src/linker/{000-implementation-candidates.ts → implementation-candidates.ts} +1 -1
- package/src/linker/{001-implementation-evidence-projection.ts → implementation-evidence-projection.ts} +1 -1
- package/src/linker/odata-path-normalizer.ts +1 -1
- package/src/linker/{005-odata-path-structure.ts → odata-path-structure.ts} +1 -1
- package/src/linker/package-event-constant-resolver.ts +298 -0
- package/src/linker/{003-package-import-symbol-resolver.ts → package-import-symbol-resolver.ts} +3 -3
- package/src/linker/service-resolver.ts +2 -2
- package/src/output/{001-compact-json-output.ts → compact-json-output.ts} +1 -1
- package/src/output/table-output.ts +13 -1
- package/src/parsers/{006-binding-identity.ts → binding-identity.ts} +3 -3
- package/src/parsers/{011-binding-lexical-scope.ts → binding-lexical-scope.ts} +1 -1
- package/src/parsers/{021-binding-visibility.ts → binding-visibility.ts} +1 -1
- package/src/parsers/decorator-parser.ts +9 -53
- package/src/parsers/environment-declarations.ts +327 -0
- package/src/parsers/event-call-analysis.ts +242 -0
- package/src/parsers/event-environment-reference.ts +231 -0
- package/src/parsers/event-loop-registration.ts +132 -0
- package/src/parsers/event-name-import-resolution.ts +243 -0
- package/src/parsers/event-receiver-analysis.ts +404 -0
- package/src/parsers/{005-event-subscription-facts.ts → event-subscription-facts.ts} +6 -2
- package/src/parsers/generated-constants-parser.ts +80 -14
- package/src/parsers/{016-local-symbol-reference.ts → local-symbol-reference.ts} +2 -2
- package/src/parsers/operation-path-analysis.ts +1 -1
- package/src/parsers/{023-outbound-call-classifier.ts → outbound-call-classifier.ts} +30 -127
- package/src/parsers/outbound-call-parser.ts +15 -3
- package/src/parsers/{022-outbound-expression-analysis.ts → outbound-expression-analysis.ts} +4 -4
- package/src/parsers/{018-package-commonjs-syntax.ts → package-commonjs-syntax.ts} +1 -1
- package/src/parsers/{012-package-fact-contract.ts → package-fact-contract.ts} +3 -3
- package/src/parsers/{010-package-public-surface-analysis.ts → package-public-surface-analysis.ts} +2 -2
- package/src/parsers/{003-package-public-surface.ts → package-public-surface.ts} +3 -3
- package/src/parsers/{008-package-surface-publication.ts → package-surface-publication.ts} +1 -1
- package/src/parsers/{001-query-entity-resolution.ts → query-entity-resolution.ts} +1 -1
- package/src/parsers/{015-service-binding-collector.ts → service-binding-collector.ts} +3 -3
- package/src/parsers/{014-service-binding-helper-flow.ts → service-binding-helper-flow.ts} +2 -2
- package/src/parsers/service-binding-parser-helpers.ts +1 -1
- package/src/parsers/service-binding-parser.ts +2 -2
- package/src/parsers/{007-source-fact-reconciliation.ts → source-fact-reconciliation.ts} +3 -3
- package/src/parsers/{020-stable-local-value.ts → stable-local-value.ts} +32 -11
- package/src/parsers/string-constant-lookups.ts +358 -0
- package/src/parsers/{009-symbol-call-facts.ts → symbol-call-facts.ts} +3 -3
- package/src/parsers/{017-symbol-derived-contexts.ts → symbol-derived-contexts.ts} +2 -2
- package/src/parsers/symbol-parser.ts +6 -6
- package/src/trace/{021-compact-decision-normalization.ts → compact-decision-normalization.ts} +2 -2
- package/src/trace/{020-compact-field-projection.ts → compact-field-projection.ts} +3 -3
- package/src/trace/{024-compact-observation-decision.ts → compact-observation-decision.ts} +3 -3
- package/src/trace/{016-compact-projector.ts → compact-projector.ts} +4 -4
- package/src/trace/{018-compact-trace.ts → compact-trace.ts} +3 -3
- package/src/trace/{006-contextual-projection.ts → contextual-projection.ts} +1 -1
- package/src/trace/{008-contextual-runtime-state.ts → contextual-runtime-state.ts} +1 -1
- package/src/trace/{001-dynamic-identity.ts → dynamic-identity.ts} +2 -2
- package/src/trace/{003-dynamic-references.ts → dynamic-references.ts} +2 -2
- package/src/trace/dynamic-targets.ts +6 -6
- package/src/trace/{030-event-runtime-resolution.ts → event-runtime-resolution.ts} +26 -5
- package/src/trace/event-shape-candidate-trace.ts +172 -0
- package/src/trace/{011-event-subscriber-traversal.ts → event-subscriber-traversal.ts} +20 -8
- package/src/trace/evidence.ts +9 -2
- package/src/trace/implementation-hints.ts +2 -2
- package/src/trace/{005-implementation-selection.ts → implementation-selection.ts} +2 -2
- package/src/trace/{031-local-call-expansion.ts → local-call-expansion.ts} +3 -3
- package/src/trace/{009-selected-handler-provenance.ts → selected-handler-provenance.ts} +1 -1
- package/src/trace/selectors.ts +1 -1
- package/src/trace/{017-trace-context.ts → trace-context.ts} +2 -2
- package/src/trace/{015-trace-edge-recorder.ts → trace-edge-recorder.ts} +2 -2
- package/src/trace/{019-trace-edge-semantics.ts → trace-edge-semantics.ts} +3 -3
- package/src/trace/trace-engine.ts +10 -10
- package/src/trace/{022-trace-fact-preflight.ts → trace-fact-preflight.ts} +2 -2
- package/src/trace/{025-trace-implementation-scope.ts → trace-implementation-scope.ts} +1 -1
- package/src/trace/{028-trace-operation-execution.ts → trace-operation-execution.ts} +10 -10
- package/src/trace/{013-trace-root-scopes.ts → trace-root-scopes.ts} +3 -3
- package/src/trace/{027-trace-scope-execution.ts → trace-scope-execution.ts} +35 -43
- package/src/trace/{029-trace-start-implementation.ts → trace-start-implementation.ts} +7 -7
- package/src/trace/{026-trace-start-scope.ts → trace-start-scope.ts} +5 -5
- package/src/trace/{010-traversal-scope.ts → traversal-scope.ts} +1 -1
- package/src/types.ts +17 -1
- package/src/utils/event-skeleton.ts +207 -0
- package/src/version.ts +1 -1
- package/dist/chunk-3N3B5KHV.js.map +0 -1
- /package/src/cli/{000-clean.ts → clean.ts} +0 -0
- /package/src/cli/{003-doctor-package-resolution.ts → doctor-package-resolution.ts} +0 -0
- /package/src/cli/{001-index-summary.ts → index-summary.ts} +0 -0
- /package/src/db/{014-binding-helper-provenance.ts → binding-helper-provenance.ts} +0 -0
- /package/src/db/{012-binding-reference-proof.ts → binding-reference-proof.ts} +0 -0
- /package/src/db/{013-index-publication-failure.ts → index-publication-failure.ts} +0 -0
- /package/src/output/{000-stdout-policy.ts → stdout-policy.ts} +0 -0
- /package/src/parsers/{019-binding-assignment-targets.ts → binding-assignment-targets.ts} +0 -0
- /package/src/parsers/{000-direct-query-execution.ts → direct-query-execution.ts} +0 -0
- /package/src/parsers/{013-executable-body-eligibility.ts → executable-body-eligibility.ts} +0 -0
- /package/src/parsers/{004-fact-identity.ts → fact-identity.ts} +0 -0
- /package/src/parsers/{002-symbol-import-bindings.ts → symbol-import-bindings.ts} +0 -0
- /package/src/trace/{014-compact-contract.ts → compact-contract.ts} +0 -0
- /package/src/trace/{004-dynamic-candidate-sources.ts → dynamic-candidate-sources.ts} +0 -0
- /package/src/trace/{000-dynamic-target-types.ts → dynamic-target-types.ts} +0 -0
- /package/src/trace/{007-implementation-start-diagnostic.ts → implementation-start-diagnostic.ts} +0 -0
- /package/src/trace/{023-nested-event-scopes.ts → nested-event-scopes.ts} +0 -0
- /package/src/trace/{002-trace-diagnostics.ts → trace-diagnostics.ts} +0 -0
- /package/src/trace/{012-trace-graph-lookups.ts → trace-graph-lookups.ts} +0 -0
- /package/src/utils/{000-bounded-projection.ts → bounded-projection.ts} +0 -0
- /package/src/utils/{001-placeholders.ts → placeholders.ts} +0 -0
|
@@ -2,7 +2,7 @@ import type { Db } from './connection.js';
|
|
|
2
2
|
import { ANALYZER_VERSION } from '../version.js';
|
|
3
3
|
import {
|
|
4
4
|
parsePackageImportReference,
|
|
5
|
-
} from '../parsers/
|
|
5
|
+
} from '../parsers/package-fact-contract.js';
|
|
6
6
|
|
|
7
7
|
interface PackageCallRow {
|
|
8
8
|
id: number;
|
|
@@ -10,6 +10,13 @@ interface PackageCallRow {
|
|
|
10
10
|
evidence: Record<string, unknown>;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
interface PackageEventCallRow {
|
|
14
|
+
id: number;
|
|
15
|
+
repoId: number;
|
|
16
|
+
unresolvedReason?: string | null;
|
|
17
|
+
evidence: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
|
|
13
20
|
export interface PackageInvalidationBatch {
|
|
14
21
|
publishingRepoIds: ReadonlySet<number>;
|
|
15
22
|
affectedCallerRepoIds: Set<number>;
|
|
@@ -44,6 +51,14 @@ function packageName(evidence: Record<string, unknown>): string | undefined {
|
|
|
44
51
|
?.requestedPackageName ?? undefined;
|
|
45
52
|
}
|
|
46
53
|
|
|
54
|
+
function eventPackageName(
|
|
55
|
+
evidence: Record<string, unknown>,
|
|
56
|
+
): string | undefined {
|
|
57
|
+
return parsePackageImportReference(
|
|
58
|
+
evidence.eventNameConstantImportBinding,
|
|
59
|
+
)?.requestedPackageName ?? undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
47
62
|
function packageCallEvidenceValid(
|
|
48
63
|
evidence: Record<string, unknown>,
|
|
49
64
|
): boolean {
|
|
@@ -94,6 +109,67 @@ function pendingEvidence(evidence: Record<string, unknown>): string {
|
|
|
94
109
|
});
|
|
95
110
|
}
|
|
96
111
|
|
|
112
|
+
function currentEventCalls(
|
|
113
|
+
db: Db,
|
|
114
|
+
workspaceId: number,
|
|
115
|
+
targetRepoId: number,
|
|
116
|
+
): PackageEventCallRow[] {
|
|
117
|
+
const rows = db.prepare(`SELECT c.id,c.repo_id repoId,
|
|
118
|
+
c.unresolved_reason unresolvedReason,c.evidence_json evidenceJson
|
|
119
|
+
FROM outbound_calls c JOIN repositories r ON r.id=c.repo_id
|
|
120
|
+
WHERE r.workspace_id=? AND r.id<>? AND r.fact_analyzer_version=?
|
|
121
|
+
AND json_extract(c.evidence_json,
|
|
122
|
+
'$.eventNameConstantImportBinding.moduleKind')='package'
|
|
123
|
+
ORDER BY c.id`).all(workspaceId, targetRepoId, ANALYZER_VERSION);
|
|
124
|
+
return rows.flatMap((row) => {
|
|
125
|
+
const evidence = parsedEvidence(row.evidenceJson);
|
|
126
|
+
return evidence && eventPackageName(evidence)
|
|
127
|
+
&& typeof row.id === 'number' && typeof row.repoId === 'number'
|
|
128
|
+
? [{
|
|
129
|
+
id: row.id, repoId: row.repoId, evidence,
|
|
130
|
+
unresolvedReason: typeof row.unresolvedReason === 'string'
|
|
131
|
+
? row.unresolvedReason : null,
|
|
132
|
+
}] : [];
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function pendingEventEvidence(
|
|
137
|
+
evidence: Record<string, unknown>,
|
|
138
|
+
): string {
|
|
139
|
+
const parser = { ...evidence };
|
|
140
|
+
delete parser.eventNameConstant;
|
|
141
|
+
delete parser.eventNamePackageConstantResolution;
|
|
142
|
+
parser.eventNameUnresolvedReason = 'event_name_constant_resolution_pending';
|
|
143
|
+
parser.eventNameStatus = 'dynamic';
|
|
144
|
+
parser.eventNameSourceKind = 'dynamic_expression';
|
|
145
|
+
parser.eventNamePlaceholderKeys = [];
|
|
146
|
+
return JSON.stringify(parser);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function resetPackageEventCalls(
|
|
150
|
+
db: Db,
|
|
151
|
+
workspaceId: number,
|
|
152
|
+
targetRepoId: number,
|
|
153
|
+
names: ReadonlySet<string>,
|
|
154
|
+
batch: PackageInvalidationBatch,
|
|
155
|
+
): boolean {
|
|
156
|
+
const update = db.prepare(`UPDATE outbound_calls SET event_name_expr=?,
|
|
157
|
+
unresolved_reason=?,evidence_json=? WHERE id=?`);
|
|
158
|
+
let matched = false;
|
|
159
|
+
for (const call of currentEventCalls(db, workspaceId, targetRepoId)) {
|
|
160
|
+
if (!names.has(eventPackageName(call.evidence) ?? '')) continue;
|
|
161
|
+
const source = call.evidence.eventNameConstantSourceExpression;
|
|
162
|
+
if (typeof source !== 'string' || source.length === 0)
|
|
163
|
+
throw new Error('invalid_current_package_event_constant_evidence');
|
|
164
|
+
const reason = call.evidence.receiverClassification === 'unproven'
|
|
165
|
+
? call.unresolvedReason : 'event_name_constant_resolution_pending';
|
|
166
|
+
update.run(source, reason, pendingEventEvidence(call.evidence), call.id);
|
|
167
|
+
batch.affectedCallerRepoIds.add(call.repoId);
|
|
168
|
+
matched = true;
|
|
169
|
+
}
|
|
170
|
+
return matched;
|
|
171
|
+
}
|
|
172
|
+
|
|
97
173
|
function targetWorkspace(
|
|
98
174
|
db: Db,
|
|
99
175
|
repoId: number,
|
|
@@ -142,6 +218,9 @@ export function invalidatePackageTargetFacts(
|
|
|
142
218
|
batch.affectedCallerRepoIds.add(call.repoId);
|
|
143
219
|
matched = true;
|
|
144
220
|
}
|
|
221
|
+
matched = resetPackageEventCalls(
|
|
222
|
+
db, target.workspaceId, targetRepoId, names, batch,
|
|
223
|
+
) || matched;
|
|
145
224
|
if (matched || packageIdentityChanged(
|
|
146
225
|
target.packageName, newPackageName,
|
|
147
226
|
)) batch.affectedWorkspaceIds.add(target.workspaceId);
|
|
@@ -2,12 +2,12 @@ import type { Db } from './connection.js';
|
|
|
2
2
|
import { ANALYZER_VERSION } from '../version.js';
|
|
3
3
|
import {
|
|
4
4
|
resolveRelativeSymbolCall,
|
|
5
|
-
} from './
|
|
5
|
+
} from './relative-symbol-resolution.js';
|
|
6
6
|
import type { SymbolCallFact } from '../types.js';
|
|
7
7
|
import { parseRelativeImportReference } from
|
|
8
|
-
'../parsers/
|
|
8
|
+
'../parsers/package-fact-contract.js';
|
|
9
9
|
import type { SymbolImportReference } from
|
|
10
|
-
'../parsers/
|
|
10
|
+
'../parsers/symbol-import-bindings.js';
|
|
11
11
|
|
|
12
12
|
export interface RelativeFactCategoryCount {
|
|
13
13
|
category: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { posix } from 'node:path';
|
|
2
2
|
import type { SymbolCallFact } from '../types.js';
|
|
3
3
|
import { packageModuleRequest } from
|
|
4
|
-
'../parsers/
|
|
4
|
+
'../parsers/symbol-import-bindings.js';
|
|
5
5
|
import type { Db } from './connection.js';
|
|
6
6
|
|
|
7
7
|
export interface RelativeSymbolCallResolution {
|
package/src/db/repositories.ts
CHANGED
|
@@ -7,15 +7,19 @@ import type {
|
|
|
7
7
|
HandlerRegistrationFact,
|
|
8
8
|
ServiceBindingFact,
|
|
9
9
|
ExecutableSymbolFact,
|
|
10
|
+
GeneratedConstantFact,
|
|
10
11
|
} from '../types.js';
|
|
11
12
|
import {
|
|
12
13
|
selectCallOwner,
|
|
13
14
|
type OwnerCandidate,
|
|
14
|
-
} from '../parsers/
|
|
15
|
+
} from '../parsers/fact-identity.js';
|
|
15
16
|
import {
|
|
16
17
|
PreparedRepositorySnapshotError,
|
|
17
18
|
type PreparedSnapshotFailureCode,
|
|
18
|
-
} from './
|
|
19
|
+
} from './index-publication-failure.js';
|
|
20
|
+
import {
|
|
21
|
+
emptyEnvironmentDeclarations,
|
|
22
|
+
} from '../parsers/environment-declarations.js';
|
|
19
23
|
export interface RepoRow {
|
|
20
24
|
id: number;
|
|
21
25
|
name: string;
|
|
@@ -92,8 +96,8 @@ export function upsertRepository(
|
|
|
92
96
|
db.prepare(
|
|
93
97
|
`INSERT INTO repositories(workspace_id,name,absolute_path,relative_path,
|
|
94
98
|
package_name,package_version,dependencies_json,
|
|
95
|
-
package_public_surface_json,kind,is_git_repo)
|
|
96
|
-
VALUES(
|
|
99
|
+
package_public_surface_json,environment_declarations_json,kind,is_git_repo)
|
|
100
|
+
VALUES(?,?,?,?,?,?,?,?,?,?,?)
|
|
97
101
|
ON CONFLICT(workspace_id,absolute_path) DO UPDATE SET
|
|
98
102
|
name=excluded.name,relative_path=excluded.relative_path,
|
|
99
103
|
package_name=excluded.package_name,
|
|
@@ -108,6 +112,7 @@ export function upsertRepository(
|
|
|
108
112
|
r.packageVersion,
|
|
109
113
|
JSON.stringify(r.dependencies ?? {}),
|
|
110
114
|
initialPackagePublicSurface(r.packageName),
|
|
115
|
+
JSON.stringify(emptyEnvironmentDeclarations()),
|
|
111
116
|
r.kind ?? 'unknown',
|
|
112
117
|
r.isGitRepo ? 1 : 0,
|
|
113
118
|
);
|
|
@@ -152,6 +157,7 @@ export function clearRepoFacts(db: Db, repoId: number): void {
|
|
|
152
157
|
'symbol_calls',
|
|
153
158
|
'handler_registrations',
|
|
154
159
|
'service_bindings',
|
|
160
|
+
'generated_constants',
|
|
155
161
|
'symbols',
|
|
156
162
|
'diagnostics',
|
|
157
163
|
'files',
|
|
@@ -159,6 +165,26 @@ export function clearRepoFacts(db: Db, repoId: number): void {
|
|
|
159
165
|
db.prepare(`DELETE FROM ${t} WHERE repo_id=?`).run(repoId);
|
|
160
166
|
db.prepare('DELETE FROM search_index WHERE repo=?').run(String(repoId));
|
|
161
167
|
}
|
|
168
|
+
export function insertGeneratedConstants(
|
|
169
|
+
db: Db,
|
|
170
|
+
repoId: number,
|
|
171
|
+
rows: GeneratedConstantFact[],
|
|
172
|
+
): void {
|
|
173
|
+
const stmt = db.prepare(`INSERT INTO generated_constants(
|
|
174
|
+
repo_id,source_file,source_line,name,container_name,member_name,value,
|
|
175
|
+
constant_kind,exported,stable,resolution_status,unresolved_reason,
|
|
176
|
+
declaration_start_offset,declaration_end_offset,
|
|
177
|
+
value_start_offset,value_end_offset
|
|
178
|
+
) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`);
|
|
179
|
+
for (const row of rows) stmt.run(
|
|
180
|
+
repoId, row.sourceFile, row.sourceLine, row.name,
|
|
181
|
+
row.containerName ?? null, row.memberName ?? null, row.value ?? null,
|
|
182
|
+
row.constantKind, row.exported ? 1 : 0, row.stable ? 1 : 0,
|
|
183
|
+
row.resolutionStatus, row.unresolvedReason ?? null,
|
|
184
|
+
row.declarationStartOffset, row.declarationEndOffset,
|
|
185
|
+
row.valueStartOffset, row.valueEndOffset,
|
|
186
|
+
);
|
|
187
|
+
}
|
|
162
188
|
export function insertRequires(
|
|
163
189
|
db: Db,
|
|
164
190
|
repoId: number,
|
|
@@ -505,4 +531,4 @@ export function insertExecutableSymbols(db: Db, repoId: number, rows: Executable
|
|
|
505
531
|
const stmt = db.prepare('INSERT INTO symbols(repo_id,file_id,kind,name,qualified_name,exported,start_line,end_line,start_offset,end_offset,source_file,exported_name,evidence_json) VALUES(?,(SELECT id FROM files WHERE repo_id=? AND relative_path=?),?,?,?,?,?,?,?,?,?,?,?)');
|
|
506
532
|
for (const r of rows) stmt.run(repoId, repoId, r.sourceFile, r.kind, r.localName, r.qualifiedName, r.exported ? 1 : 0, r.startLine, r.endLine, r.startOffset, r.endOffset, r.sourceFile, r.exportedName, r.importExportEvidence ? JSON.stringify(r.importExportEvidence) : null);
|
|
507
533
|
}
|
|
508
|
-
export { insertCalls, insertSymbolCalls } from './
|
|
534
|
+
export { insertCalls, insertSymbolCalls } from './call-fact-repository.js';
|
|
@@ -12,7 +12,8 @@ const requiredColumns = {
|
|
|
12
12
|
repositories: [
|
|
13
13
|
'id', 'workspace_id', 'name', 'absolute_path', 'relative_path',
|
|
14
14
|
'package_name', 'package_version', 'dependencies_json',
|
|
15
|
-
'package_public_surface_json', '
|
|
15
|
+
'package_public_surface_json', 'environment_declarations_json',
|
|
16
|
+
'kind', 'is_git_repo', 'last_indexed_at',
|
|
16
17
|
'index_status', 'error_count', 'fingerprint', 'fact_generation',
|
|
17
18
|
'graph_generation', 'graph_stale_reason', 'graph_stale_at',
|
|
18
19
|
'fact_analyzer_version',
|
|
@@ -66,6 +67,7 @@ const requiredColumns = {
|
|
|
66
67
|
outbound_calls: [
|
|
67
68
|
'id', 'repo_id', 'source_symbol_id', 'service_binding_id', 'call_type',
|
|
68
69
|
'method', 'operation_path_expr', 'query_entity', 'event_name_expr',
|
|
70
|
+
'event_skeleton_signature', 'event_skeleton_json',
|
|
69
71
|
'payload_summary', 'source_file', 'source_line',
|
|
70
72
|
'call_site_start_offset', 'call_site_end_offset', 'evidence_json',
|
|
71
73
|
'confidence', 'unresolved_reason', 'local_service_name',
|
|
@@ -79,6 +81,13 @@ const requiredColumns = {
|
|
|
79
81
|
'call_site_end_offset', 'call_role', 'status', 'evidence_json',
|
|
80
82
|
'confidence', 'unresolved_reason',
|
|
81
83
|
],
|
|
84
|
+
generated_constants: [
|
|
85
|
+
'id', 'repo_id', 'source_file', 'source_line', 'name',
|
|
86
|
+
'container_name', 'member_name', 'value', 'constant_kind', 'exported',
|
|
87
|
+
'stable', 'resolution_status', 'unresolved_reason',
|
|
88
|
+
'declaration_start_offset', 'declaration_end_offset',
|
|
89
|
+
'value_start_offset', 'value_end_offset',
|
|
90
|
+
],
|
|
82
91
|
graph_edges: [
|
|
83
92
|
'id', 'workspace_id', 'edge_type', 'status', 'from_kind', 'from_id',
|
|
84
93
|
'to_kind', 'to_id', 'confidence', 'evidence_json', 'is_dynamic',
|
|
@@ -167,6 +176,33 @@ function bindingIndexInvalid(
|
|
|
167
176
|
&& metadata?.unique === unique && metadata.partial === partial ? 0 : 1;
|
|
168
177
|
}
|
|
169
178
|
|
|
179
|
+
function tableIndexInvalid(
|
|
180
|
+
db: Db,
|
|
181
|
+
table: string,
|
|
182
|
+
name: string,
|
|
183
|
+
columns: readonly string[],
|
|
184
|
+
unique: number,
|
|
185
|
+
): number {
|
|
186
|
+
const metadata = db.prepare(`PRAGMA index_list(${table})`)
|
|
187
|
+
.all().find((item) => item.name === name);
|
|
188
|
+
return metadata?.unique === unique
|
|
189
|
+
&& indexColumns(db, name).join('\0') === columns.join('\0') ? 0 : 1;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function eventSurfaceIndexesInvalid(db: Db): number {
|
|
193
|
+
return tableIndexInvalid(
|
|
194
|
+
db, 'outbound_calls', 'idx_outbound_event_skeleton',
|
|
195
|
+
['event_skeleton_signature', 'call_type', 'repo_id'], 0,
|
|
196
|
+
) + tableIndexInvalid(
|
|
197
|
+
db, 'generated_constants', 'idx_generated_constant_name',
|
|
198
|
+
['repo_id', 'source_file', 'name'], 0,
|
|
199
|
+
) + tableIndexInvalid(
|
|
200
|
+
db, 'generated_constants', 'uq_generated_constant_site',
|
|
201
|
+
['repo_id', 'source_file', 'name', 'declaration_start_offset',
|
|
202
|
+
'declaration_end_offset'], 1,
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
170
206
|
function exactBindingIndexInvalid(db: Db): number {
|
|
171
207
|
const row = db.prepare(`SELECT sql FROM sqlite_master
|
|
172
208
|
WHERE type='index' AND name='uq_service_binding_exact_site'`).get();
|
|
@@ -197,5 +233,9 @@ export function invalidSchemaStructureCategories(
|
|
|
197
233
|
exactBindingIndexInvalid(db)
|
|
198
234
|
+ bindingIndexInvalid(db, 'idx_service_binding_site', 0, 0),
|
|
199
235
|
),
|
|
236
|
+
...category(
|
|
237
|
+
'schema_event_surface_index_invalid',
|
|
238
|
+
eventSurfaceIndexesInvalid(db),
|
|
239
|
+
),
|
|
200
240
|
];
|
|
201
241
|
}
|
package/src/db/schema.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const schemaTablesSql = `
|
|
2
2
|
CREATE TABLE IF NOT EXISTS workspaces (id INTEGER PRIMARY KEY, root_path TEXT UNIQUE NOT NULL, db_path TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL);
|
|
3
|
-
CREATE TABLE IF NOT EXISTS repositories (id INTEGER PRIMARY KEY, workspace_id INTEGER NOT NULL, name TEXT NOT NULL, absolute_path TEXT NOT NULL, relative_path TEXT NOT NULL, package_name TEXT, package_version TEXT, dependencies_json TEXT DEFAULT '{}', package_public_surface_json TEXT, kind TEXT NOT NULL, is_git_repo INTEGER NOT NULL, last_indexed_at TEXT, index_status TEXT DEFAULT 'pending', error_count INTEGER DEFAULT 0, fingerprint TEXT, fact_generation INTEGER NOT NULL DEFAULT 0, graph_generation INTEGER NOT NULL DEFAULT 0, graph_stale_reason TEXT, graph_stale_at TEXT, fact_analyzer_version TEXT, UNIQUE(workspace_id, absolute_path), FOREIGN KEY(workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE);
|
|
3
|
+
CREATE TABLE IF NOT EXISTS repositories (id INTEGER PRIMARY KEY, workspace_id INTEGER NOT NULL, name TEXT NOT NULL, absolute_path TEXT NOT NULL, relative_path TEXT NOT NULL, package_name TEXT, package_version TEXT, dependencies_json TEXT DEFAULT '{}', package_public_surface_json TEXT, environment_declarations_json TEXT DEFAULT '{"schema":"service-flow/environment-declarations@1","status":"not_applicable","reason":null,"recordCap":32,"total":0,"shown":0,"omitted":0,"declarations":[]}', kind TEXT NOT NULL, is_git_repo INTEGER NOT NULL, last_indexed_at TEXT, index_status TEXT DEFAULT 'pending', error_count INTEGER DEFAULT 0, fingerprint TEXT, fact_generation INTEGER NOT NULL DEFAULT 0, graph_generation INTEGER NOT NULL DEFAULT 0, graph_stale_reason TEXT, graph_stale_at TEXT, fact_analyzer_version TEXT, UNIQUE(workspace_id, absolute_path), FOREIGN KEY(workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE);
|
|
4
4
|
CREATE TABLE IF NOT EXISTS files (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, relative_path TEXT NOT NULL, extension TEXT NOT NULL, sha256 TEXT NOT NULL, size_bytes INTEGER NOT NULL, last_indexed_at TEXT NOT NULL, UNIQUE(repo_id, relative_path), FOREIGN KEY(repo_id) REFERENCES repositories(id) ON DELETE CASCADE);
|
|
5
5
|
CREATE TABLE IF NOT EXISTS cds_requires (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, alias TEXT NOT NULL, kind TEXT, model TEXT, destination TEXT, service_path TEXT, request_timeout INTEGER, raw_json TEXT NOT NULL, FOREIGN KEY(repo_id) REFERENCES repositories(id) ON DELETE CASCADE);
|
|
6
6
|
CREATE TABLE IF NOT EXISTS cds_services (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, namespace TEXT, service_name TEXT NOT NULL, qualified_name TEXT NOT NULL, service_path TEXT NOT NULL, is_extend INTEGER NOT NULL, source_file TEXT NOT NULL, source_line INTEGER NOT NULL, extension_local_ref TEXT, extension_imported_symbol TEXT, extension_local_alias TEXT, extension_module_specifier TEXT, extension_import_kind TEXT, extension_base_service_id INTEGER, extension_base_status TEXT, FOREIGN KEY(repo_id) REFERENCES repositories(id) ON DELETE CASCADE, FOREIGN KEY(extension_base_service_id) REFERENCES cds_services(id) ON DELETE SET NULL);
|
|
@@ -10,7 +10,8 @@ CREATE TABLE IF NOT EXISTS handler_classes (id INTEGER PRIMARY KEY, repo_id INTE
|
|
|
10
10
|
CREATE TABLE IF NOT EXISTS handler_methods (id INTEGER PRIMARY KEY, handler_class_id INTEGER NOT NULL, method_name TEXT NOT NULL, decorator_kind TEXT NOT NULL, decorator_value TEXT, decorator_raw_expression TEXT NOT NULL, decorator_resolution_json TEXT NOT NULL DEFAULT '{}', source_file TEXT NOT NULL, source_line INTEGER NOT NULL, FOREIGN KEY(handler_class_id) REFERENCES handler_classes(id) ON DELETE CASCADE);
|
|
11
11
|
CREATE TABLE IF NOT EXISTS handler_registrations (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, handler_class_id INTEGER, class_name TEXT, import_source TEXT, registration_file TEXT NOT NULL, registration_line INTEGER NOT NULL, registration_kind TEXT NOT NULL, confidence REAL NOT NULL, FOREIGN KEY(repo_id) REFERENCES repositories(id) ON DELETE CASCADE, FOREIGN KEY(handler_class_id) REFERENCES handler_classes(id) ON DELETE SET NULL);
|
|
12
12
|
CREATE TABLE IF NOT EXISTS service_bindings (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, symbol_id INTEGER, variable_name TEXT NOT NULL, alias TEXT, alias_expr TEXT, destination_expr TEXT, service_path_expr TEXT, is_dynamic INTEGER NOT NULL, placeholders_json TEXT NOT NULL, source_file TEXT NOT NULL, source_line INTEGER NOT NULL, binding_site_start_offset INTEGER, binding_site_end_offset INTEGER, owner_resolution TEXT NOT NULL DEFAULT 'legacy_unknown' CHECK(owner_resolution IN ('owned_exact','ownerless_file_scope','legacy_unknown')), helper_chain_json TEXT, FOREIGN KEY(repo_id) REFERENCES repositories(id) ON DELETE CASCADE, FOREIGN KEY(symbol_id) REFERENCES symbols(id) ON DELETE SET NULL);
|
|
13
|
-
CREATE TABLE IF NOT EXISTS outbound_calls (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, source_symbol_id INTEGER, call_type TEXT NOT NULL, service_binding_id INTEGER, method TEXT, operation_path_expr TEXT, query_entity TEXT, event_name_expr TEXT, payload_summary TEXT, source_file TEXT NOT NULL, source_line INTEGER NOT NULL, call_site_start_offset INTEGER, call_site_end_offset INTEGER, confidence REAL NOT NULL, unresolved_reason TEXT, local_service_name TEXT, local_service_lookup TEXT, alias_chain_json TEXT, evidence_json TEXT, external_target_kind TEXT, external_target_id TEXT, external_target_label TEXT, external_target_dynamic INTEGER NOT NULL DEFAULT 0, FOREIGN KEY(repo_id) REFERENCES repositories(id) ON DELETE CASCADE, FOREIGN KEY(source_symbol_id) REFERENCES symbols(id) ON DELETE SET NULL, FOREIGN KEY(service_binding_id) REFERENCES service_bindings(id) ON DELETE SET NULL);
|
|
13
|
+
CREATE TABLE IF NOT EXISTS outbound_calls (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, source_symbol_id INTEGER, call_type TEXT NOT NULL, service_binding_id INTEGER, method TEXT, operation_path_expr TEXT, query_entity TEXT, event_name_expr TEXT, event_skeleton_signature TEXT, event_skeleton_json TEXT, payload_summary TEXT, source_file TEXT NOT NULL, source_line INTEGER NOT NULL, call_site_start_offset INTEGER, call_site_end_offset INTEGER, confidence REAL NOT NULL, unresolved_reason TEXT, local_service_name TEXT, local_service_lookup TEXT, alias_chain_json TEXT, evidence_json TEXT, external_target_kind TEXT, external_target_id TEXT, external_target_label TEXT, external_target_dynamic INTEGER NOT NULL DEFAULT 0, FOREIGN KEY(repo_id) REFERENCES repositories(id) ON DELETE CASCADE, FOREIGN KEY(source_symbol_id) REFERENCES symbols(id) ON DELETE SET NULL, FOREIGN KEY(service_binding_id) REFERENCES service_bindings(id) ON DELETE SET NULL);
|
|
14
|
+
CREATE TABLE IF NOT EXISTS generated_constants (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, source_file TEXT NOT NULL, source_line INTEGER NOT NULL, name TEXT NOT NULL, container_name TEXT, member_name TEXT, value TEXT, constant_kind TEXT NOT NULL, exported INTEGER NOT NULL, stable INTEGER NOT NULL, resolution_status TEXT NOT NULL CHECK(resolution_status IN ('resolved','refused')), unresolved_reason TEXT, declaration_start_offset INTEGER NOT NULL, declaration_end_offset INTEGER NOT NULL, value_start_offset INTEGER NOT NULL, value_end_offset INTEGER NOT NULL, FOREIGN KEY(repo_id) REFERENCES repositories(id) ON DELETE CASCADE);
|
|
14
15
|
CREATE TABLE IF NOT EXISTS symbol_calls (id INTEGER PRIMARY KEY, repo_id INTEGER NOT NULL, caller_symbol_id INTEGER NOT NULL, callee_symbol_id INTEGER, callee_expression TEXT NOT NULL, import_source TEXT, source_file TEXT NOT NULL, source_line INTEGER NOT NULL, call_site_start_offset INTEGER, call_site_end_offset INTEGER, call_role TEXT NOT NULL DEFAULT 'legacy_unknown', status TEXT NOT NULL, confidence REAL NOT NULL, evidence_json TEXT NOT NULL, unresolved_reason TEXT, FOREIGN KEY(repo_id) REFERENCES repositories(id) ON DELETE CASCADE, FOREIGN KEY(caller_symbol_id) REFERENCES symbols(id) ON DELETE CASCADE, FOREIGN KEY(callee_symbol_id) REFERENCES symbols(id) ON DELETE SET NULL);
|
|
15
16
|
CREATE TABLE IF NOT EXISTS graph_edges (id INTEGER PRIMARY KEY, workspace_id INTEGER NOT NULL, edge_type TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'unresolved', from_kind TEXT NOT NULL, from_id TEXT NOT NULL, to_kind TEXT NOT NULL, to_id TEXT NOT NULL, confidence REAL NOT NULL, evidence_json TEXT NOT NULL, is_dynamic INTEGER NOT NULL, unresolved_reason TEXT, generation INTEGER NOT NULL DEFAULT 0, FOREIGN KEY(workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE);
|
|
16
17
|
CREATE TABLE IF NOT EXISTS index_runs (id INTEGER PRIMARY KEY, workspace_id INTEGER NOT NULL, started_at TEXT NOT NULL, finished_at TEXT, status TEXT NOT NULL, repo_count INTEGER NOT NULL, file_count INTEGER NOT NULL, diagnostic_count INTEGER NOT NULL, error_message TEXT, owner_pid INTEGER, FOREIGN KEY(workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE);
|
|
@@ -24,6 +25,9 @@ CREATE INDEX IF NOT EXISTS idx_extension_import ON cds_services(extension_module
|
|
|
24
25
|
CREATE INDEX IF NOT EXISTS idx_operation_name ON cds_operations(operation_name, operation_path);
|
|
25
26
|
CREATE INDEX IF NOT EXISTS idx_operation_base ON cds_operations(base_operation_id);
|
|
26
27
|
CREATE INDEX IF NOT EXISTS idx_calls_repo ON outbound_calls(repo_id, call_type);
|
|
28
|
+
CREATE INDEX IF NOT EXISTS idx_outbound_event_skeleton ON outbound_calls(event_skeleton_signature,call_type,repo_id);
|
|
29
|
+
CREATE INDEX IF NOT EXISTS idx_generated_constant_name ON generated_constants(repo_id,source_file,name);
|
|
30
|
+
CREATE UNIQUE INDEX IF NOT EXISTS uq_generated_constant_site ON generated_constants(repo_id,source_file,name,declaration_start_offset,declaration_end_offset);
|
|
27
31
|
CREATE INDEX IF NOT EXISTS idx_symbol_calls_caller ON symbol_calls(repo_id, caller_symbol_id);
|
|
28
32
|
CREATE INDEX IF NOT EXISTS idx_outbound_call_site ON outbound_calls(repo_id, source_file, call_site_start_offset, call_site_end_offset, call_type);
|
|
29
33
|
CREATE INDEX IF NOT EXISTS idx_symbol_call_site_role ON symbol_calls(repo_id, source_file, call_site_start_offset, call_site_end_offset, call_role);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { SymbolCallFact } from '../types.js';
|
|
2
2
|
import { ANALYZER_VERSION } from '../version.js';
|
|
3
|
-
import { resolveSymbolCallTarget } from './
|
|
3
|
+
import { resolveSymbolCallTarget } from './call-fact-repository.js';
|
|
4
4
|
import type { Db } from './connection.js';
|
|
5
5
|
|
|
6
6
|
export interface SymbolFactCategoryCount {
|
package/src/index.ts
CHANGED
|
@@ -13,8 +13,8 @@ export { trace } from './trace/trace-engine.js';
|
|
|
13
13
|
export {
|
|
14
14
|
compactTrace,
|
|
15
15
|
traceAndCompact,
|
|
16
|
-
} from './trace/
|
|
17
|
-
export type { CompactTraceExecution } from './trace/
|
|
16
|
+
} from './trace/compact-trace.js';
|
|
17
|
+
export type { CompactTraceExecution } from './trace/compact-trace.js';
|
|
18
18
|
export type {
|
|
19
19
|
CompactDecisionV1,
|
|
20
20
|
CompactDiagnosticDetailsV1,
|
|
@@ -31,7 +31,7 @@ export type {
|
|
|
31
31
|
CompactStartV1,
|
|
32
32
|
CompactStatus,
|
|
33
33
|
CompactStatusCountsV1,
|
|
34
|
-
} from './trace/
|
|
34
|
+
} from './trace/compact-contract.js';
|
|
35
35
|
export { parseImplementationHint } from './trace/implementation-hints.js';
|
|
36
36
|
export type { DynamicMode, ImplementationHint, TraceOptions } from './types.js';
|
|
37
37
|
export { redactValue, redactText } from './utils/redaction.js';
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
insertCalls,
|
|
8
8
|
insertExecutableSymbols,
|
|
9
9
|
insertHandler,
|
|
10
|
+
insertGeneratedConstants,
|
|
10
11
|
handlerMethodIsExecutable,
|
|
11
12
|
insertRegistrations,
|
|
12
13
|
insertSymbolCalls,
|
|
@@ -23,18 +24,21 @@ import {
|
|
|
23
24
|
parseOutboundCalls,
|
|
24
25
|
} from '../parsers/outbound-call-parser.js';
|
|
25
26
|
import { parseExecutableSymbols } from '../parsers/symbol-parser.js';
|
|
27
|
+
import {
|
|
28
|
+
generatedConstantFacts,
|
|
29
|
+
} from '../parsers/generated-constants-parser.js';
|
|
26
30
|
import {
|
|
27
31
|
loadPackageJsonSnapshot,
|
|
28
32
|
} from '../parsers/package-json-parser.js';
|
|
29
33
|
import { parseServiceBindings } from '../parsers/service-binding-parser.js';
|
|
30
|
-
import { reconcileSourceFacts } from '../parsers/
|
|
34
|
+
import { reconcileSourceFacts } from '../parsers/source-fact-reconciliation.js';
|
|
31
35
|
import {
|
|
32
36
|
analyzeRepositoryPackageSurface,
|
|
33
37
|
mergePackageSymbolEvidence,
|
|
34
|
-
} from '../parsers/
|
|
38
|
+
} from '../parsers/package-surface-publication.js';
|
|
35
39
|
import type {
|
|
36
40
|
PackagePublicSurfaceFact,
|
|
37
|
-
} from '../parsers/
|
|
41
|
+
} from '../parsers/package-public-surface.js';
|
|
38
42
|
import { normalizePath } from '../utils/path-utils.js';
|
|
39
43
|
import { errorMessage } from '../utils/diagnostics.js';
|
|
40
44
|
import { sha256Text } from '../utils/hashing.js';
|
|
@@ -44,17 +48,29 @@ import {
|
|
|
44
48
|
finalizePackageTargetInvalidations,
|
|
45
49
|
invalidatePackageTargetFacts,
|
|
46
50
|
type PackageInvalidationBatch,
|
|
47
|
-
} from '../db/
|
|
51
|
+
} from '../db/package-target-invalidation.js';
|
|
48
52
|
import {
|
|
49
53
|
isPreparedRepositorySnapshotError,
|
|
50
54
|
recordPreparedSnapshotFailure,
|
|
51
|
-
} from '../db/
|
|
55
|
+
} from '../db/index-publication-failure.js';
|
|
52
56
|
import {
|
|
53
57
|
loadRepositorySourceContext,
|
|
54
58
|
type RepositorySourceContext,
|
|
55
59
|
type SourceContextInstrumentation,
|
|
56
60
|
} from '../parsers/ts-project.js';
|
|
57
|
-
import
|
|
61
|
+
import {
|
|
62
|
+
createImportedEventNameResolver,
|
|
63
|
+
} from '../parsers/event-name-import-resolution.js';
|
|
64
|
+
import {
|
|
65
|
+
collectEnvironmentDeclarations,
|
|
66
|
+
type EnvironmentDeclarationsFact,
|
|
67
|
+
} from '../parsers/environment-declarations.js';
|
|
68
|
+
import {
|
|
69
|
+
createEventEnvironmentReferenceResolver,
|
|
70
|
+
} from '../parsers/event-environment-reference.js';
|
|
71
|
+
import { invalidateEventSurfaceFacts } from
|
|
72
|
+
'../db/event-surface-invalidation.js';
|
|
73
|
+
import type { CdsServiceFact, GeneratedConstantFact, HandlerClassFact, HandlerRegistrationFact, OutboundCallFact, PackageFacts, ServiceBindingFact, ExecutableSymbolFact, SymbolCallFact } from '../types.js';
|
|
58
74
|
export interface IndexRepoResult {
|
|
59
75
|
fileCount: number;
|
|
60
76
|
diagnosticCount: number;
|
|
@@ -68,6 +84,7 @@ interface ParsedFacts {
|
|
|
68
84
|
calls: OutboundCallFact[];
|
|
69
85
|
symbols: ExecutableSymbolFact[];
|
|
70
86
|
symbolCalls: SymbolCallFact[];
|
|
87
|
+
generatedConstants: GeneratedConstantFact[];
|
|
71
88
|
fileRecords: Array<{ relativePath: string; extension: string; sha256: string; sizeBytes: number }>;
|
|
72
89
|
}
|
|
73
90
|
export interface PreparedRepositoryIndex extends IndexRepoResult {
|
|
@@ -77,6 +94,7 @@ export interface PreparedRepositoryIndex extends IndexRepoResult {
|
|
|
77
94
|
kind?: string;
|
|
78
95
|
parsed?: ParsedFacts;
|
|
79
96
|
packagePublicSurface?: PackagePublicSurfaceFact;
|
|
97
|
+
environmentDeclarations?: EnvironmentDeclarationsFact;
|
|
80
98
|
}
|
|
81
99
|
export async function indexRepository(
|
|
82
100
|
db: Db,
|
|
@@ -139,6 +157,7 @@ export async function prepareRepositoryIndex(
|
|
|
139
157
|
kind: await classifyRepository(repo.absolute_path, packageFacts),
|
|
140
158
|
parsed,
|
|
141
159
|
packagePublicSurface: packageSurface.surface,
|
|
160
|
+
environmentDeclarations: collectEnvironmentDeclarations(sources),
|
|
142
161
|
fileCount: sourceFiles.length,
|
|
143
162
|
diagnosticCount: parsed.handlers.filter((handler) =>
|
|
144
163
|
handler.hasHandlerDecorator
|
|
@@ -154,20 +173,27 @@ export function publishPreparedRepositoryIndex(
|
|
|
154
173
|
): void {
|
|
155
174
|
if (prepared.skipped) return;
|
|
156
175
|
if (!prepared.packageFacts || !prepared.parsed || !prepared.fingerprint
|
|
157
|
-
|| !prepared.kind || !prepared.packagePublicSurface
|
|
176
|
+
|| !prepared.kind || !prepared.packagePublicSurface
|
|
177
|
+
|| !prepared.environmentDeclarations)
|
|
158
178
|
throw new Error('Prepared repository index is missing publication facts');
|
|
159
179
|
const now = new Date().toISOString();
|
|
160
180
|
const repoId = prepared.repo.id;
|
|
181
|
+
const environmentJson = JSON.stringify(prepared.environmentDeclarations);
|
|
161
182
|
invalidatePackageTargetFacts(
|
|
162
183
|
db, repoId, prepared.packageFacts.packageName, invalidations,
|
|
163
184
|
);
|
|
185
|
+
invalidateEventSurfaceFacts(
|
|
186
|
+
db, repoId, prepared.parsed.calls, environmentJson,
|
|
187
|
+
);
|
|
164
188
|
db.prepare(`UPDATE repositories SET package_name=?, package_version=?,
|
|
165
|
-
dependencies_json=?,package_public_surface_json=?,
|
|
189
|
+
dependencies_json=?,package_public_surface_json=?,
|
|
190
|
+
environment_declarations_json=?,kind=?,index_status=?
|
|
166
191
|
WHERE id=?`).run(
|
|
167
192
|
prepared.packageFacts.packageName,
|
|
168
193
|
prepared.packageFacts.packageVersion,
|
|
169
194
|
JSON.stringify(prepared.packageFacts.dependencies),
|
|
170
195
|
JSON.stringify(prepared.packagePublicSurface),
|
|
196
|
+
environmentJson,
|
|
171
197
|
prepared.kind,
|
|
172
198
|
'indexing',
|
|
173
199
|
repoId,
|
|
@@ -183,6 +209,7 @@ export function publishPreparedRepositoryIndex(
|
|
|
183
209
|
insertRegistrations(db, repoId, prepared.parsed.registrations);
|
|
184
210
|
insertBindings(db, repoId, prepared.parsed.bindings);
|
|
185
211
|
insertCalls(db, repoId, prepared.parsed.calls);
|
|
212
|
+
insertGeneratedConstants(db, repoId, prepared.parsed.generatedConstants);
|
|
186
213
|
db.prepare("UPDATE repositories SET last_indexed_at=?, index_status='indexed', error_count=0, fingerprint=?, fact_generation=COALESCE(fact_generation,0)+1, graph_stale_reason='facts_changed', graph_stale_at=?, fact_analyzer_version=? WHERE id=?").run(now, prepared.fingerprint, now, ANALYZER_VERSION, repoId);
|
|
187
214
|
}
|
|
188
215
|
|
|
@@ -243,14 +270,21 @@ async function parseAllSourceFacts(
|
|
|
243
270
|
root: string,
|
|
244
271
|
sources: RepositorySourceContext,
|
|
245
272
|
): Promise<ParsedFacts> {
|
|
246
|
-
const facts: ParsedFacts = { services: [], handlers: [], registrations: [], bindings: [], calls: [], symbols: [], symbolCalls: [], fileRecords: [] };
|
|
273
|
+
const facts: ParsedFacts = { services: [], handlers: [], registrations: [], bindings: [], calls: [], symbols: [], symbolCalls: [], generatedConstants: [], fileRecords: [] };
|
|
247
274
|
for (const snapshot of sources.entries()) {
|
|
248
275
|
const file = snapshot.filePath;
|
|
249
276
|
facts.fileRecords.push({ relativePath: normalizePath(file), extension: path.extname(file), sha256: sha256Text(snapshot.text), sizeBytes: snapshot.sizeBytes });
|
|
250
277
|
if (file.endsWith('.cds')) facts.services.push(...(await parseCdsFile(root, file, sources)));
|
|
251
278
|
if (/\.[jt]s$/.test(file)) {
|
|
252
279
|
const source = snapshot.sourceFile();
|
|
253
|
-
|
|
280
|
+
facts.generatedConstants.push(...generatedConstantFacts(source, file));
|
|
281
|
+
const classified = classifyOutboundCallsInSource(source, file, {
|
|
282
|
+
importedEventNameResolver: createImportedEventNameResolver(
|
|
283
|
+
sources, source, file,
|
|
284
|
+
),
|
|
285
|
+
eventEnvironmentReferenceResolver:
|
|
286
|
+
createEventEnvironmentReferenceResolver(sources, source, file),
|
|
287
|
+
});
|
|
254
288
|
facts.handlers.push(...(await parseDecorators(root, file, sources)));
|
|
255
289
|
facts.registrations.push(...(await parseHandlerRegistrations(root, file, sources)));
|
|
256
290
|
const bindings = await parseServiceBindings(root, file, sources);
|
|
@@ -280,12 +314,17 @@ async function findSourceFiles(root: string): Promise<string[]> {
|
|
|
280
314
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
281
315
|
if (e.isDirectory()) {
|
|
282
316
|
if (!['node_modules', 'dist', 'gen', 'coverage', '.git'].includes(e.name)) await walk(path.join(dir, e.name), rel);
|
|
283
|
-
} else if (
|
|
317
|
+
} else if (isRepositoryFactInput(e.name)
|
|
318
|
+
&& !isDefaultTestFile(rel)) out.push(rel);
|
|
284
319
|
}
|
|
285
320
|
}
|
|
286
321
|
await walk(root);
|
|
287
322
|
return out.sort();
|
|
288
323
|
}
|
|
324
|
+
function isRepositoryFactInput(name: string): boolean {
|
|
325
|
+
return /\.(cds|ts|js)$/.test(name)
|
|
326
|
+
|| ['nodemon.json', '.env', 'mta.yaml', 'manifest.yml'].includes(name);
|
|
327
|
+
}
|
|
289
328
|
function isDefaultTestFile(relativeFile: string): boolean {
|
|
290
329
|
const parts = relativeFile.split('/');
|
|
291
330
|
if (parts.some((part) => ['test', 'tests', '__tests__'].includes(part))) return true;
|
|
@@ -13,11 +13,11 @@ import {
|
|
|
13
13
|
finalizePackageTargetInvalidations,
|
|
14
14
|
mergePackageInvalidationEffects,
|
|
15
15
|
type PackageInvalidationBatch,
|
|
16
|
-
} from '../db/
|
|
16
|
+
} from '../db/package-target-invalidation.js';
|
|
17
17
|
import {
|
|
18
18
|
isPreparedRepositorySnapshotError,
|
|
19
|
-
} from '../db/
|
|
20
|
-
import { binaryCompare } from '../parsers/
|
|
19
|
+
} from '../db/index-publication-failure.js';
|
|
20
|
+
import { binaryCompare } from '../parsers/fact-identity.js';
|
|
21
21
|
// Ownerless rows predate PID coordination; this matches doctor's stale-run threshold without taking over a recent legacy writer.
|
|
22
22
|
const LEGACY_OWNER_RECOVERY_MS = 60 * 60 * 1_000;
|
|
23
23
|
type RunningIndexRow = Record<string, unknown>;
|
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
linkedCallEvidence,
|
|
5
5
|
objectJson,
|
|
6
6
|
objectValue,
|
|
7
|
-
} from './
|
|
7
|
+
} from './call-evidence.js';
|
|
8
8
|
import { applyVariables } from './dynamic-edge-resolver.js';
|
|
9
|
-
import { insertEventCallEdge } from './
|
|
9
|
+
import { insertEventCallEdge } from './event-template-link.js';
|
|
10
10
|
import { externalHttpTarget } from './external-http-target.js';
|
|
11
11
|
import {
|
|
12
12
|
classifyODataPathIntent,
|
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
boundCandidateLikeEvidence,
|
|
7
7
|
projectBounded,
|
|
8
8
|
type BoundedProjection,
|
|
9
|
-
} from '../utils/
|
|
10
|
-
import { extractPlaceholderKeys } from '../utils/
|
|
9
|
+
} from '../utils/bounded-projection.js';
|
|
10
|
+
import { extractPlaceholderKeys } from '../utils/placeholders.js';
|
|
11
11
|
|
|
12
12
|
export interface LinkedOperationResolution {
|
|
13
13
|
target?: {
|