import { ConnectionPersistenceError, ConnectionRegistrationStore, ConnectionTargetStore, putRemoteDpopTokenInCatalog, registerConnectionInCatalog, removeConnectionFromCatalog, removeCatalogValue, replaceCatalogValue,} from "@t3tools/client-runtime/platform";import { TokenStore } from "@t3tools/client-runtime/authorization";import { ConnectionTransientError, CredentialStore, ProfileStore,} from "@t3tools/client-runtime/connection";import * as Context from "effect/Context";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Option from "effect/Option";import * as CatalogStore from "./catalog-store"; function targetPersistenceError( operation: "list-targets" | "register-connection" | "remove-connection", error: ConnectionTransientError,) { return new ConnectionPersistenceError({ operation, message: error.message, });} export const connectionStorageLayer = Layer.effectContext( Effect.gen(function* () { const catalog = yield* CatalogStore.make(); const targetStore = ConnectionTargetStore.of({ list: catalog.read.pipe( Effect.map((document) => document.targets), Effect.mapError((error) => targetPersistenceError("list-targets", error)), ), }); const registrationStore = ConnectionRegistrationStore.of({ register: (registration) => catalog .update((document) => registerConnectionInCatalog(document, registration)) .pipe(Effect.mapError((error) => targetPersistenceError("register-connection", error))), remove: (target) => catalog .update((document) => removeConnectionFromCatalog(document, target)) .pipe(Effect.mapError((error) => targetPersistenceError("remove-connection", error))), }); const profileStore = ProfileStore.make({ get: (connectionId) => catalog.read.pipe( Effect.map((document) => Option.fromUndefinedOr( document.profiles.find((candidate) => candidate.connectionId === connectionId), ), ), ), put: (profile) => catalog.update((document) => ({ ...document, profiles: replaceCatalogValue(document.profiles, (value) => value.connectionId, profile), })), remove: (connectionId) => catalog.update((document) => ({ ...document, profiles: removeCatalogValue( document.profiles, (value) => value.connectionId, connectionId, ), })), }); const credentialStore = CredentialStore.make({ get: (connectionId) => catalog.read.pipe( Effect.map((document) => Option.fromUndefinedOr( document.credentials.find((entry) => entry.connectionId === connectionId)?.credential, ), ), ), put: (connectionId, credential) => catalog.update((document) => ({ ...document, credentials: replaceCatalogValue(document.credentials, (value) => value.connectionId, { connectionId, credential, }), })), remove: (connectionId) => catalog.update((document) => ({ ...document, credentials: removeCatalogValue( document.credentials, (value) => value.connectionId, connectionId, ), })), }); const remoteTokenStore = TokenStore.make({ get: (environmentId) => catalog.read.pipe( Effect.map((document) => Option.fromUndefinedOr( document.remoteDpopTokens.find((token) => token.environmentId === environmentId), ), ), ), put: (token) => catalog.update((document) => putRemoteDpopTokenInCatalog(document, token)), remove: (environmentId) => catalog.update((document) => ({ ...document, remoteDpopTokens: removeCatalogValue( document.remoteDpopTokens, (value) => value.environmentId, environmentId, ), })), }); return Context.make(ConnectionTargetStore, targetStore).pipe( Context.add(ConnectionRegistrationStore, registrationStore), Context.add(ProfileStore.ConnectionProfileStore, profileStore), Context.add(CredentialStore.ConnectionCredentialStore, credentialStore), Context.add(TokenStore.RemoteDpopAccessTokenStore, remoteTokenStore), ); }),);
import {
ConnectionPersistenceError,
ConnectionRegistrationStore,
ConnectionTargetStore,
putRemoteDpopTokenInCatalog,
registerConnectionInCatalog,
removeConnectionFromCatalog,
removeCatalogValue,
replaceCatalogValue,
} from "@t3tools/client-runtime/platform";
import { TokenStore } from "@t3tools/client-runtime/authorization";
import {
ConnectionTransientError,
CredentialStore,
ProfileStore,
} from "@t3tools/client-runtime/connection";
import * as Context from "effect/Context";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import * as Option from "effect/Option";
import * as CatalogStore from "./catalog-store";
function targetPersistenceError(
operation: "list-targets" | "register-connection" | "remove-connection",
error: ConnectionTransientError,
) {
return new ConnectionPersistenceError({
operation,
message: error.message,
});
}
export const connectionStorageLayer = Layer.effectContext(
Effect.gen(function* () {
const catalog = yield* CatalogStore.make();
const targetStore = ConnectionTargetStore.of({
list: catalog.read.pipe(
Effect.map((document) => document.targets),
Effect.mapError((error) => targetPersistenceError("list-targets", error)),
),
});
const registrationStore = ConnectionRegistrationStore.of({
register: (registration) =>
catalog
.update((document) => registerConnectionInCatalog(document, registration))
.pipe(Effect.mapError((error) => targetPersistenceError("register-connection", error))),
remove: (target) =>
catalog
.update((document) => removeConnectionFromCatalog(document, target))
.pipe(Effect.mapError((error) => targetPersistenceError("remove-connection", error))),
});
const profileStore = ProfileStore.make({
get: (connectionId) =>
catalog.read.pipe(
Effect.map((document) =>
Option.fromUndefinedOr(
document.profiles.find((candidate) => candidate.connectionId === connectionId),
),
),
),
put: (profile) =>
catalog.update((document) => ({
...document,
profiles: replaceCatalogValue(document.profiles, (value) => value.connectionId, profile),
})),
remove: (connectionId) =>
catalog.update((document) => ({
...document,
profiles: removeCatalogValue(
document.profiles,
(value) => value.connectionId,
connectionId,
),
})),
});
const credentialStore = CredentialStore.make({
get: (connectionId) =>
catalog.read.pipe(
Effect.map((document) =>
Option.fromUndefinedOr(
document.credentials.find((entry) => entry.connectionId === connectionId)?.credential,
),
),
),
put: (connectionId, credential) =>
catalog.update((document) => ({
...document,
credentials: replaceCatalogValue(document.credentials, (value) => value.connectionId, {
connectionId,
credential,
}),
})),
remove: (connectionId) =>
catalog.update((document) => ({
...document,
credentials: removeCatalogValue(
document.credentials,
(value) => value.connectionId,
connectionId,
),
})),
});
const remoteTokenStore = TokenStore.make({
get: (environmentId) =>
catalog.read.pipe(
Effect.map((document) =>
Option.fromUndefinedOr(
document.remoteDpopTokens.find((token) => token.environmentId === environmentId),
),
),
),
put: (token) => catalog.update((document) => putRemoteDpopTokenInCatalog(document, token)),
remove: (environmentId) =>
catalog.update((document) => ({
...document,
remoteDpopTokens: removeCatalogValue(
document.remoteDpopTokens,
(value) => value.environmentId,
environmentId,
),
})),
});
return Context.make(ConnectionTargetStore, targetStore).pipe(
Context.add(ConnectionRegistrationStore, registrationStore),
Context.add(ProfileStore.ConnectionProfileStore, profileStore),
Context.add(CredentialStore.ConnectionCredentialStore, credentialStore),
Context.add(TokenStore.RemoteDpopAccessTokenStore, remoteTokenStore),
);
}),
);