( inputs: readonly PlannedOAuthClientInput[], )
| 762 | }; |
| 763 | |
| 764 | export const dedupeOAuthClients = ( |
| 765 | inputs: readonly PlannedOAuthClientInput[], |
| 766 | ): OAuthClientDedupResult => { |
| 767 | const slugByDedupKey: Record<string, string> = {}; |
| 768 | const clients: DedupedOAuthClient[] = []; |
| 769 | // Per-partition taken slugs, so two distinct apps in one partition disambiguate. |
| 770 | const takenByPartition = new Map<string, Set<string>>(); |
| 771 | |
| 772 | for (const input of inputs) { |
| 773 | const partition = ownerPartitionKey(input.ownerKeys); |
| 774 | const key = oauthClientPlanDedupKey(input); |
| 775 | if (slugByDedupKey[key]) continue; // already folded — identical app |
| 776 | |
| 777 | const taken = takenByPartition.get(partition) ?? new Set<string>(); |
| 778 | const base = hostSlug(input.tokenUrl); |
| 779 | let slug = base; |
| 780 | let n = 2; |
| 781 | while (taken.has(slug)) slug = `${base}_${n++}`; |
| 782 | taken.add(slug); |
| 783 | takenByPartition.set(partition, taken); |
| 784 | |
| 785 | slugByDedupKey[key] = slug; |
| 786 | clients.push({ ...input, slug }); |
| 787 | } |
| 788 | |
| 789 | return { clients, slugByDedupKey }; |
| 790 | }; |
| 791 | |
| 792 | const secretReadRefKey = (ref: SecretReadRef): string => |
| 793 | `${ref.provider}\0${ref.scopeId}\0${ref.secretId}`; |
no test coverage detected