* Resolve identifiers to property_rids. * In 'resolve' mode: creates missing properties, logs activity. * In 'lookup' mode: returns existing only, no creates, no logging.
(
identifiers: ResolveInput[],
mode: ResolveMode,
memberId: string,
provenance: Provenance
)
| 130 | * In 'lookup' mode: returns existing only, no creates, no logging. |
| 131 | */ |
| 132 | async resolveIdentifiers( |
| 133 | identifiers: ResolveInput[], |
| 134 | mode: ResolveMode, |
| 135 | memberId: string, |
| 136 | provenance: Provenance |
| 137 | ): Promise<ResolveResult> { |
| 138 | const normalized = identifiers.map(({ type, value }) => normalizeIdentifier(type, value)); |
| 139 | const results: ResolvedEntry[] = []; |
| 140 | let created = 0; |
| 141 | let excluded = 0; |
| 142 | let notFound = 0; |
| 143 | |
| 144 | // Batch lookup: find all existing identifiers |
| 145 | const existing = await this.batchLookupIdentifiers( |
| 146 | normalized.map(n => ({ type: n.type, value: n.value })) |
| 147 | ); |
| 148 | |
| 149 | // Check aliases for any found rids |
| 150 | const aliasMap = await this.batchResolveAliases( |
| 151 | [...new Set( |
| 152 | Array.from(existing.values()) |
| 153 | .filter(e => e !== null) |
| 154 | .map(e => e!.property_rid) |
| 155 | )] |
| 156 | ); |
| 157 | |
| 158 | // For unknown identifiers, batch-fetch classifications from catalog_facts |
| 159 | const unknownNorms = normalized.filter(n => !existing.has(`${n.type}:${n.value}`)); |
| 160 | const classifications = unknownNorms.length > 0 |
| 161 | ? await this.batchGetClassifications(unknownNorms.map(n => `${n.type}:${n.value}`)) |
| 162 | : new Map<string, string>(); |
| 163 | |
| 164 | // Collect entries to batch-create |
| 165 | const toCreate: Array<{ |
| 166 | propertyRid: string; |
| 167 | identifierType: string; |
| 168 | identifierValue: string; |
| 169 | memberId: string; |
| 170 | provenance: Provenance; |
| 171 | }> = []; |
| 172 | |
| 173 | // First pass: classify all results without DB writes |
| 174 | for (const norm of normalized) { |
| 175 | const key = `${norm.type}:${norm.value}`; |
| 176 | const found = existing.get(key); |
| 177 | |
| 178 | if (found) { |
| 179 | const canonicalRid = aliasMap.get(found.property_rid) ?? found.property_rid; |
| 180 | results.push({ |
| 181 | identifier: { type: norm.type, value: norm.value }, |
| 182 | property_rid: canonicalRid, |
| 183 | classification: found.classification, |
| 184 | status: 'existing', |
| 185 | source: found.source, |
| 186 | }); |
| 187 | } else if (mode === 'resolve') { |
| 188 | const classification = classifications.get(`${norm.type}:${norm.value}`) ?? null; |
| 189 |
no test coverage detected