ff-serv 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,32 @@
1
+ import * as effect_Scope from 'effect/Scope';
2
+ import { Effect } from 'effect';
3
+ import { Cause } from 'effect/Cause';
4
+
5
+ type AnyResponse = Response | Promise<Response>;
6
+ type HandlerResult = {
7
+ matched: true;
8
+ response: AnyResponse;
9
+ } | {
10
+ matched: false;
11
+ response: undefined;
12
+ };
13
+ declare class Handler<NAME extends string, R> {
14
+ readonly _tag: NAME;
15
+ readonly handle: (opt: {
16
+ url: URL;
17
+ request: Request;
18
+ }) => Effect.Effect<HandlerResult, unknown, R>;
19
+ constructor(_tag: NAME, handle: (opt: {
20
+ url: URL;
21
+ request: Request;
22
+ }) => Effect.Effect<HandlerResult, unknown, R>);
23
+ }
24
+ type ExtractRequirements<T> = T extends Handler<string, infer R> ? R : never;
25
+ declare const createFetchHandler: <const HANDLERS extends [Handler<string, unknown>, ...Array<Handler<string, unknown>>], R = ExtractRequirements<HANDLERS[number]>>(handlers: HANDLERS, opts?: {
26
+ debug?: boolean;
27
+ onError?: (ctx: {
28
+ error: Cause<unknown>;
29
+ }) => Effect.Effect<unknown, unknown>;
30
+ }) => Effect.Effect<(request: Request) => Promise<Response>, never, R | effect_Scope.Scope>;
31
+
32
+ export { type AnyResponse as A, Handler as H, createFetchHandler as c };
package/dist/index.cjs CHANGED
@@ -37,6 +37,9 @@ __export(index_exports, {
37
37
  });
38
38
  module.exports = __toCommonJS(index_exports);
39
39
 
40
+ // src/http/basic.ts
41
+ var import_effect3 = require("effect");
42
+
40
43
  // src/http/fetch-handler.ts
41
44
  var import_effect2 = require("effect");
42
45
  var import_nanoid = require("nanoid");
@@ -242,16 +245,12 @@ var Logger;
242
245
  })(Logger || (Logger = {}));
243
246
 
244
247
  // src/http/fetch-handler.ts
