@shapeshift-labs/frontier-lang-compiler 0.2.78 → 0.2.79
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.
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
SourceSpan
|
|
7
7
|
} from '@shapeshift-labs/frontier-lang-kernel';
|
|
8
8
|
import type { SemanticImportOwnershipRegion } from './semantic-sidecar.js';
|
|
9
|
-
import type { CreateSemanticLineageEventInput, SemanticLineageEvent } from './semantic-lineage.js';
|
|
9
|
+
import type { CreateSemanticLineageEventInput, SemanticAnchor, SemanticLineageEvent, SemanticLineageMap, SemanticLineageResolution } from './semantic-lineage.js';
|
|
10
10
|
|
|
11
11
|
import type { SemanticHistoryAdmissionStatus, SemanticHistoryReviewerStatus, SemanticHistoryReplayLinkKind, SemanticHistoryOverlapKind, SemanticHistoryConflictReason, SemanticHistoryClaimKind, SemanticHistoryClaimStatus, SemanticHistoryProofAttemptStatus, SemanticHistoryMergeDecisionStatus, SemanticHistoryActorRef, SemanticHistoryRecordSourceRef, SemanticHistorySourceRef, SemanticHistoryOwnershipRegionRef, SemanticHistoryCandidateRef, SemanticHistoryClaimRecord, SemanticHistoryImportedParserEvidenceRecord, SemanticHistoryProofAttemptRecord, SemanticHistoryPatchAncestryRecord, SemanticHistoryMergeDecisionRecord, SemanticHistoryClaimInput, SemanticHistoryImportedParserEvidenceInput, SemanticHistoryProofAttemptInput, SemanticHistoryPatchAncestryInput, SemanticHistoryMergeDecisionInput, SemanticHistoryReviewerState, SemanticHistoryAdmissionState, SemanticHistoryReplayLink, SemanticHistoryRecordIndex } from './semantic-history-records.js';
|
|
12
12
|
export type { SemanticHistoryAdmissionStatus, SemanticHistoryReviewerStatus, SemanticHistoryReplayLinkKind, SemanticHistoryOverlapKind, SemanticHistoryConflictReason, SemanticHistoryClaimKind, SemanticHistoryClaimStatus, SemanticHistoryProofAttemptStatus, SemanticHistoryMergeDecisionStatus, SemanticHistoryActorRef, SemanticHistoryRecordSourceRef, SemanticHistorySourceRef, SemanticHistoryOwnershipRegionRef, SemanticHistoryCandidateRef, SemanticHistoryClaimRecord, SemanticHistoryImportedParserEvidenceRecord, SemanticHistoryProofAttemptRecord, SemanticHistoryPatchAncestryRecord, SemanticHistoryMergeDecisionRecord, SemanticHistoryClaimInput, SemanticHistoryImportedParserEvidenceInput, SemanticHistoryProofAttemptInput, SemanticHistoryPatchAncestryInput, SemanticHistoryMergeDecisionInput, SemanticHistoryReviewerState, SemanticHistoryAdmissionState, SemanticHistoryReplayLink, SemanticHistoryRecordIndex } from './semantic-history-records.js';
|
|
@@ -138,6 +138,51 @@ export interface SemanticHistoryOverlapRecord {
|
|
|
138
138
|
readonly reviewer: { readonly left?: SemanticHistoryReviewerStatus; readonly right?: SemanticHistoryReviewerStatus };
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
export type SemanticHistoryLineageAnchorSetKind = 'active' | 'candidate' | 'inactive' | 'deleted' | 'unresolved' | 'blocked';
|
|
142
|
+
|
|
143
|
+
export interface SemanticHistoryLineageAnchorRecord extends Pick<SemanticAnchor, 'key' | 'id' | 'kind' | 'language' | 'sourcePath' | 'symbolId' | 'symbolName'> {
|
|
144
|
+
readonly status: string;
|
|
145
|
+
readonly resolutionId: string;
|
|
146
|
+
readonly reasonCodes: readonly string[];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export type SemanticHistoryLineageAnchorInventory = Readonly<Record<SemanticHistoryLineageAnchorSetKind, readonly SemanticHistoryLineageAnchorRecord[]>>;
|
|
150
|
+
|
|
151
|
+
export interface SemanticHistoryRecordLineageResolution {
|
|
152
|
+
readonly kind: 'frontier.lang.semanticHistoryRecordLineageResolution';
|
|
153
|
+
readonly version: 1;
|
|
154
|
+
readonly id: string;
|
|
155
|
+
readonly stableId: string;
|
|
156
|
+
readonly hash: string;
|
|
157
|
+
readonly sourceRecordId?: string;
|
|
158
|
+
readonly sourceRecordStableId?: string;
|
|
159
|
+
readonly sourceRecordHash?: string;
|
|
160
|
+
readonly generatedAt: number | string;
|
|
161
|
+
readonly resolutions: readonly SemanticLineageResolution[];
|
|
162
|
+
readonly anchorInventory: SemanticHistoryLineageAnchorInventory;
|
|
163
|
+
readonly resolvedRecord: SemanticHistoryRecord;
|
|
164
|
+
readonly summary: Record<string, unknown> & {
|
|
165
|
+
readonly anchorCount: number;
|
|
166
|
+
readonly currentAnchorKeys: readonly string[];
|
|
167
|
+
readonly ownershipKeys: readonly string[];
|
|
168
|
+
readonly conflictKeys: readonly string[];
|
|
169
|
+
readonly activeAnchorKeys: readonly string[];
|
|
170
|
+
readonly candidateAnchorKeys: readonly string[];
|
|
171
|
+
readonly inactiveAnchorKeys: readonly string[];
|
|
172
|
+
readonly deletedAnchorKeys: readonly string[];
|
|
173
|
+
readonly unresolvedAnchorKeys: readonly string[];
|
|
174
|
+
readonly blockedAnchorKeys: readonly string[];
|
|
175
|
+
readonly reasonCodes: readonly string[];
|
|
176
|
+
};
|
|
177
|
+
readonly admission: {
|
|
178
|
+
readonly readiness: SemanticMergeReadiness | string;
|
|
179
|
+
readonly reviewRequired: boolean;
|
|
180
|
+
readonly autoMergeClaim: false;
|
|
181
|
+
readonly semanticEquivalenceClaim: false;
|
|
182
|
+
};
|
|
183
|
+
readonly metadata?: Record<string, unknown>;
|
|
184
|
+
}
|
|
185
|
+
|
|
141
186
|
export declare const SemanticHistoryAdmissionStatuses: readonly SemanticHistoryAdmissionStatus[];
|
|
142
187
|
export declare const SemanticHistoryReviewerStatuses: readonly SemanticHistoryReviewerStatus[];
|
|
143
188
|
export declare const SemanticHistoryOverlapKinds: readonly SemanticHistoryOverlapKind[];
|
|
@@ -146,3 +191,5 @@ export declare function createSemanticHistoryRecord(input?: CreateSemanticHistor
|
|
|
146
191
|
export declare function querySemanticHistoryRecordOverlaps(records: SemanticHistoryRecord | readonly SemanticHistoryRecord[], options?: SemanticHistoryOverlapQueryOptions): readonly SemanticHistoryOverlapRecord[];
|
|
147
192
|
export declare function semanticHistoryRecordsOverlap(left: SemanticHistoryRecord, right: SemanticHistoryRecord, options?: SemanticHistoryOverlapQueryOptions): boolean;
|
|
148
193
|
export declare function semanticHistoryRecordsConflict(left: SemanticHistoryRecord, right: SemanticHistoryRecord, options?: SemanticHistoryOverlapQueryOptions): boolean;
|
|
194
|
+
export declare function resolveSemanticHistoryRecordLineage(record: SemanticHistoryRecord, eventsOrMap?: SemanticLineageMap | readonly CreateSemanticLineageEventInput[], options?: { readonly id?: string; readonly generatedAt?: number | string; readonly maxDepth?: number; readonly keepDeletedAnchors?: boolean; readonly keepCandidateAnchors?: boolean; readonly keepBlockedAnchors?: boolean; readonly keepUnresolvedAnchors?: boolean; readonly metadata?: Record<string, unknown> }): SemanticHistoryRecordLineageResolution;
|
|
195
|
+
export declare function resolveSemanticHistoryRecordsLineage(records: readonly SemanticHistoryRecord[] | SemanticHistoryRecord, eventsOrMap?: SemanticLineageMap | readonly CreateSemanticLineageEventInput[], options?: { readonly generatedAt?: number | string; readonly maxDepth?: number; readonly keepDeletedAnchors?: boolean; readonly keepCandidateAnchors?: boolean; readonly keepBlockedAnchors?: boolean; readonly keepUnresolvedAnchors?: boolean; readonly metadata?: Record<string, unknown> }): readonly SemanticHistoryRecordLineageResolution[];
|
package/dist/index.js
CHANGED
|
@@ -73,6 +73,7 @@ export { queryUniversalConversionPlan } from './internal/index-impl/queryUnivers
|
|
|
73
73
|
export { createSemanticAnchor, createSemanticLineageEvent, createSemanticLineageMap, querySemanticLineageEvents, SemanticLineageEventKinds } from './internal/index-impl/semanticLineageRecords.js';
|
|
74
74
|
export { resolveSemanticLineage, resolveSemanticLineageBatch, SemanticLineageResolutionStatuses } from './internal/index-impl/semanticLineageResolutionRecords.js';
|
|
75
75
|
export { createSemanticHistoryRecord, querySemanticHistoryRecordOverlaps, SemanticHistoryAdmissionStatuses, SemanticHistoryConflictReasons, SemanticHistoryOverlapKinds, SemanticHistoryReviewerStatuses, semanticHistoryRecordsConflict, semanticHistoryRecordsOverlap } from './internal/index-impl/semanticHistoryRecords.js';
|
|
76
|
+
export { resolveSemanticHistoryRecordLineage, resolveSemanticHistoryRecordsLineage } from './internal/index-impl/semanticHistoryLineageResolution.js';
|
|
76
77
|
export { readSemanticSliceJson } from './internal/index-impl/readSemanticSliceJson.js';
|
|
77
78
|
export { readUniversalAstJson } from './internal/index-impl/readUniversalAstJson.js';
|
|
78
79
|
export { renderTargetAst } from './internal/index-impl/renderTargetAst.js';
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { hashSemanticValue } from '@shapeshift-labs/frontier-lang-kernel';
|
|
2
|
+
import { idFragment, uniqueStrings as uniqueRawStrings } from '../../native-import-utils.js';
|
|
3
|
+
import { resolveSemanticLineage } from './semanticLineageResolutionRecords.js';
|
|
4
|
+
|
|
5
|
+
export function resolveSemanticHistoryRecordLineage(record = {}, eventsOrMap = [], options = {}) {
|
|
6
|
+
const generatedAt = options.generatedAt ?? Date.now();
|
|
7
|
+
const sourceIndex = record.index ?? {};
|
|
8
|
+
const anchorKeys = uniqueStrings([
|
|
9
|
+
...array(sourceIndex.semanticAnchorKeys),
|
|
10
|
+
...array(sourceIndex.ownershipKeys),
|
|
11
|
+
...array(sourceIndex.conflictKeys)
|
|
12
|
+
]);
|
|
13
|
+
const resolutions = anchorKeys.map((anchorKey) => resolveSemanticLineage(eventsOrMap, {
|
|
14
|
+
anchorKey,
|
|
15
|
+
generatedAt
|
|
16
|
+
}, { maxDepth: options.maxDepth }));
|
|
17
|
+
const byAnchorKey = new Map(resolutions.map((resolution) => [resolution.query.anchorKey, resolution]));
|
|
18
|
+
const resolvedIndex = {
|
|
19
|
+
...sourceIndex,
|
|
20
|
+
ownershipKeys: resolveIndexKeys(sourceIndex.ownershipKeys, byAnchorKey, options),
|
|
21
|
+
conflictKeys: resolveIndexKeys(sourceIndex.conflictKeys, byAnchorKey, options),
|
|
22
|
+
semanticAnchorKeys: resolveIndexKeys(sourceIndex.semanticAnchorKeys, byAnchorKey, options),
|
|
23
|
+
sourcePaths: uniqueStrings([
|
|
24
|
+
...array(sourceIndex.sourcePaths),
|
|
25
|
+
...resolutions.flatMap((resolution) => resolution.currentAnchors.map((anchor) => anchor.sourcePath))
|
|
26
|
+
]),
|
|
27
|
+
lineageEventIds: uniqueStrings([
|
|
28
|
+
...array(sourceIndex.lineageEventIds),
|
|
29
|
+
...resolutions.flatMap((resolution) => resolution.traversedEventIds)
|
|
30
|
+
]),
|
|
31
|
+
semanticLineageKinds: uniqueStrings([
|
|
32
|
+
...array(sourceIndex.semanticLineageKinds),
|
|
33
|
+
...resolutions.flatMap((resolution) => resolution.lineageEventKinds)
|
|
34
|
+
]),
|
|
35
|
+
crdtOperationIds: uniqueStrings([
|
|
36
|
+
...array(sourceIndex.crdtOperationIds),
|
|
37
|
+
...resolutions.flatMap((resolution) => resolution.crdtOperationIds)
|
|
38
|
+
]),
|
|
39
|
+
crdtHeads: uniqueStrings([
|
|
40
|
+
...array(sourceIndex.crdtHeads),
|
|
41
|
+
...resolutions.flatMap((resolution) => resolution.crdtHeads)
|
|
42
|
+
]),
|
|
43
|
+
evidenceIds: uniqueStrings([
|
|
44
|
+
...array(sourceIndex.evidenceIds),
|
|
45
|
+
...resolutions.flatMap((resolution) => resolution.evidenceIds)
|
|
46
|
+
]),
|
|
47
|
+
proofIds: uniqueStrings([
|
|
48
|
+
...array(sourceIndex.proofIds),
|
|
49
|
+
...resolutions.flatMap((resolution) => resolution.proofIds)
|
|
50
|
+
])
|
|
51
|
+
};
|
|
52
|
+
const anchorInventory = createAnchorInventory(resolutions);
|
|
53
|
+
const summary = summarizeSemanticHistoryLineageResolutions(resolutions, resolvedIndex, anchorInventory);
|
|
54
|
+
const readiness = summary.cycle > 0 || summary.maxDepth > 0 ? 'blocked' : summary.resolved > 0 || summary.ambiguous > 0 || summary.deleted > 0 || summary.recreated > 0 ? 'needs-review' : 'ready';
|
|
55
|
+
const resolutionCore = {
|
|
56
|
+
kind: 'frontier.lang.semanticHistoryRecordLineageResolution',
|
|
57
|
+
version: 1,
|
|
58
|
+
sourceRecordId: record.id,
|
|
59
|
+
sourceRecordStableId: record.stableId,
|
|
60
|
+
sourceRecordHash: record.hash,
|
|
61
|
+
generatedAt,
|
|
62
|
+
resolutions,
|
|
63
|
+
anchorInventory,
|
|
64
|
+
summary,
|
|
65
|
+
admission: {
|
|
66
|
+
readiness,
|
|
67
|
+
reviewRequired: readiness !== 'ready',
|
|
68
|
+
autoMergeClaim: false,
|
|
69
|
+
semanticEquivalenceClaim: false
|
|
70
|
+
},
|
|
71
|
+
metadata: compactRecord(options.metadata)
|
|
72
|
+
};
|
|
73
|
+
const hash = hashSemanticValue(resolutionCore);
|
|
74
|
+
const id = options.id ?? `semantic_history_lineage_resolution_${idFragment(firstString(record.id, record.stableId, hash))}`;
|
|
75
|
+
const resolvedRecord = createResolvedHistoryRecord(record, resolvedIndex, { id, hash, generatedAt, summary, readiness });
|
|
76
|
+
return {
|
|
77
|
+
...resolutionCore,
|
|
78
|
+
id,
|
|
79
|
+
stableId: `semantic_history_lineage_resolution_${idFragment(hash)}`,
|
|
80
|
+
hash,
|
|
81
|
+
resolvedRecord
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function resolveSemanticHistoryRecordsLineage(records = [], eventsOrMap = [], options = {}) {
|
|
86
|
+
return array(records).map((record) => resolveSemanticHistoryRecordLineage(record, eventsOrMap, options));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function createResolvedHistoryRecord(record, index, resolution) {
|
|
90
|
+
const core = {
|
|
91
|
+
...record,
|
|
92
|
+
id: `${record.id ?? 'semantic_history'}#lineage-resolved`,
|
|
93
|
+
index,
|
|
94
|
+
metadata: {
|
|
95
|
+
...(record.metadata ?? {}),
|
|
96
|
+
semanticHistoryLineageResolution: {
|
|
97
|
+
id: resolution.id,
|
|
98
|
+
sourceRecordId: record.id,
|
|
99
|
+
sourceRecordHash: record.hash,
|
|
100
|
+
readiness: resolution.readiness,
|
|
101
|
+
summary: resolution.summary,
|
|
102
|
+
anchorSummary: {
|
|
103
|
+
activeAnchorKeys: resolution.summary.activeAnchorKeys,
|
|
104
|
+
candidateAnchorKeys: resolution.summary.candidateAnchorKeys,
|
|
105
|
+
inactiveAnchorKeys: resolution.summary.inactiveAnchorKeys,
|
|
106
|
+
blockedAnchorKeys: resolution.summary.blockedAnchorKeys
|
|
107
|
+
},
|
|
108
|
+
autoMergeClaim: false,
|
|
109
|
+
semanticEquivalenceClaim: false
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
const stableCore = { ...core };
|
|
114
|
+
delete stableCore.hash;
|
|
115
|
+
delete stableCore.stableId;
|
|
116
|
+
const hash = hashSemanticValue(stableCore);
|
|
117
|
+
return {
|
|
118
|
+
...core,
|
|
119
|
+
stableId: `semantic_history_${idFragment(hash)}`,
|
|
120
|
+
hash
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function resolveIndexKeys(values, resolutions, options) {
|
|
125
|
+
return uniqueStrings(array(values).flatMap((value) => {
|
|
126
|
+
const key = String(value);
|
|
127
|
+
const resolution = resolutions.get(key);
|
|
128
|
+
if (!resolution) return [key];
|
|
129
|
+
if (resolution.status === 'deleted' && options.keepDeletedAnchors !== true) return [];
|
|
130
|
+
if (resolution.status === 'cycle' && options.keepBlockedAnchors !== true) return [];
|
|
131
|
+
if (resolution.status === 'max-depth' && options.keepBlockedAnchors !== true) return [];
|
|
132
|
+
if (resolution.status === 'not-found' && options.keepUnresolvedAnchors !== true) return [];
|
|
133
|
+
if (resolution.status === 'ambiguous' && options.keepCandidateAnchors === false) return [];
|
|
134
|
+
const current = resolution.currentAnchors.map((anchor) => anchor.key).filter(Boolean);
|
|
135
|
+
return current.length ? current : [key];
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function summarizeSemanticHistoryLineageResolutions(resolutions, index, anchorInventory) {
|
|
140
|
+
const byStatus = {};
|
|
141
|
+
for (const resolution of resolutions) byStatus[resolution.status] = (byStatus[resolution.status] ?? 0) + 1;
|
|
142
|
+
return {
|
|
143
|
+
anchorCount: resolutions.length,
|
|
144
|
+
unchanged: byStatus.unchanged ?? 0,
|
|
145
|
+
resolved: byStatus.resolved ?? 0,
|
|
146
|
+
ambiguous: byStatus.ambiguous ?? 0,
|
|
147
|
+
deleted: byStatus.deleted ?? 0,
|
|
148
|
+
recreated: byStatus.recreated ?? 0,
|
|
149
|
+
cycle: byStatus.cycle ?? 0,
|
|
150
|
+
maxDepth: byStatus['max-depth'] ?? 0,
|
|
151
|
+
notFound: byStatus['not-found'] ?? 0,
|
|
152
|
+
currentAnchorKeys: uniqueStrings(index.semanticAnchorKeys),
|
|
153
|
+
ownershipKeys: uniqueStrings(index.ownershipKeys),
|
|
154
|
+
conflictKeys: uniqueStrings(index.conflictKeys),
|
|
155
|
+
sourcePaths: uniqueStrings(index.sourcePaths),
|
|
156
|
+
activeAnchorKeys: uniqueStrings(anchorInventory.active.map((anchor) => anchor.key)),
|
|
157
|
+
candidateAnchorKeys: uniqueStrings(anchorInventory.candidate.map((anchor) => anchor.key)),
|
|
158
|
+
inactiveAnchorKeys: uniqueStrings(anchorInventory.inactive.map((anchor) => anchor.key)),
|
|
159
|
+
deletedAnchorKeys: uniqueStrings(anchorInventory.deleted.map((anchor) => anchor.key)),
|
|
160
|
+
unresolvedAnchorKeys: uniqueStrings(anchorInventory.unresolved.map((anchor) => anchor.key)),
|
|
161
|
+
blockedAnchorKeys: uniqueStrings(anchorInventory.blocked.map((anchor) => anchor.key)),
|
|
162
|
+
traversedEventIds: uniqueStrings(resolutions.flatMap((resolution) => resolution.traversedEventIds)),
|
|
163
|
+
terminalEventIds: uniqueStrings(resolutions.flatMap((resolution) => resolution.terminalEventIds)),
|
|
164
|
+
reasonCodes: uniqueStrings(resolutions.flatMap((resolution) => resolution.reasonCodes))
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function createAnchorInventory(resolutions) {
|
|
169
|
+
const inventory = {
|
|
170
|
+
active: [],
|
|
171
|
+
candidate: [],
|
|
172
|
+
inactive: [],
|
|
173
|
+
deleted: [],
|
|
174
|
+
unresolved: [],
|
|
175
|
+
blocked: []
|
|
176
|
+
};
|
|
177
|
+
for (const resolution of resolutions) {
|
|
178
|
+
const start = anchorEntry(resolution.startAnchor ?? queryAnchor(resolution), resolution);
|
|
179
|
+
const current = resolution.currentAnchors.map((anchor) => anchorEntry(anchor, resolution));
|
|
180
|
+
if (resolution.status === 'ambiguous') {
|
|
181
|
+
inventory.candidate.push(...current);
|
|
182
|
+
if (start) inventory.inactive.push(start);
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (resolution.status === 'deleted') {
|
|
186
|
+
if (start) {
|
|
187
|
+
inventory.inactive.push(start);
|
|
188
|
+
inventory.deleted.push(start);
|
|
189
|
+
}
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (resolution.status === 'cycle' || resolution.status === 'max-depth') {
|
|
193
|
+
if (start) {
|
|
194
|
+
inventory.inactive.push(start);
|
|
195
|
+
inventory.blocked.push(start);
|
|
196
|
+
}
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
if (resolution.status === 'not-found') {
|
|
200
|
+
if (start) {
|
|
201
|
+
inventory.inactive.push(start);
|
|
202
|
+
inventory.unresolved.push(start);
|
|
203
|
+
}
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
inventory.active.push(...current);
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
active: uniqueAnchorEntries(inventory.active),
|
|
210
|
+
candidate: uniqueAnchorEntries(inventory.candidate),
|
|
211
|
+
inactive: uniqueAnchorEntries(inventory.inactive),
|
|
212
|
+
deleted: uniqueAnchorEntries(inventory.deleted),
|
|
213
|
+
unresolved: uniqueAnchorEntries(inventory.unresolved),
|
|
214
|
+
blocked: uniqueAnchorEntries(inventory.blocked)
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function anchorEntry(anchor, resolution) {
|
|
219
|
+
if (!anchor) return undefined;
|
|
220
|
+
return compactRecord({
|
|
221
|
+
key: anchor.key,
|
|
222
|
+
id: anchor.id,
|
|
223
|
+
kind: anchor.kind,
|
|
224
|
+
language: anchor.language,
|
|
225
|
+
sourcePath: anchor.sourcePath,
|
|
226
|
+
symbolId: anchor.symbolId,
|
|
227
|
+
symbolName: anchor.symbolName,
|
|
228
|
+
status: resolution.status,
|
|
229
|
+
resolutionId: resolution.id,
|
|
230
|
+
reasonCodes: uniqueStrings(resolution.reasonCodes)
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function queryAnchor(resolution) {
|
|
235
|
+
return compactRecord({
|
|
236
|
+
key: resolution.query?.anchorKey,
|
|
237
|
+
id: resolution.query?.anchorId,
|
|
238
|
+
sourcePath: resolution.query?.sourcePath,
|
|
239
|
+
symbolName: resolution.query?.symbolName
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function uniqueAnchorEntries(entries) {
|
|
244
|
+
const seen = new Set();
|
|
245
|
+
return entries.filter(Boolean).filter((entry) => {
|
|
246
|
+
const key = entry.key ?? entry.id ?? `${entry.sourcePath ?? ''}:${entry.symbolName ?? ''}`;
|
|
247
|
+
if (!key || seen.has(key)) return false;
|
|
248
|
+
seen.add(key);
|
|
249
|
+
return true;
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function array(value) { return value === undefined || value === null ? [] : Array.isArray(value) ? value : [value]; }
|
|
254
|
+
function uniqueStrings(values) { return uniqueRawStrings(array(values).map((value) => String(value ?? '')).filter(Boolean)); }
|
|
255
|
+
function firstString(...values) { return values.map((value) => value === undefined || value === null ? '' : String(value)).find(Boolean); }
|
|
256
|
+
function compactRecord(value) { return Object.fromEntries(Object.entries(value ?? {}).filter(([, entry]) => entry !== undefined)); }
|
package/package.json
CHANGED