162 lines · 4.7 KB · TypeScript
RawDownload
import * as Schema from "effect/Schema"; import {  type ConnectionRegistration,  ConnectionCredential,  ConnectionProfile,} from "../connection/catalog.ts";import { type ConnectionTarget, PersistedConnectionTarget } from "../connection/model.ts";import * as TokenStore from "../authorization/tokenStore.ts"; export const StoredConnectionCredential = Schema.Struct({  connectionId: Schema.String,  credential: ConnectionCredential,});export type StoredConnectionCredential = typeof StoredConnectionCredential.Type; export const ConnectionCatalogDocument = Schema.Struct({  schemaVersion: Schema.Literal(1),  targets: Schema.Array(PersistedConnectionTarget),  profiles: Schema.Array(ConnectionProfile),  credentials: Schema.Array(StoredConnectionCredential),  remoteDpopTokens: Schema.Array(TokenStore.RemoteDpopAccessToken),});export type ConnectionCatalogDocument = typeof ConnectionCatalogDocument.Type; export const EMPTY_CONNECTION_CATALOG_DOCUMENT: ConnectionCatalogDocument = Object.freeze({  schemaVersion: 1,  targets: [],  profiles: [],  credentials: [],  remoteDpopTokens: [],}); export function replaceCatalogValue<A>(  values: ReadonlyArray<A>,  key: (value: A) => string,  next: A,): ReadonlyArray<A> {  const nextKey = key(next);  return [...values.filter((value) => key(value) !== nextKey), next];} export function removeCatalogValue<A>(  values: ReadonlyArray<A>,  key: (value: A) => string,  removedKey: string,): ReadonlyArray<A> {  return values.filter((value) => key(value) !== removedKey);} function connectionIdOf(target: ConnectionTarget): string | null {  switch (target._tag) {    case "PrimaryConnectionTarget":    case "RelayConnectionTarget":      return null;    case "BearerConnectionTarget":    case "SshConnectionTarget":      return target.connectionId;  }} function removeConnectionMetadata(  document: ConnectionCatalogDocument,  target: ConnectionTarget,  removeRemoteToken: boolean,): ConnectionCatalogDocument {  const connectionId = connectionIdOf(target);  return {    ...document,    targets: removeCatalogValue(      document.targets,      (value) => value.environmentId,      target.environmentId,    ),    profiles:      connectionId === null        ? document.profiles        : removeCatalogValue(document.profiles, (value) => value.connectionId, connectionId),    credentials:      connectionId === null        ? document.credentials        : removeCatalogValue(document.credentials, (value) => value.connectionId, connectionId),    remoteDpopTokens: removeRemoteToken      ? removeCatalogValue(          document.remoteDpopTokens,          (value) => value.environmentId,          target.environmentId,        )      : document.remoteDpopTokens,  };} export function registerConnectionInCatalog(  document: ConnectionCatalogDocument,  registration: ConnectionRegistration,): ConnectionCatalogDocument {  const target = registration.target;  const previous = document.targets.find(    (candidate) => candidate.environmentId === target.environmentId,  );  const cleaned =    previous === undefined ? document : removeConnectionMetadata(document, previous, false);  const next: ConnectionCatalogDocument = {    ...cleaned,    targets: replaceCatalogValue(cleaned.targets, (value) => value.environmentId, target),  };   switch (registration._tag) {    case "RelayConnectionRegistration":      return next;    case "BearerConnectionRegistration":      return {        ...next,        profiles: replaceCatalogValue(          next.profiles,          (value) => value.connectionId,          registration.profile,        ),        credentials: replaceCatalogValue(next.credentials, (value) => value.connectionId, {          connectionId: registration.target.connectionId,          credential: registration.credential,        }),      };    case "SshConnectionRegistration":      return {        ...next,        profiles: replaceCatalogValue(          next.profiles,          (value) => value.connectionId,          registration.profile,        ),      };  }} export function removeConnectionFromCatalog(  document: ConnectionCatalogDocument,  target: ConnectionTarget,): ConnectionCatalogDocument {  return removeConnectionMetadata(document, target, true);} export function putRemoteDpopTokenInCatalog(  document: ConnectionCatalogDocument,  token: TokenStore.RemoteDpopAccessToken,): ConnectionCatalogDocument {  const registered = document.targets.some(    (target) =>      target._tag === "RelayConnectionTarget" && target.environmentId === token.environmentId,  );  if (!registered) {    return document;  }  return {    ...document,    remoteDpopTokens: replaceCatalogValue(      document.remoteDpopTokens,      (value) => value.environmentId,      token,    ),  };}