From e967853de4ca1b99d38edd8e85b0294fd905ef77 Mon Sep 17 00:00:00 2001 From: Chris Wilkinson Date: Fri, 20 Sep 2024 10:16:52 +0100 Subject: [PATCH] Get ready to use existing data loaders in Effect Refs #1941, #1834 --- src/Context.ts | 5 ++++- src/DeprecatedServices.ts | 12 ++++++++++-- src/ExpressServer.ts | 5 +++-- src/Program.ts | 4 +++- src/app.ts | 27 +++++++++++++-------------- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/Context.ts b/src/Context.ts index 10b9f362d..40d06b394 100644 --- a/src/Context.ts +++ b/src/Context.ts @@ -5,6 +5,7 @@ import type { LoggerEnv } from 'logger-fp-ts' import type { ConfigEnv } from './app.js' import type { EnvVars } from './env.js' import type { EventStore as EventStoreService } from './EventStore.js' +import type { SleepEnv } from './fetch.js' import type { SupportedLocale } from './locales/index.js' import type { User } from './user.js' @@ -12,9 +13,11 @@ export class DeprecatedEnvVars extends Context.Tag('DeprecatedEnvVars')() {} +export class DeprecatedSleepEnv extends Context.Tag('DeprecatedSleepEnv')() {} + export class Express extends Context.Tag('Express')() {} -export class ExpressConfig extends Context.Tag('ExpressConfig')>() {} +export class ExpressConfig extends Context.Tag('ExpressConfig')>() {} export class Locale extends Context.Tag('Locale')() {} diff --git a/src/DeprecatedServices.ts b/src/DeprecatedServices.ts index 1afd29b10..244cd8a22 100644 --- a/src/DeprecatedServices.ts +++ b/src/DeprecatedServices.ts @@ -1,10 +1,10 @@ import { SystemClock } from 'clock-ts' -import { Array, Effect, HashMap, Inspectable, Logger, Match } from 'effect' +import { Array, Effect, HashMap, Inspectable, Logger, Match, Runtime } from 'effect' import * as C from 'fp-ts/lib/Console.js' import { pipe } from 'fp-ts/lib/function.js' import type * as J from 'fp-ts/lib/Json.js' import * as L from 'logger-fp-ts' -import { DeprecatedEnvVars, DeprecatedLoggerEnv } from './Context.js' +import { DeprecatedEnvVars, DeprecatedLoggerEnv, type DeprecatedSleepEnv } from './Context.js' import { decodeEnv } from './env.js' export const makeDeprecatedEnvVars = decodeEnv(process)() @@ -17,6 +17,14 @@ export const makeDeprecatedLoggerEnv = Effect.gen(function* () { } }) +export const makeDeprecatedSleepEnv = Effect.gen(function* () { + const runtime = yield* Effect.runtime() + + return { + sleep: (duration: number) => Runtime.runPromise(runtime)(Effect.sleep(`${duration} millis`)), + } satisfies typeof DeprecatedSleepEnv.Service +}) + export const DeprecatedLogger = Effect.gen(function* () { const loggerEnv = yield* DeprecatedLoggerEnv diff --git a/src/ExpressServer.ts b/src/ExpressServer.ts index 4aad37dbb..309719c52 100644 --- a/src/ExpressServer.ts +++ b/src/ExpressServer.ts @@ -5,13 +5,14 @@ import Keyv from 'keyv' import nodemailer from 'nodemailer' import { P, match } from 'ts-pattern' import { app, type ConfigEnv } from './app.js' -import { DeprecatedEnvVars, DeprecatedLoggerEnv, ExpressConfig, Redis } from './Context.js' +import { DeprecatedEnvVars, DeprecatedLoggerEnv, DeprecatedSleepEnv, ExpressConfig, Redis } from './Context.js' export const expressServer = Effect.gen(function* () { const config = yield* ExpressConfig const fetch = yield* FetchHttpClient.Fetch + const sleep = yield* DeprecatedSleepEnv - return app({ fetch, ...config } as unknown as ConfigEnv) + return app({ fetch, ...sleep, ...config } as unknown as ConfigEnv) }) export const ExpressConfigLive = Effect.gen(function* () { diff --git a/src/Program.ts b/src/Program.ts index 3cf6fa2c4..4c9a52d8c 100644 --- a/src/Program.ts +++ b/src/Program.ts @@ -11,7 +11,8 @@ import cspBuilder from 'content-security-policy-builder' import cookieSignature from 'cookie-signature' import { Config, Effect, Layer, Option, pipe } from 'effect' import * as Uuid from 'uuid-ts' -import { DeprecatedLoggerEnv, Express, ExpressConfig, Locale, LoggedInUser } from './Context.js' +import { DeprecatedLoggerEnv, DeprecatedSleepEnv, Express, ExpressConfig, Locale, LoggedInUser } from './Context.js' +import { makeDeprecatedSleepEnv } from './DeprecatedServices.js' import { ExpressHttpApp } from './ExpressHttpApp.js' import { expressServer } from './ExpressServer.js' import { collapseRequests, logFetch } from './fetch.js' @@ -136,4 +137,5 @@ export const Program = pipe( Layer.provide(Layer.effect(Express, expressServer)), Layer.provide(Layer.effect(TemplatePage.TemplatePage, TemplatePage.make)), Layer.provide(setUpFetch), + Layer.provide(Layer.effect(DeprecatedSleepEnv, makeDeprecatedSleepEnv)), ) diff --git a/src/app.ts b/src/app.ts index 19e7410b0..0f45aa739 100644 --- a/src/app.ts +++ b/src/app.ts @@ -18,7 +18,6 @@ import { match, P as p } from 'ts-pattern' import * as uuid from 'uuid-ts' import { type RouterEnv, routes } from './app-router.js' import type { Email } from './email.js' -import type { SleepEnv } from './fetch.js' import { doesPreprintExist, getPreprint, getPreprintTitle, resolvePreprintId } from './get-preprint.js' import { pageNotFound } from './http-error.js' import { getUserOnboarding } from './keyv.js' @@ -43,7 +42,6 @@ export type ConfigEnv = Omit< | 'getPreprintIdFromUuid' | 'getProfileIdFromUuid' | 'sendEmail' - | 'sleep' > & (MailjetApiEnv | NodemailerEnv) & { allowSiteCrawlers: boolean @@ -222,7 +220,7 @@ export const app = (config: ConfigEnv) => .use((req, res, next) => { return pipe( appMiddleware, - R.local((env: ConfigEnv & SleepEnv): RouterEnv & LegacyEnv => ({ + R.local((env: ConfigEnv): RouterEnv & LegacyEnv => ({ ...env, doesPreprintExist: withEnv(doesPreprintExist, env), generateUuid: uuid.v4(), @@ -236,17 +234,18 @@ export const app = (config: ConfigEnv) => resolvePreprintId: withEnv(resolvePreprintId, env), sendEmail: withEnv(sendEmail, env), })), - R.local((appEnv: ConfigEnv): ConfigEnv & SleepEnv => ({ - ...appEnv, - logger: pipe( - appEnv.logger, - l.contramap(entry => ({ - ...entry, - payload: { requestId: req.header('Fly-Request-Id') ?? null, ...entry.payload }, - })), - ), - sleep: duration => new Promise(resolve => setTimeout(resolve, duration)), - })), + R.local( + (appEnv: ConfigEnv): ConfigEnv => ({ + ...appEnv, + logger: pipe( + appEnv.logger, + l.contramap(entry => ({ + ...entry, + payload: { requestId: req.header('Fly-Request-Id') ?? null, ...entry.payload }, + })), + ), + }), + ), apply(config), toRequestHandler, )(req, res, next)