245
- function basicHandler(path, handler) {
246
- return {
247
- _tag: "basicHandler",
248
- handle: ({ url, request }) => {
249
- const matched = typeof path === "function" ? path(url) : path === url.pathname;
250
- if (!matched) return { matched: false, response: void 0 };
251
- return { matched: true, response: handler(request) };
252
- }
253
- };
254
- }
248
+ var Handler = class {
249
+ constructor(_tag, handle) {
250
+ this._tag = _tag;
251
+ this.handle = handle;
252
+ }
253
+ };
255
254
  var createFetchHandler = (handlers, opts) => import_effect2.Effect.gen(function* () {
256
255
  const runFork = yield* import_effect2.FiberSet.makeRuntimePromise();
257
256
  return async (request) => {
@@ -262,10 +261,36 @@ var createFetchHandler = (handlers, opts) => import_effect2.Effect.gen(function*
262
261
  { request: { pathname: urlObj.pathname } },
263
262
  "Request started"
264
263
  );
265
- for (const handler of Array.isArray(handlers) ? handlers : [handlers]) {
264
+ for (const handler of handlers) {
266
265
  if (!handler) continue;
267
- const maybeResult = handler.handle({ url: urlObj, request });
268
- const result = maybeResult instanceof Promise ? yield* import_effect2.Effect.tryPromise(() => maybeResult) : maybeResult;
266
+ const result = yield* handler.handle({ url: urlObj, request }).pipe(
267
+ import_effect2.Effect.flatMap(
268
+ ({ matched, response }) => import_effect2.Effect.gen(function* () {
269
+ if (matched) {
270
+ return {
271
+ matched: true,
272
+ response: response instanceof Promise ? yield* import_effect2.Effect.tryPromise(() => response) : response
273
+ };
274
+ }
275
+ return { matched: false, response: void 0 };
276
+ })
277
+ ),
278
+ import_effect2.Effect.catchAllCause(
279
+ (error) => import_effect2.Effect.gen(function* () {
280
+ yield* Logger.error(
281
+ { error },
282
+ `Unhandled exception in HTTP handler '${handler._tag}'`
283
+ );
284
+ if (opts?.onError) yield* opts.onError({ error });
285
+ return {
286
+ matched: true,
287
+ response: new Response("Internal Server Error", {
288
+ status: 500
289
+ })
290
+ };
291
+ })
292
+ )
293
+ );
269
294
  if (opts?.debug)
270
295
  yield* Logger.debug(
271
296
  { handler: handler._tag, request, result },
@@ -276,23 +301,9 @@ var createFetchHandler = (handlers, opts) => import_effect2.Effect.gen(function*
276
301
  }
277
302
  return new Response("Not Found", { status: 404 });
278
303
  }).pipe(
279
- import_effect2.Effect.flatMap(
280
- (response) => response instanceof Promise ? import_effect2.Effect.tryPromise(() => response) : import_effect2.Effect.succeed(response)
281
- ),
282
304
  import_effect2.Effect.tap(
283
305
  (response) => response.ok ? Logger.info(`Request completed with status ${response.status}`) : Logger.warn(`Request completed with status ${response.status}`)
284
306
  ),
285
- import_effect2.Effect.catchAll(
286
- (error) => import_effect2.Effect.gen(function* () {
287
- yield* Logger.error(
288
- { error },
289
- "Unhandled exception in HTTP handler"
290
- );
291
- return new Response("Internal Server Error", {
292
- status: 500
293
- });
294
- })
295
- ),
296
307
  import_effect2.Effect.withSpan("http"),
297
308
  import_effect2.Effect.annotateLogs({ requestId }),
298
309
  import_effect2.Effect.scoped
@@ -301,10 +312,40 @@ var createFetchHandler = (handlers, opts) => import_effect2.Effect.gen(function*
301
312
  };
302
313
  });
303
314
 
315
+ // src/http/basic.ts
316
+ var Path;
317
+ ((Path2) => {
318
+ function matched(path, url) {
319
+ return typeof path === "function" ? path(url) : path === url.pathname;
320
+ }
321
+ Path2.matched = matched;
322
+ })(Path || (Path = {}));
323
+ var Fn;
324
+ ((Fn2) => {
325
+ function exec(fn, ...[request]) {
326
+ const response = fn(request);
327
+ if (!import_effect3.Effect.isEffect(response)) return import_effect3.Effect.succeed(response);
328
+ return response;
329
+ }
330
+ Fn2.exec = exec;
331
+ })(Fn || (Fn = {}));
332
+ function basicHandler(path, fn) {
333
+ return new Handler("basicHandler", ({ url, request }) => {
334
+ if (!Path.matched(path, url))
335
+ return import_effect3.Effect.succeed({ matched: false, response: void 0 });
336
+ return import_effect3.Effect.gen(function* () {
337
+ return {
338
+ matched: true,
339
+ response: yield* Fn.exec(fn, request)
340
+ };
341
+ });
342
+ });
343
+ }
344
+
304
345
  // src/port.ts
305
- var import_effect3 = require("effect");
346
+ var import_effect4 = require("effect");
306
347
  var GetPort = __toESM(require("get-port"), 1);
307
- var getPort = (options) => import_effect3.Effect.tryPromise(() => GetPort.default(options));
348
+ var getPort = (options) => import_effect4.Effect.tryPromise(() => GetPort.default(options));
308
349
  // Annotate the CommonJS export names for ESM import in node:
309
350
  0 && (module.exports = {
310
351
  Logger,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/http/fetch-handler.ts","../src/logger.ts","../src/port.ts"],"sourcesContent":["export { basicHandler, createFetchHandler } from './http/index.js';\nexport { Logger } from './logger.js';\nexport { getPort } from './port.js';","import { Effect, FiberSet } from 'effect';\nimport { nanoid } from 'nanoid';\nimport { Logger } from '../logger.js';\n\nexport type HandlerResult =\n\t| {\n\t\t\tmatched: true;\n\t\t\tresponse: Response | Promise<Response>;\n\t }\n\t| {\n\t\t\tmatched: false;\n\t\t\tresponse: undefined;\n\t };\n\nexport type Handler<T extends string = string> = {\n\t_tag: T;\n\thandle: (opt: {\n\t\turl: URL;\n\t\trequest: Request;\n\t}) => HandlerResult | Promise<HandlerResult>;\n};\n\nexport function basicHandler(\n\tpath: string | ((url: URL) => boolean),\n\thandler: (request: Request) => Response | Promise<Response>,\n): Handler<'basicHandler'> {\n\treturn {\n\t\t_tag: 'basicHandler',\n\t\thandle: ({ url, request }) => {\n\t\t\tconst matched =\n\t\t\t\ttypeof path === 'function' ? path(url) : path === url.pathname;\n\t\t\tif (!matched) return { matched: false, response: undefined };\n\n\t\t\treturn { matched: true, response: handler(request) };\n\t\t},\n\t};\n}\n\nexport const createFetchHandler = (\n\thandlers?: Handler | [Handler, ...Array<Handler>],\n\topts?: {\n\t\tdebug?: boolean;\n\t},\n) =>\n\tEffect.gen(function* () {\n\t\tconst runFork = yield* FiberSet.makeRuntimePromise();\n\t\treturn async (request: Request) => {\n\t\t\tconst urlObj = new URL(request.url);\n\t\t\tconst requestId = nanoid(6);\n\n\t\t\tconst effect = Effect.gen(function* () {\n\t\t\t\tyield* Logger.info(\n\t\t\t\t\t{ request: { pathname: urlObj.pathname } },\n\t\t\t\t\t'Request started',\n\t\t\t\t);\n\n\t\t\t\tfor (const handler of Array.isArray(handlers) ? handlers : [handlers]) {\n\t\t\t\t\tif (!handler) continue;\n\n\t\t\t\t\tconst maybeResult = handler.handle({ url: urlObj, request });\n\t\t\t\t\tconst result =\n\t\t\t\t\t\tmaybeResult instanceof Promise\n\t\t\t\t\t\t\t? yield* Effect.tryPromise(() => maybeResult)\n\t\t\t\t\t\t\t: maybeResult;\n\n\t\t\t\t\tif (opts?.debug)\n\t\t\t\t\t\tyield* Logger.debug(\n\t\t\t\t\t\t\t{ handler: handler._tag, request, result },\n\t\t\t\t\t\t\t'Processed handler',\n\t\t\t\t\t\t);\n\n\t\t\t\t\tif (!result.matched) continue;\n\t\t\t\t\treturn result.response;\n\t\t\t\t}\n\n\t\t\t\treturn new Response('Not Found', { status: 404 });\n\t\t\t}).pipe(\n\t\t\t\tEffect.flatMap((response) =>\n\t\t\t\t\tresponse instanceof Promise\n\t\t\t\t\t\t? Effect.tryPromise(() => response)\n\t\t\t\t\t\t: Effect.succeed(response),\n\t\t\t\t),\n\t\t\t\tEffect.tap((response) =>\n\t\t\t\t\tresponse.ok\n\t\t\t\t\t\t? Logger.info(`Request completed with status ${response.status}`)\n\t\t\t\t\t\t: Logger.warn(`Request completed with status ${response.status}`),\n\t\t\t\t),\n\t\t\t\tEffect.catchAll((error) =>\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tyield* Logger.error(\n\t\t\t\t\t\t\t{ error },\n\t\t\t\t\t\t\t'Unhandled exception in HTTP handler',\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn new Response('Internal Server Error', {\n\t\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\t});\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\tEffect.withSpan('http'),\n\t\t\t\tEffect.annotateLogs({ requestId }),\n\t\t\t\tEffect.scoped,\n\t\t\t);\n\n\t\t\treturn runFork(effect);\n\t\t};\n\t});","import {\n\tConfig,\n\tContext,\n\tEffect,\n\tLogger as EffectLogger,\n\tHashMap,\n\tLayer,\n\tLogLevel,\n\tManagedRuntime,\n\tOption,\n} from 'effect';\nimport pino from 'pino';\n\n// Pino Instance\n\nnamespace LoggerType {\n\texport function fromPino(x: pino.Logger<never, boolean>) {\n\t\treturn {\n\t\t\tinfo: x.info.bind(x),\n\t\t\terror: x.error.bind(x),\n\t\t\twarn: x.warn.bind(x),\n\t\t\tdebug: x.debug.bind(x),\n\t\t\tchild: (...params: Parameters<typeof x.child>) => {\n\t\t\t\treturn fromPino(\n\t\t\t\t\tx.child(...params) as unknown as pino.Logger<never, boolean>,\n\t\t\t\t);\n\t\t\t},\n\t\t\tflush: x.flush.bind(x),\n\t\t\t_pino: x,\n\t\t};\n\t}\n\n\texport type CreateParams = {\n\t\tstream?: pino.DestinationStream;\n\t};\n\n\texport function create(params?: CreateParams) {\n\t\tconst logger = pino(\n\t\t\t{\n\t\t\t\tlevel: 'trace', // Level is managed by Effect, so we set the lowest here\n\t\t\t\tserializers: {\n\t\t\t\t\terror: pino.stdSerializers.errWithCause,\n\t\t\t\t\terr: pino.stdSerializers.errWithCause,\n\t\t\t\t},\n\t\t\t\tformatters: {\n\t\t\t\t\tlevel: (label) => {\n\t\t\t\t\t\treturn { level: label };\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tparams?.stream,\n\t\t);\n\t\treturn fromPino(logger);\n\t}\n\n\texport type Type = ReturnType<typeof LoggerType.create>;\n\n\texport function is(x: object): x is Type {\n\t\treturn '_pino' in x;\n\t}\n}\ntype LoggerType = LoggerType.Type;\n\n// The Gist\n\nconst createInstance = (params?: LoggerType.CreateParams) =>\n\tEffect.gen(function* () {\n\t\tconst isDev = Option.getOrNull(\n\t\t\tyield* Config.boolean('DEV').pipe(Config.option),\n\t\t);\n\t\tconst logFile = Option.getOrNull(\n\t\t\tyield* Config.boolean('LOGGER_LOGFILE').pipe(Config.option),\n\t\t);\n\n\t\treturn LoggerType.create({\n\t\t\t...params,\n\t\t\t...(isDev && {\n\t\t\t\tstream: logFile\n\t\t\t\t\t? pino.transport({\n\t\t\t\t\t\t\ttarget: 'pino/file',\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tdestination: './logs/server.log',\n\t\t\t\t\t\t\t\tmkdir: true,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t: pino.transport({\n\t\t\t\t\t\t\ttarget: 'pino-pretty',\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tignore: 'pid,hostname',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t}),\n\t\t});\n\t});\n\n// Pino Context and Effect Logger integration\n\ntype LogParams = [obj: unknown, msg?: string];\nfunction extractParams(...[obj, msg]: LogParams) {\n\tif (typeof obj === 'string') {\n\t\treturn { message: obj };\n\t}\n\treturn { message: msg, attributes: obj as Record<string, any> };\n}\n\n/** A simple helper for calling pino log functions */\nfunction callPino(\n\t{\n\t\tannotations,\n\t\tmessage,\n\t}: Pick<EffectLogger.Logger.Options<unknown>, 'annotations' | 'message'>,\n\tcall: (...params: [obj: unknown, msg?: string]) => void,\n) {\n\tconst entries = HashMap.toEntries(annotations);\n\tif (entries.length > 0) {\n\t\treturn call(Object.fromEntries(entries), String(message));\n\t}\n\n\treturn call(String(message));\n}\n\nnamespace PinoCtx {\n\tconst tag = 'ff-serv/Pino';\n\texport type Type = ReturnType<typeof create>;\n\n\texport function is(obj: unknown): obj is Type {\n\t\treturn (\n\t\t\ttypeof obj === 'object' &&\n\t\t\tobj != null &&\n\t\t\t'_tag' in obj &&\n\t\t\tobj._tag === tag\n\t\t);\n\t}\n\n\texport function create(pino: LoggerType) {\n\t\treturn {\n\t\t\t_tag: tag,\n\t\t\tpino,\n\t\t\teffectLogger: EffectLogger.make(({ logLevel, ...input }) => {\n\t\t\t\tswitch (logLevel) {\n\t\t\t\t\tcase LogLevel.Info:\n\t\t\t\t\t\treturn callPino(input, pino.info);\n\t\t\t\t\tcase LogLevel.Debug:\n\t\t\t\t\t\treturn callPino(input, pino.debug);\n\t\t\t\t\tcase LogLevel.Warning:\n\t\t\t\t\t\treturn callPino(input, pino.warn);\n\t\t\t\t\tcase LogLevel.Error:\n\t\t\t\t\tcase LogLevel.Fatal:\n\t\t\t\t\t\treturn callPino(input, pino.error);\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn callPino(input, pino.info);\n\t\t\t\t}\n\t\t\t}),\n\t\t};\n\t}\n}\ntype PinoCtx = PinoCtx.Type;\n\nclass Pino extends Context.Tag('ff-serv/Pino')<Pino, PinoCtx>() {}\n\n// Facade\n\nexport namespace Logger {\n\texport const layer = (opts?: Parameters<typeof createInstance>[0]) =>\n\t\tEffectLogger.replaceEffect(\n\t\t\tEffectLogger.defaultLogger,\n\t\t\tEffect.gen(function* () {\n\t\t\t\treturn (yield* Pino).effectLogger;\n\t\t\t}),\n\t\t).pipe(\n\t\t\tLayer.provideMerge(\n\t\t\t\tLayer.effect(\n\t\t\t\t\tPino,\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\treturn PinoCtx.create(yield* createInstance(opts));\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\n\t//\n\n\texport const sync = () =>\n\t\tEffect.gen(function* () {\n\t\t\tconst pino = yield* Pino;\n\t\t\tconst runtime = ManagedRuntime.make(\n\t\t\t\tEffectLogger.replace(EffectLogger.defaultLogger, pino.effectLogger),\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tinfo: (...params: Parameters<typeof Logger.info>) =>\n\t\t\t\t\tLogger.info(...params).pipe((e) => runtime.runSync(e)),\n\t\t\t\tdebug: (...params: Parameters<typeof Logger.debug>) =>\n\t\t\t\t\tLogger.debug(...params).pipe((e) => runtime.runSync(e)),\n\t\t\t\twarn: (...params: Parameters<typeof Logger.warn>) =>\n\t\t\t\t\tLogger.warn(...params).pipe((e) => runtime.runSync(e)),\n\t\t\t\terror: (...params: Parameters<typeof Logger.error>) =>\n\t\t\t\t\tLogger.error(...params).pipe((e) => runtime.runSync(e)),\n\t\t\t};\n\t\t});\n\n\t/** @deprecated — will be renamed to `sync` */\n\texport const get = () => Logger.sync();\n\n\texport const replace =\n\t\t(logger: LoggerType | pino.Logger) =>\n\t\t<A, E, R>(e: Effect.Effect<A, E, R>) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst oldPinoCtx = yield* Pino;\n\t\t\t\tconst pino = LoggerType.is(logger)\n\t\t\t\t\t? logger\n\t\t\t\t\t: LoggerType.fromPino(logger);\n\t\t\t\tconst pinoCtx = PinoCtx.create(pino);\n\n\t\t\t\treturn yield* Effect.provide(\n\t\t\t\t\te,\n\t\t\t\t\tLayer.mergeAll(\n\t\t\t\t\t\tEffectLogger.replace(oldPinoCtx.effectLogger, pinoCtx.effectLogger),\n\t\t\t\t\t\tLayer.succeed(Pino, pinoCtx),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t});\n\n\texport const replaceChild =\n\t\t(...params: Parameters<LoggerType['child']>) =>\n\t\t<A, E, R>(e: Effect.Effect<A, E, R>) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst oldPinoCtx = yield* Pino;\n\t\t\t\tconst pino = oldPinoCtx.pino.child(...params);\n\t\t\t\tconst pinoCtx = PinoCtx.create(pino);\n\n\t\t\t\treturn yield* Effect.provide(\n\t\t\t\t\tEffect.provide(\n\t\t\t\t\t\te,\n\t\t\t\t\t\tEffectLogger.replace(oldPinoCtx.effectLogger, pinoCtx.effectLogger),\n\t\t\t\t\t),\n\t\t\t\t\tLayer.succeed(Pino, pinoCtx),\n\t\t\t\t);\n\t\t\t});\n\n\t// --\n\n\texport const info = (...params: LogParams) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst { message, attributes } = extractParams(...params);\n\t\t\tyield* Effect.logInfo(message).pipe(\n\t\t\t\tattributes ? Effect.annotateLogs(attributes) : (e) => e,\n\t\t\t);\n\t\t});\n\n\texport const debug = (...params: LogParams) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst { message, attributes } = extractParams(...params);\n\t\t\tyield* Effect.logDebug(message).pipe(\n\t\t\t\tattributes ? Effect.annotateLogs(attributes) : (e) => e,\n\t\t\t);\n\t\t});\n\n\texport const warn = (...params: LogParams) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst { message, attributes } = extractParams(...params);\n\t\t\tyield* Effect.logWarning(message).pipe(\n\t\t\t\tattributes ? Effect.annotateLogs(attributes) : (e) => e,\n\t\t\t);\n\t\t});\n\n\texport const error = (...params: LogParams) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst { message, attributes } = extractParams(...params);\n\t\t\tyield* Effect.logError(message).pipe(\n\t\t\t\tattributes ? Effect.annotateLogs(attributes) : (e) => e,\n\t\t\t);\n\t\t});\n\n\t/** @deprecated */\n\texport const flush = (..._params: Parameters<LoggerType['flush']>) =>\n\t\tEffect.void;\n}\n","import { Effect } from 'effect';\nimport * as GetPort from 'get-port';\n\nexport const getPort = (options?: GetPort.Options) =>\n\tEffect.tryPromise(() => GetPort.default(options));\n"],"mappings":"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","names":["import_effect","LoggerType","pino","PinoCtx","EffectLogger","Logger","import_effect"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/http/basic.ts","../src/http/fetch-handler.ts","../src/logger.ts","../src/port.ts"],"sourcesContent":["export * from './http/index.js';\nexport { Logger } from './logger.js';\nexport { getPort } from './port.js';\n","import { Effect } from 'effect';\nimport { type AnyResponse, Handler } from './fetch-handler.js';\n\nexport namespace Path {\n\texport type Type = `/${string}` | ((url: URL) => boolean);\n\texport function matched(path: Type, url: URL) {\n\t\treturn typeof path === 'function' ? path(url) : path === url.pathname;\n\t}\n}\n\nexport namespace Fn {\n\ttype Input = [request: Request];\n\n\ttype OutputSync = AnyResponse;\n\ttype OutputEffect<R> = Effect.Effect<AnyResponse, unknown, R>;\n\n\texport type FnSync = (...input: Input) => OutputSync;\n\texport type FnEffect<R> = (...input: Input) => OutputEffect<R>;\n\texport type FnAny<R> = (...input: Input) => OutputSync | OutputEffect<R>;\n\n\texport function exec<R>(fn: FnAny<R>, ...[request]: Input) {\n\t\tconst response = fn(request);\n\t\tif (!Effect.isEffect(response)) return Effect.succeed(response);\n\t\treturn response;\n\t}\n}\n\nexport function basicHandler(\n\tpath: Path.Type,\n\tfn: Fn.FnSync,\n): Handler<'basicHandler', never>;\nexport function basicHandler<R>(\n\tpath: Path.Type,\n\tfn: Fn.FnEffect<R>,\n): Handler<'basicHandler', R>;\nexport function basicHandler<R>(path: Path.Type, fn: Fn.FnAny<R>) {\n\treturn new Handler('basicHandler', ({ url, request }) => {\n\t\tif (!Path.matched(path, url))\n\t\t\treturn Effect.succeed({ matched: false, response: undefined });\n\n\t\treturn Effect.gen(function* () {\n\t\t\treturn {\n\t\t\t\tmatched: true,\n\t\t\t\tresponse: yield* Fn.exec(fn, request),\n\t\t\t};\n\t\t});\n\t});\n}\n","import { Effect, FiberSet } from 'effect';\nimport type { Cause } from 'effect/Cause';\nimport { nanoid } from 'nanoid';\nimport { Logger } from '../logger.js';\n\n// #region Handler\n\nexport type AnyResponse = Response | Promise<Response>;\n\nexport type HandlerResult =\n\t| {\n\t\t\tmatched: true;\n\t\t\tresponse: AnyResponse;\n\t }\n\t| {\n\t\t\tmatched: false;\n\t\t\tresponse: undefined;\n\t };\n\nexport class Handler<NAME extends string, R> {\n\tconstructor(\n\t\treadonly _tag: NAME,\n\t\treadonly handle: (opt: {\n\t\t\turl: URL;\n\t\t\trequest: Request;\n\t\t}) => Effect.Effect<HandlerResult, unknown, R>,\n\t) {}\n}\n\n// #endregion\n\ntype ExtractRequirements<T> = T extends Handler<string, infer R> ? R : never;\n\nexport const createFetchHandler = <\n\tconst HANDLERS extends [\n\t\tHandler<string, unknown>,\n\t\t...Array<Handler<string, unknown>>,\n\t],\n\tR = ExtractRequirements<HANDLERS[number]>,\n>(\n\thandlers: HANDLERS,\n\topts?: {\n\t\tdebug?: boolean;\n\t\tonError?: (ctx: {\n\t\t\terror: Cause<unknown>;\n\t\t}) => Effect.Effect<unknown, unknown>;\n\t},\n) =>\n\tEffect.gen(function* () {\n\t\tconst runFork = yield* FiberSet.makeRuntimePromise<R>();\n\t\treturn async (request: Request) => {\n\t\t\tconst urlObj = new URL(request.url);\n\t\t\tconst requestId = nanoid(6);\n\n\t\t\tconst effect = Effect.gen(function* () {\n\t\t\t\tyield* Logger.info(\n\t\t\t\t\t{ request: { pathname: urlObj.pathname } },\n\t\t\t\t\t'Request started',\n\t\t\t\t);\n\n\t\t\t\tfor (const handler of handlers) {\n\t\t\t\t\tif (!handler) continue;\n\n\t\t\t\t\tconst result = yield* handler.handle({ url: urlObj, request }).pipe(\n\t\t\t\t\t\tEffect.flatMap(({ matched, response }) =>\n\t\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\t\tif (matched) {\n\t\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\t\tmatched: true,\n\t\t\t\t\t\t\t\t\t\tresponse:\n\t\t\t\t\t\t\t\t\t\t\tresponse instanceof Promise\n\t\t\t\t\t\t\t\t\t\t\t\t? yield* Effect.tryPromise(() => response)\n\t\t\t\t\t\t\t\t\t\t\t\t: response,\n\t\t\t\t\t\t\t\t\t} as const;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn { matched: false, response: undefined } as const;\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tEffect.catchAllCause((error) =>\n\t\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\t\tyield* Logger.error(\n\t\t\t\t\t\t\t\t\t{ error },\n\t\t\t\t\t\t\t\t\t`Unhandled exception in HTTP handler '${handler._tag}'`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tif (opts?.onError) yield* opts.onError({ error });\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tmatched: true,\n\t\t\t\t\t\t\t\t\tresponse: new Response('Internal Server Error', {\n\t\t\t\t\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t} as const;\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\n\t\t\t\t\tif (opts?.debug)\n\t\t\t\t\t\tyield* Logger.debug(\n\t\t\t\t\t\t\t{ handler: handler._tag, request, result },\n\t\t\t\t\t\t\t'Processed handler',\n\t\t\t\t\t\t);\n\n\t\t\t\t\tif (!result.matched) continue;\n\t\t\t\t\treturn result.response;\n\t\t\t\t}\n\n\t\t\t\treturn new Response('Not Found', { status: 404 });\n\t\t\t}).pipe(\n\t\t\t\tEffect.tap((response) =>\n\t\t\t\t\tresponse.ok\n\t\t\t\t\t\t? Logger.info(`Request completed with status ${response.status}`)\n\t\t\t\t\t\t: Logger.warn(`Request completed with status ${response.status}`),\n\t\t\t\t),\n\t\t\t\tEffect.withSpan('http'),\n\t\t\t\tEffect.annotateLogs({ requestId }),\n\t\t\t\tEffect.scoped,\n\t\t\t) as Effect.Effect<Response, never, R>;\n\n\t\t\treturn runFork(effect);\n\t\t};\n\t});\n","import {\n\tConfig,\n\tContext,\n\tEffect,\n\tLogger as EffectLogger,\n\tHashMap,\n\tLayer,\n\tLogLevel,\n\tManagedRuntime,\n\tOption,\n} from 'effect';\nimport pino from 'pino';\n\n// Pino Instance\n\nnamespace LoggerType {\n\texport function fromPino(x: pino.Logger<never, boolean>) {\n\t\treturn {\n\t\t\tinfo: x.info.bind(x),\n\t\t\terror: x.error.bind(x),\n\t\t\twarn: x.warn.bind(x),\n\t\t\tdebug: x.debug.bind(x),\n\t\t\tchild: (...params: Parameters<typeof x.child>) => {\n\t\t\t\treturn fromPino(\n\t\t\t\t\tx.child(...params) as unknown as pino.Logger<never, boolean>,\n\t\t\t\t);\n\t\t\t},\n\t\t\tflush: x.flush.bind(x),\n\t\t\t_pino: x,\n\t\t};\n\t}\n\n\texport type CreateParams = {\n\t\tstream?: pino.DestinationStream;\n\t};\n\n\texport function create(params?: CreateParams) {\n\t\tconst logger = pino(\n\t\t\t{\n\t\t\t\tlevel: 'trace', // Level is managed by Effect, so we set the lowest here\n\t\t\t\tserializers: {\n\t\t\t\t\terror: pino.stdSerializers.errWithCause,\n\t\t\t\t\terr: pino.stdSerializers.errWithCause,\n\t\t\t\t},\n\t\t\t\tformatters: {\n\t\t\t\t\tlevel: (label) => {\n\t\t\t\t\t\treturn { level: label };\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tparams?.stream,\n\t\t);\n\t\treturn fromPino(logger);\n\t}\n\n\texport type Type = ReturnType<typeof LoggerType.create>;\n\n\texport function is(x: object): x is Type {\n\t\treturn '_pino' in x;\n\t}\n}\ntype LoggerType = LoggerType.Type;\n\n// The Gist\n\nconst createInstance = (params?: LoggerType.CreateParams) =>\n\tEffect.gen(function* () {\n\t\tconst isDev = Option.getOrNull(\n\t\t\tyield* Config.boolean('DEV').pipe(Config.option),\n\t\t);\n\t\tconst logFile = Option.getOrNull(\n\t\t\tyield* Config.boolean('LOGGER_LOGFILE').pipe(Config.option),\n\t\t);\n\n\t\treturn LoggerType.create({\n\t\t\t...params,\n\t\t\t...(isDev && {\n\t\t\t\tstream: logFile\n\t\t\t\t\t? pino.transport({\n\t\t\t\t\t\t\ttarget: 'pino/file',\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tdestination: './logs/server.log',\n\t\t\t\t\t\t\t\tmkdir: true,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t: pino.transport({\n\t\t\t\t\t\t\ttarget: 'pino-pretty',\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tignore: 'pid,hostname',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t}),\n\t\t});\n\t});\n\n// Pino Context and Effect Logger integration\n\ntype LogParams = [obj: unknown, msg?: string];\nfunction extractParams(...[obj, msg]: LogParams) {\n\tif (typeof obj === 'string') {\n\t\treturn { message: obj };\n\t}\n\treturn { message: msg, attributes: obj as Record<string, any> };\n}\n\n/** A simple helper for calling pino log functions */\nfunction callPino(\n\t{\n\t\tannotations,\n\t\tmessage,\n\t}: Pick<EffectLogger.Logger.Options<unknown>, 'annotations' | 'message'>,\n\tcall: (...params: [obj: unknown, msg?: string]) => void,\n) {\n\tconst entries = HashMap.toEntries(annotations);\n\tif (entries.length > 0) {\n\t\treturn call(Object.fromEntries(entries), String(message));\n\t}\n\n\treturn call(String(message));\n}\n\nnamespace PinoCtx {\n\tconst tag = 'ff-serv/Pino';\n\texport type Type = ReturnType<typeof create>;\n\n\texport function is(obj: unknown): obj is Type {\n\t\treturn (\n\t\t\ttypeof obj === 'object' &&\n\t\t\tobj != null &&\n\t\t\t'_tag' in obj &&\n\t\t\tobj._tag === tag\n\t\t);\n\t}\n\n\texport function create(pino: LoggerType) {\n\t\treturn {\n\t\t\t_tag: tag,\n\t\t\tpino,\n\t\t\teffectLogger: EffectLogger.make(({ logLevel, ...input }) => {\n\t\t\t\tswitch (logLevel) {\n\t\t\t\t\tcase LogLevel.Info:\n\t\t\t\t\t\treturn callPino(input, pino.info);\n\t\t\t\t\tcase LogLevel.Debug:\n\t\t\t\t\t\treturn callPino(input, pino.debug);\n\t\t\t\t\tcase LogLevel.Warning:\n\t\t\t\t\t\treturn callPino(input, pino.warn);\n\t\t\t\t\tcase LogLevel.Error:\n\t\t\t\t\tcase LogLevel.Fatal:\n\t\t\t\t\t\treturn callPino(input, pino.error);\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn callPino(input, pino.info);\n\t\t\t\t}\n\t\t\t}),\n\t\t};\n\t}\n}\ntype PinoCtx = PinoCtx.Type;\n\nclass Pino extends Context.Tag('ff-serv/Pino')<Pino, PinoCtx>() {}\n\n// Facade\n\nexport namespace Logger {\n\texport const layer = (opts?: Parameters<typeof createInstance>[0]) =>\n\t\tEffectLogger.replaceEffect(\n\t\t\tEffectLogger.defaultLogger,\n\t\t\tEffect.gen(function* () {\n\t\t\t\treturn (yield* Pino).effectLogger;\n\t\t\t}),\n\t\t).pipe(\n\t\t\tLayer.provideMerge(\n\t\t\t\tLayer.effect(\n\t\t\t\t\tPino,\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\treturn PinoCtx.create(yield* createInstance(opts));\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\n\t//\n\n\texport const sync = () =>\n\t\tEffect.gen(function* () {\n\t\t\tconst pino = yield* Pino;\n\t\t\tconst runtime = ManagedRuntime.make(\n\t\t\t\tEffectLogger.replace(EffectLogger.defaultLogger, pino.effectLogger),\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tinfo: (...params: Parameters<typeof Logger.info>) =>\n\t\t\t\t\tLogger.info(...params).pipe((e) => runtime.runSync(e)),\n\t\t\t\tdebug: (...params: Parameters<typeof Logger.debug>) =>\n\t\t\t\t\tLogger.debug(...params).pipe((e) => runtime.runSync(e)),\n\t\t\t\twarn: (...params: Parameters<typeof Logger.warn>) =>\n\t\t\t\t\tLogger.warn(...params).pipe((e) => runtime.runSync(e)),\n\t\t\t\terror: (...params: Parameters<typeof Logger.error>) =>\n\t\t\t\t\tLogger.error(...params).pipe((e) => runtime.runSync(e)),\n\t\t\t};\n\t\t});\n\n\t/** @deprecated — will be renamed to `sync` */\n\texport const get = () => Logger.sync();\n\n\texport const replace =\n\t\t(logger: LoggerType | pino.Logger) =>\n\t\t<A, E, R>(e: Effect.Effect<A, E, R>) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst oldPinoCtx = yield* Pino;\n\t\t\t\tconst pino = LoggerType.is(logger)\n\t\t\t\t\t? logger\n\t\t\t\t\t: LoggerType.fromPino(logger);\n\t\t\t\tconst pinoCtx = PinoCtx.create(pino);\n\n\t\t\t\treturn yield* Effect.provide(\n\t\t\t\t\te,\n\t\t\t\t\tLayer.mergeAll(\n\t\t\t\t\t\tEffectLogger.replace(oldPinoCtx.effectLogger, pinoCtx.effectLogger),\n\t\t\t\t\t\tLayer.succeed(Pino, pinoCtx),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t});\n\n\texport const replaceChild =\n\t\t(...params: Parameters<LoggerType['child']>) =>\n\t\t<A, E, R>(e: Effect.Effect<A, E, R>) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst oldPinoCtx = yield* Pino;\n\t\t\t\tconst pino = oldPinoCtx.pino.child(...params);\n\t\t\t\tconst pinoCtx = PinoCtx.create(pino);\n\n\t\t\t\treturn yield* Effect.provide(\n\t\t\t\t\tEffect.provide(\n\t\t\t\t\t\te,\n\t\t\t\t\t\tEffectLogger.replace(oldPinoCtx.effectLogger, pinoCtx.effectLogger),\n\t\t\t\t\t),\n\t\t\t\t\tLayer.succeed(Pino, pinoCtx),\n\t\t\t\t);\n\t\t\t});\n\n\t// --\n\n\texport const info = (...params: LogParams) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst { message, attributes } = extractParams(...params);\n\t\t\tyield* Effect.logInfo(message).pipe(\n\t\t\t\tattributes ? Effect.annotateLogs(attributes) : (e) => e,\n\t\t\t);\n\t\t});\n\n\texport const debug = (...params: LogParams) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst { message, attributes } = extractParams(...params);\n\t\t\tyield* Effect.logDebug(message).pipe(\n\t\t\t\tattributes ? Effect.annotateLogs(attributes) : (e) => e,\n\t\t\t);\n\t\t});\n\n\texport const warn = (...params: LogParams) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst { message, attributes } = extractParams(...params);\n\t\t\tyield* Effect.logWarning(message).pipe(\n\t\t\t\tattributes ? Effect.annotateLogs(attributes) : (e) => e,\n\t\t\t);\n\t\t});\n\n\texport const error = (...params: LogParams) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst { message, attributes } = extractParams(...params);\n\t\t\tyield* Effect.logError(message).pipe(\n\t\t\t\tattributes ? Effect.annotateLogs(attributes) : (e) => e,\n\t\t\t);\n\t\t});\n\n\t/** @deprecated */\n\texport const flush = (..._params: Parameters<LoggerType['flush']>) =>\n\t\tEffect.void;\n}\n","import { Effect } from 'effect';\nimport * as GetPort from 'get-port';\n\nexport const getPort = (options?: GetPort.Options) =>\n\tEffect.tryPromise(() => GetPort.default(options));\n"],"mappings":"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","names":["import_effect","import_effect","LoggerType","pino","PinoCtx","EffectLogger","Logger","Path","Fn","import_effect"]}
package/dist/index.d.cts CHANGED
@@ -1,11 +1,29 @@
1
- export { b as basicHandler, c as createFetchHandler } from './fetch-handler-BgTGMsrV.cjs';
2
- import * as effect_ConfigError from 'effect/ConfigError';
3
1
  import { Effect, Layer, Context, Logger as Logger$1 } from 'effect';
2
+ import { A as AnyResponse, H as Handler } from './fetch-handler-Dwj0ax2Z.cjs';
3
+ export { c as createFetchHandler } from './fetch-handler-Dwj0ax2Z.cjs';
4
+ import * as effect_ConfigError from 'effect/ConfigError';
4
5
  import pino from 'pino';
5
6
  import * as effect_Cause from 'effect/Cause';
6
7
  import * as GetPort from 'get-port';
7
8
  import 'effect/Scope';
8
9
 
10
+ declare namespace Path {
11
+ type Type = `/${string}` | ((url: URL) => boolean);
12
+ function matched(path: Type, url: URL): boolean;
13
+ }
14
+ declare namespace Fn {
15
+ type Input = [request: Request];
16
+ type OutputSync = AnyResponse;
17
+ type OutputEffect<R> = Effect.Effect<AnyResponse, unknown, R>;
18
+ export type FnSync = (...input: Input) => OutputSync;
19
+ export type FnEffect<R> = (...input: Input) => OutputEffect<R>;
20
+ export type FnAny<R> = (...input: Input) => OutputSync | OutputEffect<R>;
21
+ export function exec<R>(fn: FnAny<R>, ...[request]: Input): OutputEffect<R>;
22
+ export { };
23
+ }
24
+ declare function basicHandler(path: Path.Type, fn: Fn.FnSync): Handler<'basicHandler', never>;
25
+ declare function basicHandler<R>(path: Path.Type, fn: Fn.FnEffect<R>): Handler<'basicHandler', R>;
26
+
9
27
  declare namespace LoggerType {
10
28
  function fromPino(x: pino.Logger<never, boolean>): {
11
29
  info: pino.LogFn;
@@ -84,4 +102,4 @@ declare namespace Logger {
84
102
 
85
103
  declare const getPort: (options?: GetPort.Options) => Effect.Effect<number, effect_Cause.UnknownException, never>;
86
104
 
87
- export { Logger, getPort };
105
+ export { Logger, basicHandler, getPort };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,29 @@
1
- export { b as basicHandler, c as createFetchHandler } from './fetch-handler-BgTGMsrV.js';
2
- import * as effect_ConfigError from 'effect/ConfigError';
3
1
  import { Effect, Layer, Context, Logger as Logger$1 } from 'effect';
2
+ import { A as AnyResponse, H as Handler } from './fetch-handler-Dwj0ax2Z.js';
3
+ export { c as createFetchHandler } from './fetch-handler-Dwj0ax2Z.js';
4
+ import * as effect_ConfigError from 'effect/ConfigError';
4
5
  import pino from 'pino';
5
6
  import * as effect_Cause from 'effect/Cause';
6
7
  import * as GetPort from 'get-port';
7
8
  import 'effect/Scope';
8
9
 
10
+ declare namespace Path {
11
+ type Type = `/${string}` | ((url: URL) => boolean);
12
+ function matched(path: Type, url: URL): boolean;
13
+ }
14
+ declare namespace Fn {
15
+ type Input = [request: Request];
16
+ type OutputSync = AnyResponse;
17
+ type OutputEffect<R> = Effect.Effect<AnyResponse, unknown, R>;
18
+ export type FnSync = (...input: Input) => OutputSync;
19
+ export type FnEffect<R> = (...input: Input) => OutputEffect<R>;
20
+ export type FnAny<R> = (...input: Input) => OutputSync | OutputEffect<R>;
21
+ export function exec<R>(fn: FnAny<R>, ...[request]: Input): OutputEffect<R>;
22
+ export { };
23
+ }
24
+ declare function basicHandler(path: Path.Type, fn: Fn.FnSync): Handler<'basicHandler', never>;
25
+ declare function basicHandler<R>(path: Path.Type, fn: Fn.FnEffect<R>): Handler<'basicHandler', R>;
26
+
9
27
  declare namespace LoggerType {
10
28
  function fromPino(x: pino.Logger<never, boolean>): {
11
29
  info: pino.LogFn;
@@ -84,4 +102,4 @@ declare namespace Logger {
84
102
 
85
103
  declare const getPort: (options?: GetPort.Options) => Effect.Effect<number, effect_Cause.UnknownException, never>;
86
104
 
87
- export { Logger, getPort };
105
+ export { Logger, basicHandler, getPort };
package/dist/index.js CHANGED
@@ -1,3 +1,6 @@
1
+ // src/http/basic.ts
2
+ import { Effect as Effect3 } from "effect";
3
+
1
4
  // src/http/fetch-handler.ts
2
5
  import { Effect as Effect2, FiberSet } from "effect";
3
6
  import { nanoid } from "nanoid";
@@ -213,16 +216,12 @@ var Logger;
213
216
  })(Logger || (Logger = {}));
214
217
 
215
218
  // src/http/fetch-handler.ts
216
- function basicHandler(path, handler) {
217
- return {
218
- _tag: "basicHandler",
219
- handle: ({ url, request }) => {
220
- const matched = typeof path === "function" ? path(url) : path === url.pathname;
221
- if (!matched) return { matched: false, response: void 0 };
222
- return { matched: true, response: handler(request) };
223
- }
224
- };
225
- }
219
+ var Handler = class {
220
+ constructor(_tag, handle) {
221
+ this._tag = _tag;
222
+ this.handle = handle;
223
+ }
224
+ };
226
225
  var createFetchHandler = (handlers, opts) => Effect2.gen(function* () {
227
226
  const runFork = yield* FiberSet.makeRuntimePromise();
228
227
  return async (request) => {
@@ -233,10 +232,36 @@ var createFetchHandler = (handlers, opts) => Effect2.gen(function* () {
233
232
  { request: { pathname: urlObj.pathname } },
234
233
  "Request started"
235
234
  );
236
- for (const handler of Array.isArray(handlers) ? handlers : [handlers]) {
235
+ for (const handler of handlers) {
237
236
  if (!handler) continue;
238
- const maybeResult = handler.handle({ url: urlObj, request });
239
- const result = maybeResult instanceof Promise ? yield* Effect2.tryPromise(() => maybeResult) : maybeResult;
237
+ const result = yield* handler.handle({ url: urlObj, request }).pipe(
238
+ Effect2.flatMap(
239
+ ({ matched, response }) => Effect2.gen(function* () {
240
+ if (matched) {
241
+ return {
242
+ matched: true,
243
+ response: response instanceof Promise ? yield* Effect2.tryPromise(() => response) : response
244
+ };
245
+ }
246
+ return { matched: false, response: void 0 };
247
+ })
248
+ ),
249
+ Effect2.catchAllCause(
250
+ (error) => Effect2.gen(function* () {
251
+ yield* Logger.error(
252
+ { error },
253
+ `Unhandled exception in HTTP handler '${handler._tag}'`
254
+ );
255
+ if (opts?.onError) yield* opts.onError({ error });
256
+ return {
257
+ matched: true,
258
+ response: new Response("Internal Server Error", {
259
+ status: 500
260
+ })
261
+ };
262
+ })
263
+ )
264
+ );
240
265
  if (opts?.debug)
241
266
  yield* Logger.debug(
242
267
  { handler: handler._tag, request, result },
@@ -247,23 +272,9 @@ var createFetchHandler = (handlers, opts) => Effect2.gen(function* () {
247
272
  }
248
273
  return new Response("Not Found", { status: 404 });
249
274
  }).pipe(
250
- Effect2.flatMap(
251
- (response) => response instanceof Promise ? Effect2.tryPromise(() => response) : Effect2.succeed(response)
252
- ),
253
275
  Effect2.tap(
254
276
  (response) => response.ok ? Logger.info(`Request completed with status ${response.status}`) : Logger.warn(`Request completed with status ${response.status}`)
255
277
  ),
256
- Effect2.catchAll(
257
- (error) => Effect2.gen(function* () {
258
- yield* Logger.error(
259
- { error },
260
- "Unhandled exception in HTTP handler"
261
- );
262
- return new Response("Internal Server Error", {
263
- status: 500
264
- });
265
- })
266
- ),
267
278
  Effect2.withSpan("http"),
268
279
  Effect2.annotateLogs({ requestId }),
269
280
  Effect2.scoped
@@ -272,10 +283,40 @@ var createFetchHandler = (handlers, opts) => Effect2.gen(function* () {
272
283
  };
273
284
  });
274
285
 
286
+ // src/http/basic.ts
287
+ var Path;
288
+ ((Path2) => {
289
+ function matched(path, url) {
290
+ return typeof path === "function" ? path(url) : path === url.pathname;
291
+ }
292
+ Path2.matched = matched;
293
+ })(Path || (Path = {}));
294
+ var Fn;
295
+ ((Fn2) => {
296
+ function exec(fn, ...[request]) {
297
+ const response = fn(request);
298
+ if (!Effect3.isEffect(response)) return Effect3.succeed(response);
299
+ return response;
300
+ }
301
+ Fn2.exec = exec;
302
+ })(Fn || (Fn = {}));
303
+ function basicHandler(path, fn) {
304
+ return new Handler("basicHandler", ({ url, request }) => {
305
+ if (!Path.matched(path, url))
306
+ return Effect3.succeed({ matched: false, response: void 0 });
307
+ return Effect3.gen(function* () {
308
+ return {
309
+ matched: true,
310
+ response: yield* Fn.exec(fn, request)
311
+ };
312
+ });
313
+ });
314
+ }
315
+
275
316
  // src/port.ts
276
- import { Effect as Effect3 } from "effect";
317
+ import { Effect as Effect4 } from "effect";
277
318
  import * as GetPort from "get-port";
278
- var getPort = (options) => Effect3.tryPromise(() => GetPort.default(options));
319
+ var getPort = (options) => Effect4.tryPromise(() => GetPort.default(options));
279
320
  export {
280
321
  Logger,
281
322
  basicHandler,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/http/fetch-handler.ts","../src/logger.ts","../src/port.ts"],"sourcesContent":["import { Effect, FiberSet } from 'effect';\nimport { nanoid } from 'nanoid';\nimport { Logger } from '../logger.js';\n\nexport type HandlerResult =\n\t| {\n\t\t\tmatched: true;\n\t\t\tresponse: Response | Promise<Response>;\n\t }\n\t| {\n\t\t\tmatched: false;\n\t\t\tresponse: undefined;\n\t };\n\nexport type Handler<T extends string = string> = {\n\t_tag: T;\n\thandle: (opt: {\n\t\turl: URL;\n\t\trequest: Request;\n\t}) => HandlerResult | Promise<HandlerResult>;\n};\n\nexport function basicHandler(\n\tpath: string | ((url: URL) => boolean),\n\thandler: (request: Request) => Response | Promise<Response>,\n): Handler<'basicHandler'> {\n\treturn {\n\t\t_tag: 'basicHandler',\n\t\thandle: ({ url, request }) => {\n\t\t\tconst matched =\n\t\t\t\ttypeof path === 'function' ? path(url) : path === url.pathname;\n\t\t\tif (!matched) return { matched: false, response: undefined };\n\n\t\t\treturn { matched: true, response: handler(request) };\n\t\t},\n\t};\n}\n\nexport const createFetchHandler = (\n\thandlers?: Handler | [Handler, ...Array<Handler>],\n\topts?: {\n\t\tdebug?: boolean;\n\t},\n) =>\n\tEffect.gen(function* () {\n\t\tconst runFork = yield* FiberSet.makeRuntimePromise();\n\t\treturn async (request: Request) => {\n\t\t\tconst urlObj = new URL(request.url);\n\t\t\tconst requestId = nanoid(6);\n\n\t\t\tconst effect = Effect.gen(function* () {\n\t\t\t\tyield* Logger.info(\n\t\t\t\t\t{ request: { pathname: urlObj.pathname } },\n\t\t\t\t\t'Request started',\n\t\t\t\t);\n\n\t\t\t\tfor (const handler of Array.isArray(handlers) ? handlers : [handlers]) {\n\t\t\t\t\tif (!handler) continue;\n\n\t\t\t\t\tconst maybeResult = handler.handle({ url: urlObj, request });\n\t\t\t\t\tconst result =\n\t\t\t\t\t\tmaybeResult instanceof Promise\n\t\t\t\t\t\t\t? yield* Effect.tryPromise(() => maybeResult)\n\t\t\t\t\t\t\t: maybeResult;\n\n\t\t\t\t\tif (opts?.debug)\n\t\t\t\t\t\tyield* Logger.debug(\n\t\t\t\t\t\t\t{ handler: handler._tag, request, result },\n\t\t\t\t\t\t\t'Processed handler',\n\t\t\t\t\t\t);\n\n\t\t\t\t\tif (!result.matched) continue;\n\t\t\t\t\treturn result.response;\n\t\t\t\t}\n\n\t\t\t\treturn new Response('Not Found', { status: 404 });\n\t\t\t}).pipe(\n\t\t\t\tEffect.flatMap((response) =>\n\t\t\t\t\tresponse instanceof Promise\n\t\t\t\t\t\t? Effect.tryPromise(() => response)\n\t\t\t\t\t\t: Effect.succeed(response),\n\t\t\t\t),\n\t\t\t\tEffect.tap((response) =>\n\t\t\t\t\tresponse.ok\n\t\t\t\t\t\t? Logger.info(`Request completed with status ${response.status}`)\n\t\t\t\t\t\t: Logger.warn(`Request completed with status ${response.status}`),\n\t\t\t\t),\n\t\t\t\tEffect.catchAll((error) =>\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tyield* Logger.error(\n\t\t\t\t\t\t\t{ error },\n\t\t\t\t\t\t\t'Unhandled exception in HTTP handler',\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn new Response('Internal Server Error', {\n\t\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\t});\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t\tEffect.withSpan('http'),\n\t\t\t\tEffect.annotateLogs({ requestId }),\n\t\t\t\tEffect.scoped,\n\t\t\t);\n\n\t\t\treturn runFork(effect);\n\t\t};\n\t});","import {\n\tConfig,\n\tContext,\n\tEffect,\n\tLogger as EffectLogger,\n\tHashMap,\n\tLayer,\n\tLogLevel,\n\tManagedRuntime,\n\tOption,\n} from 'effect';\nimport pino from 'pino';\n\n// Pino Instance\n\nnamespace LoggerType {\n\texport function fromPino(x: pino.Logger<never, boolean>) {\n\t\treturn {\n\t\t\tinfo: x.info.bind(x),\n\t\t\terror: x.error.bind(x),\n\t\t\twarn: x.warn.bind(x),\n\t\t\tdebug: x.debug.bind(x),\n\t\t\tchild: (...params: Parameters<typeof x.child>) => {\n\t\t\t\treturn fromPino(\n\t\t\t\t\tx.child(...params) as unknown as pino.Logger<never, boolean>,\n\t\t\t\t);\n\t\t\t},\n\t\t\tflush: x.flush.bind(x),\n\t\t\t_pino: x,\n\t\t};\n\t}\n\n\texport type CreateParams = {\n\t\tstream?: pino.DestinationStream;\n\t};\n\n\texport function create(params?: CreateParams) {\n\t\tconst logger = pino(\n\t\t\t{\n\t\t\t\tlevel: 'trace', // Level is managed by Effect, so we set the lowest here\n\t\t\t\tserializers: {\n\t\t\t\t\terror: pino.stdSerializers.errWithCause,\n\t\t\t\t\terr: pino.stdSerializers.errWithCause,\n\t\t\t\t},\n\t\t\t\tformatters: {\n\t\t\t\t\tlevel: (label) => {\n\t\t\t\t\t\treturn { level: label };\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tparams?.stream,\n\t\t);\n\t\treturn fromPino(logger);\n\t}\n\n\texport type Type = ReturnType<typeof LoggerType.create>;\n\n\texport function is(x: object): x is Type {\n\t\treturn '_pino' in x;\n\t}\n}\ntype LoggerType = LoggerType.Type;\n\n// The Gist\n\nconst createInstance = (params?: LoggerType.CreateParams) =>\n\tEffect.gen(function* () {\n\t\tconst isDev = Option.getOrNull(\n\t\t\tyield* Config.boolean('DEV').pipe(Config.option),\n\t\t);\n\t\tconst logFile = Option.getOrNull(\n\t\t\tyield* Config.boolean('LOGGER_LOGFILE').pipe(Config.option),\n\t\t);\n\n\t\treturn LoggerType.create({\n\t\t\t...params,\n\t\t\t...(isDev && {\n\t\t\t\tstream: logFile\n\t\t\t\t\t? pino.transport({\n\t\t\t\t\t\t\ttarget: 'pino/file',\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tdestination: './logs/server.log',\n\t\t\t\t\t\t\t\tmkdir: true,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t: pino.transport({\n\t\t\t\t\t\t\ttarget: 'pino-pretty',\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tignore: 'pid,hostname',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t}),\n\t\t});\n\t});\n\n// Pino Context and Effect Logger integration\n\ntype LogParams = [obj: unknown, msg?: string];\nfunction extractParams(...[obj, msg]: LogParams) {\n\tif (typeof obj === 'string') {\n\t\treturn { message: obj };\n\t}\n\treturn { message: msg, attributes: obj as Record<string, any> };\n}\n\n/** A simple helper for calling pino log functions */\nfunction callPino(\n\t{\n\t\tannotations,\n\t\tmessage,\n\t}: Pick<EffectLogger.Logger.Options<unknown>, 'annotations' | 'message'>,\n\tcall: (...params: [obj: unknown, msg?: string]) => void,\n) {\n\tconst entries = HashMap.toEntries(annotations);\n\tif (entries.length > 0) {\n\t\treturn call(Object.fromEntries(entries), String(message));\n\t}\n\n\treturn call(String(message));\n}\n\nnamespace PinoCtx {\n\tconst tag = 'ff-serv/Pino';\n\texport type Type = ReturnType<typeof create>;\n\n\texport function is(obj: unknown): obj is Type {\n\t\treturn (\n\t\t\ttypeof obj === 'object' &&\n\t\t\tobj != null &&\n\t\t\t'_tag' in obj &&\n\t\t\tobj._tag === tag\n\t\t);\n\t}\n\n\texport function create(pino: LoggerType) {\n\t\treturn {\n\t\t\t_tag: tag,\n\t\t\tpino,\n\t\t\teffectLogger: EffectLogger.make(({ logLevel, ...input }) => {\n\t\t\t\tswitch (logLevel) {\n\t\t\t\t\tcase LogLevel.Info:\n\t\t\t\t\t\treturn callPino(input, pino.info);\n\t\t\t\t\tcase LogLevel.Debug:\n\t\t\t\t\t\treturn callPino(input, pino.debug);\n\t\t\t\t\tcase LogLevel.Warning:\n\t\t\t\t\t\treturn callPino(input, pino.warn);\n\t\t\t\t\tcase LogLevel.Error:\n\t\t\t\t\tcase LogLevel.Fatal:\n\t\t\t\t\t\treturn callPino(input, pino.error);\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn callPino(input, pino.info);\n\t\t\t\t}\n\t\t\t}),\n\t\t};\n\t}\n}\ntype PinoCtx = PinoCtx.Type;\n\nclass Pino extends Context.Tag('ff-serv/Pino')<Pino, PinoCtx>() {}\n\n// Facade\n\nexport namespace Logger {\n\texport const layer = (opts?: Parameters<typeof createInstance>[0]) =>\n\t\tEffectLogger.replaceEffect(\n\t\t\tEffectLogger.defaultLogger,\n\t\t\tEffect.gen(function* () {\n\t\t\t\treturn (yield* Pino).effectLogger;\n\t\t\t}),\n\t\t).pipe(\n\t\t\tLayer.provideMerge(\n\t\t\t\tLayer.effect(\n\t\t\t\t\tPino,\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\treturn PinoCtx.create(yield* createInstance(opts));\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\n\t//\n\n\texport const sync = () =>\n\t\tEffect.gen(function* () {\n\t\t\tconst pino = yield* Pino;\n\t\t\tconst runtime = ManagedRuntime.make(\n\t\t\t\tEffectLogger.replace(EffectLogger.defaultLogger, pino.effectLogger),\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tinfo: (...params: Parameters<typeof Logger.info>) =>\n\t\t\t\t\tLogger.info(...params).pipe((e) => runtime.runSync(e)),\n\t\t\t\tdebug: (...params: Parameters<typeof Logger.debug>) =>\n\t\t\t\t\tLogger.debug(...params).pipe((e) => runtime.runSync(e)),\n\t\t\t\twarn: (...params: Parameters<typeof Logger.warn>) =>\n\t\t\t\t\tLogger.warn(...params).pipe((e) => runtime.runSync(e)),\n\t\t\t\terror: (...params: Parameters<typeof Logger.error>) =>\n\t\t\t\t\tLogger.error(...params).pipe((e) => runtime.runSync(e)),\n\t\t\t};\n\t\t});\n\n\t/** @deprecated — will be renamed to `sync` */\n\texport const get = () => Logger.sync();\n\n\texport const replace =\n\t\t(logger: LoggerType | pino.Logger) =>\n\t\t<A, E, R>(e: Effect.Effect<A, E, R>) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst oldPinoCtx = yield* Pino;\n\t\t\t\tconst pino = LoggerType.is(logger)\n\t\t\t\t\t? logger\n\t\t\t\t\t: LoggerType.fromPino(logger);\n\t\t\t\tconst pinoCtx = PinoCtx.create(pino);\n\n\t\t\t\treturn yield* Effect.provide(\n\t\t\t\t\te,\n\t\t\t\t\tLayer.mergeAll(\n\t\t\t\t\t\tEffectLogger.replace(oldPinoCtx.effectLogger, pinoCtx.effectLogger),\n\t\t\t\t\t\tLayer.succeed(Pino, pinoCtx),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t});\n\n\texport const replaceChild =\n\t\t(...params: Parameters<LoggerType['child']>) =>\n\t\t<A, E, R>(e: Effect.Effect<A, E, R>) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst oldPinoCtx = yield* Pino;\n\t\t\t\tconst pino = oldPinoCtx.pino.child(...params);\n\t\t\t\tconst pinoCtx = PinoCtx.create(pino);\n\n\t\t\t\treturn yield* Effect.provide(\n\t\t\t\t\tEffect.provide(\n\t\t\t\t\t\te,\n\t\t\t\t\t\tEffectLogger.replace(oldPinoCtx.effectLogger, pinoCtx.effectLogger),\n\t\t\t\t\t),\n\t\t\t\t\tLayer.succeed(Pino, pinoCtx),\n\t\t\t\t);\n\t\t\t});\n\n\t// --\n\n\texport const info = (...params: LogParams) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst { message, attributes } = extractParams(...params);\n\t\t\tyield* Effect.logInfo(message).pipe(\n\t\t\t\tattributes ? Effect.annotateLogs(attributes) : (e) => e,\n\t\t\t);\n\t\t});\n\n\texport const debug = (...params: LogParams) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst { message, attributes } = extractParams(...params);\n\t\t\tyield* Effect.logDebug(message).pipe(\n\t\t\t\tattributes ? Effect.annotateLogs(attributes) : (e) => e,\n\t\t\t);\n\t\t});\n\n\texport const warn = (...params: LogParams) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst { message, attributes } = extractParams(...params);\n\t\t\tyield* Effect.logWarning(message).pipe(\n\t\t\t\tattributes ? Effect.annotateLogs(attributes) : (e) => e,\n\t\t\t);\n\t\t});\n\n\texport const error = (...params: LogParams) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst { message, attributes } = extractParams(...params);\n\t\t\tyield* Effect.logError(message).pipe(\n\t\t\t\tattributes ? Effect.annotateLogs(attributes) : (e) => e,\n\t\t\t);\n\t\t});\n\n\t/** @deprecated */\n\texport const flush = (..._params: Parameters<LoggerType['flush']>) =>\n\t\tEffect.void;\n}\n","import { Effect } from 'effect';\nimport * as GetPort from 'get-port';\n\nexport const getPort = (options?: GetPort.Options) =>\n\tEffect.tryPromise(() => GetPort.default(options));\n"],"mappings":"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","names":["Effect","LoggerType","PinoCtx","pino","Logger","Effect","Effect"]}
1
+ {"version":3,"sources":["../src/http/basic.ts","../src/http/fetch-handler.ts","../src/logger.ts","../src/port.ts"],"sourcesContent":["import { Effect } from 'effect';\nimport { type AnyResponse, Handler } from './fetch-handler.js';\n\nexport namespace Path {\n\texport type Type = `/${string}` | ((url: URL) => boolean);\n\texport function matched(path: Type, url: URL) {\n\t\treturn typeof path === 'function' ? path(url) : path === url.pathname;\n\t}\n}\n\nexport namespace Fn {\n\ttype Input = [request: Request];\n\n\ttype OutputSync = AnyResponse;\n\ttype OutputEffect<R> = Effect.Effect<AnyResponse, unknown, R>;\n\n\texport type FnSync = (...input: Input) => OutputSync;\n\texport type FnEffect<R> = (...input: Input) => OutputEffect<R>;\n\texport type FnAny<R> = (...input: Input) => OutputSync | OutputEffect<R>;\n\n\texport function exec<R>(fn: FnAny<R>, ...[request]: Input) {\n\t\tconst response = fn(request);\n\t\tif (!Effect.isEffect(response)) return Effect.succeed(response);\n\t\treturn response;\n\t}\n}\n\nexport function basicHandler(\n\tpath: Path.Type,\n\tfn: Fn.FnSync,\n): Handler<'basicHandler', never>;\nexport function basicHandler<R>(\n\tpath: Path.Type,\n\tfn: Fn.FnEffect<R>,\n): Handler<'basicHandler', R>;\nexport function basicHandler<R>(path: Path.Type, fn: Fn.FnAny<R>) {\n\treturn new Handler('basicHandler', ({ url, request }) => {\n\t\tif (!Path.matched(path, url))\n\t\t\treturn Effect.succeed({ matched: false, response: undefined });\n\n\t\treturn Effect.gen(function* () {\n\t\t\treturn {\n\t\t\t\tmatched: true,\n\t\t\t\tresponse: yield* Fn.exec(fn, request),\n\t\t\t};\n\t\t});\n\t});\n}\n","import { Effect, FiberSet } from 'effect';\nimport type { Cause } from 'effect/Cause';\nimport { nanoid } from 'nanoid';\nimport { Logger } from '../logger.js';\n\n// #region Handler\n\nexport type AnyResponse = Response | Promise<Response>;\n\nexport type HandlerResult =\n\t| {\n\t\t\tmatched: true;\n\t\t\tresponse: AnyResponse;\n\t }\n\t| {\n\t\t\tmatched: false;\n\t\t\tresponse: undefined;\n\t };\n\nexport class Handler<NAME extends string, R> {\n\tconstructor(\n\t\treadonly _tag: NAME,\n\t\treadonly handle: (opt: {\n\t\t\turl: URL;\n\t\t\trequest: Request;\n\t\t}) => Effect.Effect<HandlerResult, unknown, R>,\n\t) {}\n}\n\n// #endregion\n\ntype ExtractRequirements<T> = T extends Handler<string, infer R> ? R : never;\n\nexport const createFetchHandler = <\n\tconst HANDLERS extends [\n\t\tHandler<string, unknown>,\n\t\t...Array<Handler<string, unknown>>,\n\t],\n\tR = ExtractRequirements<HANDLERS[number]>,\n>(\n\thandlers: HANDLERS,\n\topts?: {\n\t\tdebug?: boolean;\n\t\tonError?: (ctx: {\n\t\t\terror: Cause<unknown>;\n\t\t}) => Effect.Effect<unknown, unknown>;\n\t},\n) =>\n\tEffect.gen(function* () {\n\t\tconst runFork = yield* FiberSet.makeRuntimePromise<R>();\n\t\treturn async (request: Request) => {\n\t\t\tconst urlObj = new URL(request.url);\n\t\t\tconst requestId = nanoid(6);\n\n\t\t\tconst effect = Effect.gen(function* () {\n\t\t\t\tyield* Logger.info(\n\t\t\t\t\t{ request: { pathname: urlObj.pathname } },\n\t\t\t\t\t'Request started',\n\t\t\t\t);\n\n\t\t\t\tfor (const handler of handlers) {\n\t\t\t\t\tif (!handler) continue;\n\n\t\t\t\t\tconst result = yield* handler.handle({ url: urlObj, request }).pipe(\n\t\t\t\t\t\tEffect.flatMap(({ matched, response }) =>\n\t\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\t\tif (matched) {\n\t\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\t\tmatched: true,\n\t\t\t\t\t\t\t\t\t\tresponse:\n\t\t\t\t\t\t\t\t\t\t\tresponse instanceof Promise\n\t\t\t\t\t\t\t\t\t\t\t\t? yield* Effect.tryPromise(() => response)\n\t\t\t\t\t\t\t\t\t\t\t\t: response,\n\t\t\t\t\t\t\t\t\t} as const;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn { matched: false, response: undefined } as const;\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t\tEffect.catchAllCause((error) =>\n\t\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\t\tyield* Logger.error(\n\t\t\t\t\t\t\t\t\t{ error },\n\t\t\t\t\t\t\t\t\t`Unhandled exception in HTTP handler '${handler._tag}'`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tif (opts?.onError) yield* opts.onError({ error });\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tmatched: true,\n\t\t\t\t\t\t\t\t\tresponse: new Response('Internal Server Error', {\n\t\t\t\t\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t} as const;\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\n\t\t\t\t\tif (opts?.debug)\n\t\t\t\t\t\tyield* Logger.debug(\n\t\t\t\t\t\t\t{ handler: handler._tag, request, result },\n\t\t\t\t\t\t\t'Processed handler',\n\t\t\t\t\t\t);\n\n\t\t\t\t\tif (!result.matched) continue;\n\t\t\t\t\treturn result.response;\n\t\t\t\t}\n\n\t\t\t\treturn new Response('Not Found', { status: 404 });\n\t\t\t}).pipe(\n\t\t\t\tEffect.tap((response) =>\n\t\t\t\t\tresponse.ok\n\t\t\t\t\t\t? Logger.info(`Request completed with status ${response.status}`)\n\t\t\t\t\t\t: Logger.warn(`Request completed with status ${response.status}`),\n\t\t\t\t),\n\t\t\t\tEffect.withSpan('http'),\n\t\t\t\tEffect.annotateLogs({ requestId }),\n\t\t\t\tEffect.scoped,\n\t\t\t) as Effect.Effect<Response, never, R>;\n\n\t\t\treturn runFork(effect);\n\t\t};\n\t});\n","import {\n\tConfig,\n\tContext,\n\tEffect,\n\tLogger as EffectLogger,\n\tHashMap,\n\tLayer,\n\tLogLevel,\n\tManagedRuntime,\n\tOption,\n} from 'effect';\nimport pino from 'pino';\n\n// Pino Instance\n\nnamespace LoggerType {\n\texport function fromPino(x: pino.Logger<never, boolean>) {\n\t\treturn {\n\t\t\tinfo: x.info.bind(x),\n\t\t\terror: x.error.bind(x),\n\t\t\twarn: x.warn.bind(x),\n\t\t\tdebug: x.debug.bind(x),\n\t\t\tchild: (...params: Parameters<typeof x.child>) => {\n\t\t\t\treturn fromPino(\n\t\t\t\t\tx.child(...params) as unknown as pino.Logger<never, boolean>,\n\t\t\t\t);\n\t\t\t},\n\t\t\tflush: x.flush.bind(x),\n\t\t\t_pino: x,\n\t\t};\n\t}\n\n\texport type CreateParams = {\n\t\tstream?: pino.DestinationStream;\n\t};\n\n\texport function create(params?: CreateParams) {\n\t\tconst logger = pino(\n\t\t\t{\n\t\t\t\tlevel: 'trace', // Level is managed by Effect, so we set the lowest here\n\t\t\t\tserializers: {\n\t\t\t\t\terror: pino.stdSerializers.errWithCause,\n\t\t\t\t\terr: pino.stdSerializers.errWithCause,\n\t\t\t\t},\n\t\t\t\tformatters: {\n\t\t\t\t\tlevel: (label) => {\n\t\t\t\t\t\treturn { level: label };\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tparams?.stream,\n\t\t);\n\t\treturn fromPino(logger);\n\t}\n\n\texport type Type = ReturnType<typeof LoggerType.create>;\n\n\texport function is(x: object): x is Type {\n\t\treturn '_pino' in x;\n\t}\n}\ntype LoggerType = LoggerType.Type;\n\n// The Gist\n\nconst createInstance = (params?: LoggerType.CreateParams) =>\n\tEffect.gen(function* () {\n\t\tconst isDev = Option.getOrNull(\n\t\t\tyield* Config.boolean('DEV').pipe(Config.option),\n\t\t);\n\t\tconst logFile = Option.getOrNull(\n\t\t\tyield* Config.boolean('LOGGER_LOGFILE').pipe(Config.option),\n\t\t);\n\n\t\treturn LoggerType.create({\n\t\t\t...params,\n\t\t\t...(isDev && {\n\t\t\t\tstream: logFile\n\t\t\t\t\t? pino.transport({\n\t\t\t\t\t\t\ttarget: 'pino/file',\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tdestination: './logs/server.log',\n\t\t\t\t\t\t\t\tmkdir: true,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t: pino.transport({\n\t\t\t\t\t\t\ttarget: 'pino-pretty',\n\t\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t\tignore: 'pid,hostname',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}),\n\t\t\t}),\n\t\t});\n\t});\n\n// Pino Context and Effect Logger integration\n\ntype LogParams = [obj: unknown, msg?: string];\nfunction extractParams(...[obj, msg]: LogParams) {\n\tif (typeof obj === 'string') {\n\t\treturn { message: obj };\n\t}\n\treturn { message: msg, attributes: obj as Record<string, any> };\n}\n\n/** A simple helper for calling pino log functions */\nfunction callPino(\n\t{\n\t\tannotations,\n\t\tmessage,\n\t}: Pick<EffectLogger.Logger.Options<unknown>, 'annotations' | 'message'>,\n\tcall: (...params: [obj: unknown, msg?: string]) => void,\n) {\n\tconst entries = HashMap.toEntries(annotations);\n\tif (entries.length > 0) {\n\t\treturn call(Object.fromEntries(entries), String(message));\n\t}\n\n\treturn call(String(message));\n}\n\nnamespace PinoCtx {\n\tconst tag = 'ff-serv/Pino';\n\texport type Type = ReturnType<typeof create>;\n\n\texport function is(obj: unknown): obj is Type {\n\t\treturn (\n\t\t\ttypeof obj === 'object' &&\n\t\t\tobj != null &&\n\t\t\t'_tag' in obj &&\n\t\t\tobj._tag === tag\n\t\t);\n\t}\n\n\texport function create(pino: LoggerType) {\n\t\treturn {\n\t\t\t_tag: tag,\n\t\t\tpino,\n\t\t\teffectLogger: EffectLogger.make(({ logLevel, ...input }) => {\n\t\t\t\tswitch (logLevel) {\n\t\t\t\t\tcase LogLevel.Info:\n\t\t\t\t\t\treturn callPino(input, pino.info);\n\t\t\t\t\tcase LogLevel.Debug:\n\t\t\t\t\t\treturn callPino(input, pino.debug);\n\t\t\t\t\tcase LogLevel.Warning:\n\t\t\t\t\t\treturn callPino(input, pino.warn);\n\t\t\t\t\tcase LogLevel.Error:\n\t\t\t\t\tcase LogLevel.Fatal:\n\t\t\t\t\t\treturn callPino(input, pino.error);\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn callPino(input, pino.info);\n\t\t\t\t}\n\t\t\t}),\n\t\t};\n\t}\n}\ntype PinoCtx = PinoCtx.Type;\n\nclass Pino extends Context.Tag('ff-serv/Pino')<Pino, PinoCtx>() {}\n\n// Facade\n\nexport namespace Logger {\n\texport const layer = (opts?: Parameters<typeof createInstance>[0]) =>\n\t\tEffectLogger.replaceEffect(\n\t\t\tEffectLogger.defaultLogger,\n\t\t\tEffect.gen(function* () {\n\t\t\t\treturn (yield* Pino).effectLogger;\n\t\t\t}),\n\t\t).pipe(\n\t\t\tLayer.provideMerge(\n\t\t\t\tLayer.effect(\n\t\t\t\t\tPino,\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\treturn PinoCtx.create(yield* createInstance(opts));\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\n\t//\n\n\texport const sync = () =>\n\t\tEffect.gen(function* () {\n\t\t\tconst pino = yield* Pino;\n\t\t\tconst runtime = ManagedRuntime.make(\n\t\t\t\tEffectLogger.replace(EffectLogger.defaultLogger, pino.effectLogger),\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tinfo: (...params: Parameters<typeof Logger.info>) =>\n\t\t\t\t\tLogger.info(...params).pipe((e) => runtime.runSync(e)),\n\t\t\t\tdebug: (...params: Parameters<typeof Logger.debug>) =>\n\t\t\t\t\tLogger.debug(...params).pipe((e) => runtime.runSync(e)),\n\t\t\t\twarn: (...params: Parameters<typeof Logger.warn>) =>\n\t\t\t\t\tLogger.warn(...params).pipe((e) => runtime.runSync(e)),\n\t\t\t\terror: (...params: Parameters<typeof Logger.error>) =>\n\t\t\t\t\tLogger.error(...params).pipe((e) => runtime.runSync(e)),\n\t\t\t};\n\t\t});\n\n\t/** @deprecated — will be renamed to `sync` */\n\texport const get = () => Logger.sync();\n\n\texport const replace =\n\t\t(logger: LoggerType | pino.Logger) =>\n\t\t<A, E, R>(e: Effect.Effect<A, E, R>) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst oldPinoCtx = yield* Pino;\n\t\t\t\tconst pino = LoggerType.is(logger)\n\t\t\t\t\t? logger\n\t\t\t\t\t: LoggerType.fromPino(logger);\n\t\t\t\tconst pinoCtx = PinoCtx.create(pino);\n\n\t\t\t\treturn yield* Effect.provide(\n\t\t\t\t\te,\n\t\t\t\t\tLayer.mergeAll(\n\t\t\t\t\t\tEffectLogger.replace(oldPinoCtx.effectLogger, pinoCtx.effectLogger),\n\t\t\t\t\t\tLayer.succeed(Pino, pinoCtx),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t});\n\n\texport const replaceChild =\n\t\t(...params: Parameters<LoggerType['child']>) =>\n\t\t<A, E, R>(e: Effect.Effect<A, E, R>) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst oldPinoCtx = yield* Pino;\n\t\t\t\tconst pino = oldPinoCtx.pino.child(...params);\n\t\t\t\tconst pinoCtx = PinoCtx.create(pino);\n\n\t\t\t\treturn yield* Effect.provide(\n\t\t\t\t\tEffect.provide(\n\t\t\t\t\t\te,\n\t\t\t\t\t\tEffectLogger.replace(oldPinoCtx.effectLogger, pinoCtx.effectLogger),\n\t\t\t\t\t),\n\t\t\t\t\tLayer.succeed(Pino, pinoCtx),\n\t\t\t\t);\n\t\t\t});\n\n\t// --\n\n\texport const info = (...params: LogParams) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst { message, attributes } = extractParams(...params);\n\t\t\tyield* Effect.logInfo(message).pipe(\n\t\t\t\tattributes ? Effect.annotateLogs(attributes) : (e) => e,\n\t\t\t);\n\t\t});\n\n\texport const debug = (...params: LogParams) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst { message, attributes } = extractParams(...params);\n\t\t\tyield* Effect.logDebug(message).pipe(\n\t\t\t\tattributes ? Effect.annotateLogs(attributes) : (e) => e,\n\t\t\t);\n\t\t});\n\n\texport const warn = (...params: LogParams) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst { message, attributes } = extractParams(...params);\n\t\t\tyield* Effect.logWarning(message).pipe(\n\t\t\t\tattributes ? Effect.annotateLogs(attributes) : (e) => e,\n\t\t\t);\n\t\t});\n\n\texport const error = (...params: LogParams) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst { message, attributes } = extractParams(...params);\n\t\t\tyield* Effect.logError(message).pipe(\n\t\t\t\tattributes ? Effect.annotateLogs(attributes) : (e) => e,\n\t\t\t);\n\t\t});\n\n\t/** @deprecated */\n\texport const flush = (..._params: Parameters<LoggerType['flush']>) =>\n\t\tEffect.void;\n}\n","import { Effect } from 'effect';\nimport * as GetPort from 'get-port';\n\nexport const getPort = (options?: GetPort.Options) =>\n\tEffect.tryPromise(() => GetPort.default(options));\n"],"mappings":"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","names":["Effect","Effect","LoggerType","PinoCtx","pino","Logger","Effect","Path","Fn","Effect","Effect"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ff-serv",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -20,13 +20,17 @@
20
20
  ],
21
21
  "scripts": {
22
22
  "build": "tsup",
23
- "test": "vitest run",
23
+ "test": "bun -b vitest run",
24
24
  "dev": "tsup --watch"
25
25
  },
26
26
  "devDependencies": {
27
+ "@effect/vitest": "^0.27.0",
28
+ "@orpc/client": "^1.13.2",
27
29
  "@types/bun": "^1.3.2",
30
+ "ff-effect": "^0.0.7",
28
31
  "tsup": "^8.5.0",
29
- "typescript": "^5.9.3"
32
+ "typescript": "^5.9.3",
33
+ "vitest": "^4.0.16"
30
34
  },
31
35
  "peerDependencies": {
32
36
  "effect": "^3",
@@ -0,0 +1,46 @@
1
+ import { Deferred, Effect, Fiber } from 'effect';
2
+ import { Logger } from '../../logger.js';
3
+ import { getPort } from '../../port.js';
4
+
5
+ export function serverTester<
6
+ SERVER_R,
7
+ SERVER_E,
8
+ SERVER_OUTPUT extends { server: Bun.Server<never> },
9
+ TEST_A,
10
+ TEST_E,
11
+ TEST_R,
12
+ >(opt: {
13
+ server: (opt: {
14
+ port: number;
15
+ }) => Effect.Effect<SERVER_OUTPUT, SERVER_E, SERVER_R> | SERVER_OUTPUT;
16
+ test: (opt: SERVER_OUTPUT) => Effect.Effect<TEST_A, TEST_E, TEST_R>;
17
+ }) {
18
+ return Effect.gen(function* () {
19
+ const port = yield* getPort();
20
+ const ready = yield* Deferred.make<SERVER_OUTPUT>();
21
+
22
+ const fiber = yield* Effect.fork(
23
+ Effect.scoped(
24
+ Effect.gen(function* () {
25
+ const res = opt.server({ port });
26
+ const output = Effect.isEffect(res) ? yield* res : res;
27
+ yield* Logger.info(`Server started in ${port}`);
28
+ yield* Deferred.succeed(ready, output);
29
+ yield* Effect.addFinalizer(() =>
30
+ Effect.gen(function* () {
31
+ yield* Effect.promise(() => output.server.stop(true));
32
+ yield* Logger.info('Server stopped');
33
+ }),
34
+ );
35
+ yield* Effect.never;
36
+ }),
37
+ ),
38
+ );
39
+
40
+ const output = yield* Deferred.await(ready);
41
+
42
+ yield* opt.test(output);
43
+
44
+ yield* Fiber.interrupt(fiber);
45
+ }).pipe(Effect.scoped);
46
+ }