ff-serv 0.1.7 → 0.1.9

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.
package/dist/cli.js CHANGED
@@ -274,4 +274,4 @@ Quitting wizard mode...`));return r4(i8(F))}return s(O)}))}case"ShowVersion":{le
274
274
  `);Y.push({schema:Z,tables:Q.map((G)=>G.table_name)})}return Y}),XR8=(D)=>c.gen(function*(){let X=yield*DR8(D);yield*c.log(`
275
275
  The following will be truncated:
276
276
  `);for(let{schema:Y,tables:Z}of X){if(Z.length===0){yield*c.log(`Schema: ${Y}`),yield*c.log(` (no tables)
277
- `);continue}yield*c.log(`Schema: ${Y}`);for(let Q of Z)yield*c.log(` - ${Q}`);yield*c.log("")}let{shouldReset:J}=yield*c.tryPromise(()=>lT.prompt([{type:"confirm",name:"shouldReset",message:"Proceed with truncation?",default:!1}]));return{shouldReset:J,schemaInfo:X}}),JR8=(D,X)=>c.gen(function*(){let J=Qo(D);yield*c.addFinalizer(()=>c.ignore(c.tryPromise(()=>J.end()))),yield*c.log(`Truncating ${X.length} schema(s)...`);for(let{schema:Y,tables:Z}of X){if(Z.length===0){yield*c.log(` No tables in "${Y}"`);continue}yield*c.log(`Truncating ${Z.length} table(s) in schema "${Y}"...`);let Q=Z.map((G)=>`"${Y}"."${G}"`).join(", ");yield*c.tryPromise(()=>J.unsafe(`TRUNCATE ${Q} RESTART IDENTITY CASCADE`))}yield*c.log("Database reset complete")}),YR8=(D,X)=>c.gen(function*(){yield*c.log("Restoring from file"),yield*d9.make("psql",D,"-f",X).pipe(d9.stdout("inherit"),d9.exitCode)}),ZR8=c.gen(function*(){let D=yield*H5.FileSystem,X=yield*pq.Path,J=yield*D.makeTempDirectory(),Y=X.join(J,"dump.sql");return yield*c.log(`Prepared dump file: ${Y}`),Y}),QR8=(D,X)=>c.gen(function*(){yield*(yield*H5.FileSystem).copy(D,X),yield*c.log(`Dump saved to: ${X}`)}),Go=(D,X)=>c.catchAll(D,(J)=>c.gen(function*(){if(yield*c.logError(`Operation failed: ${J}`),X.downloaded)yield*c.log(`Dump file preserved at: ${X.filePath}`),yield*c.log("You can retry using --fromDump flag");if(yield*aI0)return yield*c.log("Retrying..."),yield*Go(D,X);return yield*c.fail(J)})),w_0=S7.make("pull",{fromDump:m9.file("fromDump").pipe(m9.optional),targetDatabaseUrl:XT.text({name:"targetDatabaseUrl"}).pipe(XT.optional),saveDump:m9.file("saveDump").pipe(m9.optional),config:m9.file("config").pipe(m9.optional)},({fromDump:D,targetDatabaseUrl:X,saveDump:J,config:Y})=>c.gen(function*(){let Z=yield*SE(F0.isSome(Y)?Y.value:void 0),Q=F0.getOrUndefined(X)||F0.flatMap(Z,(H)=>F0.fromNullable(H.pullDatabase?.targetDatabaseUrl)).pipe(F0.getOrUndefined)||(yield*rI0(eM8)),G;if(F0.isSome(D)){if(G={filePath:D.value,downloaded:!0},yield*c.log(`Using dump file: ${G.filePath}`),!(yield*A_0(null,Q))){yield*c.log("Operation cancelled");return}}else{G={filePath:yield*ZR8,downloaded:!1};let K=yield*Mj(F0.flatMap(Z,($)=>F0.fromNullable($.pullDatabase?.source)).pipe(F0.getOrUndefined)),B=yield*Aj(K);if(!(yield*A_0(B,Q))){yield*c.log("Operation cancelled");return}if(yield*Go(wj(B,G.filePath).pipe(c.tap(()=>c.sync(()=>{G.downloaded=!0}))),G),F0.isSome(J))yield*QR8(G.filePath,J.value)}if(yield*Go(c.gen(function*(){let{shouldReset:H,schemaInfo:K}=yield*XR8(Q);if(H)yield*JR8(Q,K);yield*YR8(Q,G.filePath)}),G),!F0.isSome(D))if(yield*sI0(G.filePath))yield*(yield*H5.FileSystem).remove(G.filePath,{recursive:!0}),yield*c.log("Dump file cleaned up");else yield*c.log(`Dump file kept at: ${G.filePath}`);yield*c.log("Database pull complete!")}).pipe(c.scoped));var M_0=S7.make("db",{},()=>c.log("Database commands - UsepullCommandle subcommands")).pipe(S7.withSubcommands([w_0,eI0]));var R_0={name:"ff-serv",version:"0.1.7",type:"module",bin:{"ff-serv":"./dist/cli"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js",require:"./dist/index.cjs"},"./orpc":{types:"./dist/exports/orpc.d.ts",import:"./dist/exports/orpc.js",require:"./dist/exports/orpc.cjs"}},files:["dist","src"],scripts:{build:"tsup && bun run build:cli","build:cli":"bun build src/cli/index.ts --production --target=bun --outfile dist/cli.js",test:"bun -b vitest run",dev:"tsup --watch"},devDependencies:{"@effect/cli":"^0.71.0","@effect/platform-bun":"^0.87.0","@effect/vitest":"^0.27.0","@orpc/client":"^1.13.2","@types/bun":"^1.3.2","@types/cli-progress":"^3.11.6","cli-progress":"^3.12.0","ff-effect":"^0.0.7",inquirer:"^12.10.0",postgres:"^3.4.7",tsup:"^8.5.0",typescript:"^5.9.3",vitest:"^4.0.16"},peerDependencies:{effect:"^3",pino:"^9","@effect/opentelemetry":"^0.60.0","get-port":"^7","@orpc/server":"^1"},publishConfig:{access:"public"},homepage:"https://github.com/fdarian/ff.git",repository:{type:"git",url:"git+https://github.com/fdarian/ff.git"},bugs:{url:"https://github.com/fdarian/ff/issues"},keywords:["effect","server","service"],dependencies:{"@effect/platform":"^0.94.1",nanoid:"^5.1.6"}};var HR8=S7.make("ff-serv",{},()=>c.log("ff-serv CLI - Use --help for available commands")).pipe(S7.withSubcommands([M_0])),KR8=S7.run(HR8,{name:"ff-serv",version:R_0.version});KR8(process.argv).pipe(c.provide(ON0),LN0);
277
+ `);continue}yield*c.log(`Schema: ${Y}`);for(let Q of Z)yield*c.log(` - ${Q}`);yield*c.log("")}let{shouldReset:J}=yield*c.tryPromise(()=>lT.prompt([{type:"confirm",name:"shouldReset",message:"Proceed with truncation?",default:!1}]));return{shouldReset:J,schemaInfo:X}}),JR8=(D,X)=>c.gen(function*(){let J=Qo(D);yield*c.addFinalizer(()=>c.ignore(c.tryPromise(()=>J.end()))),yield*c.log(`Truncating ${X.length} schema(s)...`);for(let{schema:Y,tables:Z}of X){if(Z.length===0){yield*c.log(` No tables in "${Y}"`);continue}yield*c.log(`Truncating ${Z.length} table(s) in schema "${Y}"...`);let Q=Z.map((G)=>`"${Y}"."${G}"`).join(", ");yield*c.tryPromise(()=>J.unsafe(`TRUNCATE ${Q} RESTART IDENTITY CASCADE`))}yield*c.log("Database reset complete")}),YR8=(D,X)=>c.gen(function*(){yield*c.log("Restoring from file"),yield*d9.make("psql",D,"-f",X).pipe(d9.stdout("inherit"),d9.exitCode)}),ZR8=c.gen(function*(){let D=yield*H5.FileSystem,X=yield*pq.Path,J=yield*D.makeTempDirectory(),Y=X.join(J,"dump.sql");return yield*c.log(`Prepared dump file: ${Y}`),Y}),QR8=(D,X)=>c.gen(function*(){yield*(yield*H5.FileSystem).copy(D,X),yield*c.log(`Dump saved to: ${X}`)}),Go=(D,X)=>c.catchAll(D,(J)=>c.gen(function*(){if(yield*c.logError(`Operation failed: ${J}`),X.downloaded)yield*c.log(`Dump file preserved at: ${X.filePath}`),yield*c.log("You can retry using --fromDump flag");if(yield*aI0)return yield*c.log("Retrying..."),yield*Go(D,X);return yield*c.fail(J)})),w_0=S7.make("pull",{fromDump:m9.file("fromDump").pipe(m9.optional),targetDatabaseUrl:XT.text({name:"targetDatabaseUrl"}).pipe(XT.optional),saveDump:m9.file("saveDump").pipe(m9.optional),config:m9.file("config").pipe(m9.optional)},({fromDump:D,targetDatabaseUrl:X,saveDump:J,config:Y})=>c.gen(function*(){let Z=yield*SE(F0.isSome(Y)?Y.value:void 0),Q=F0.getOrUndefined(X)||F0.flatMap(Z,(H)=>F0.fromNullable(H.pullDatabase?.targetDatabaseUrl)).pipe(F0.getOrUndefined)||(yield*rI0(eM8)),G;if(F0.isSome(D)){if(G={filePath:D.value,downloaded:!0},yield*c.log(`Using dump file: ${G.filePath}`),!(yield*A_0(null,Q))){yield*c.log("Operation cancelled");return}}else{G={filePath:yield*ZR8,downloaded:!1};let K=yield*Mj(F0.flatMap(Z,($)=>F0.fromNullable($.pullDatabase?.source)).pipe(F0.getOrUndefined)),B=yield*Aj(K);if(!(yield*A_0(B,Q))){yield*c.log("Operation cancelled");return}if(yield*Go(wj(B,G.filePath).pipe(c.tap(()=>c.sync(()=>{G.downloaded=!0}))),G),F0.isSome(J))yield*QR8(G.filePath,J.value)}if(yield*Go(c.gen(function*(){let{shouldReset:H,schemaInfo:K}=yield*XR8(Q);if(H)yield*JR8(Q,K);yield*YR8(Q,G.filePath)}),G),!F0.isSome(D))if(yield*sI0(G.filePath))yield*(yield*H5.FileSystem).remove(G.filePath,{recursive:!0}),yield*c.log("Dump file cleaned up");else yield*c.log(`Dump file kept at: ${G.filePath}`);yield*c.log("Database pull complete!")}).pipe(c.scoped));var M_0=S7.make("db",{},()=>c.log("Database commands - UsepullCommandle subcommands")).pipe(S7.withSubcommands([w_0,eI0]));var R_0={name:"ff-serv",version:"0.1.9",type:"module",bin:{"ff-serv":"./dist/cli.js"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js",require:"./dist/index.cjs"},"./orpc":{types:"./dist/exports/orpc.d.ts",import:"./dist/exports/orpc.js",require:"./dist/exports/orpc.cjs"}},files:["dist","src"],scripts:{build:"tsup && bun run build:cli","build:cli":"bun build src/cli/index.ts --production --target=bun --outfile dist/cli.js",test:"bun -b vitest run",dev:"tsup --watch"},devDependencies:{"@effect/cli":"^0.71.0","@effect/platform-bun":"^0.87.0","@effect/vitest":"^0.27.0","@orpc/client":"^1.13.2","@types/bun":"^1.3.2","@types/cli-progress":"^3.11.6","cli-progress":"^3.12.0","ff-effect":"^0.0.7",inquirer:"^12.10.0",postgres:"^3.4.7",tsup:"^8.5.0",typescript:"^5.9.3",vitest:"^4.0.16"},peerDependencies:{effect:"^3","@effect/opentelemetry":"^0.60.0","get-port":"^7","@orpc/server":"^1"},publishConfig:{access:"public"},homepage:"https://github.com/fdarian/ff.git",repository:{type:"git",url:"git+https://github.com/fdarian/ff.git"},bugs:{url:"https://github.com/fdarian/ff/issues"},keywords:["effect","server","service"],dependencies:{"@effect/platform":"^0.94.1",nanoid:"^5.1.6"}};var HR8=S7.make("ff-serv",{},()=>c.log("ff-serv CLI - Use --help for available commands")).pipe(S7.withSubcommands([M_0])),KR8=S7.run(HR8,{name:"ff-serv",version:R_0.version});KR8(process.argv).pipe(c.provide(ON0),LN0);
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
 
30
20
  // src/exports/orpc.ts
@@ -43,177 +33,26 @@ var import_nanoid = require("nanoid");
43
33
 
44
34
  // src/logger.ts
45
35
  var import_effect = require("effect");
46
- var import_pino = __toESM(require("pino"), 1);
47
- var LoggerType;
48
- ((LoggerType2) => {
49
- function fromPino(x) {
50
- return {
51
- info: x.info.bind(x),
52
- error: x.error.bind(x),
53
- warn: x.warn.bind(x),
54
- debug: x.debug.bind(x),
55
- child: (...params) => {
56
- return fromPino(
57
- x.child(...params)
58
- );
59
- },
60
- flush: x.flush.bind(x),
61
- _pino: x
62
- };
63
- }
64
- LoggerType2.fromPino = fromPino;
65
- function create(params) {
66
- const logger = (0, import_pino.default)(
67
- {
68
- level: "trace",
69
- // Level is managed by Effect, so we set the lowest here
70
- serializers: {
71
- error: import_pino.default.stdSerializers.errWithCause,
72
- err: import_pino.default.stdSerializers.errWithCause
73
- },
74
- formatters: {
75
- level: (label) => {
76
- return { level: label };
77
- }
78
- }
79
- },
80
- params?.stream
81
- );
82
- return fromPino(logger);
83
- }
84
- LoggerType2.create = create;
85
- function is(x) {
86
- return "_pino" in x;
87
- }
88
- LoggerType2.is = is;
89
- })(LoggerType || (LoggerType = {}));
90
- var createInstance = (params) => import_effect.Effect.gen(function* () {
91
- const isDev = import_effect.Option.getOrNull(
92
- yield* import_effect.Config.boolean("DEV").pipe(import_effect.Config.option)
93
- );
94
- const logFile = import_effect.Option.getOrNull(
95
- yield* import_effect.Config.boolean("LOGGER_LOGFILE").pipe(import_effect.Config.option)
96
- );
97
- return LoggerType.create({
98
- ...params,
99
- ...isDev && {
100
- stream: logFile ? import_pino.default.transport({
101
- target: "pino/file",
102
- options: {
103
- destination: "./logs/server.log",
104
- mkdir: true
105
- }
106
- }) : import_pino.default.transport({
107
- target: "pino-pretty",
108
- options: {
109
- ignore: "pid,hostname"
110
- }
111
- })
112
- }
113
- });
114
- });
115
36
  function extractParams(...[obj, msg]) {
116
37
  if (typeof obj === "string") {
117
38
  return { message: obj };
118
39
  }
119
40
  return { message: msg, attributes: obj };
120
41
  }
121
- function callPino({
122
- annotations,
123
- message
124
- }, call) {
125
- const entries = import_effect.HashMap.toEntries(annotations);
126
- if (entries.length > 0) {
127
- return call(Object.fromEntries(entries), String(message));
128
- }
129
- return call(String(message));
130
- }
131
- var PinoCtx;
132
- ((PinoCtx2) => {
133
- const tag = "ff-serv/Pino";
134
- function is(obj) {
135
- return typeof obj === "object" && obj != null && "_tag" in obj && obj._tag === tag;
136
- }
137
- PinoCtx2.is = is;
138
- function create(pino2) {
139
- return {
140
- _tag: tag,
141
- pino: pino2,
142
- effectLogger: import_effect.Logger.make(({ logLevel, ...input }) => {
143
- switch (logLevel) {
144
- case import_effect.LogLevel.Info:
145
- return callPino(input, pino2.info);
146
- case import_effect.LogLevel.Debug:
147
- return callPino(input, pino2.debug);
148
- case import_effect.LogLevel.Warning:
149
- return callPino(input, pino2.warn);
150
- case import_effect.LogLevel.Error:
151
- case import_effect.LogLevel.Fatal:
152
- return callPino(input, pino2.error);
153
- default:
154
- return callPino(input, pino2.info);
155
- }
156
- })
157
- };
158
- }
159
- PinoCtx2.create = create;
160
- })(PinoCtx || (PinoCtx = {}));
161
- var Pino = class extends import_effect.Context.Tag("ff-serv/Pino")() {
162
- };
163
42
  var Logger;
164
43
  ((Logger2) => {
165
- Logger2.layer = (opts) => import_effect.Logger.replaceEffect(
166
- import_effect.Logger.defaultLogger,
167
- import_effect.Effect.gen(function* () {
168
- return (yield* Pino).effectLogger;
169
- })
170
- ).pipe(
171
- import_effect.Layer.provideMerge(
172
- import_effect.Layer.effect(
173
- Pino,
174
- import_effect.Effect.gen(function* () {
175
- return PinoCtx.create(yield* createInstance(opts));
176
- })
177
- )
178
- )
179
- );
180
44
  Logger2.sync = () => import_effect.Effect.gen(function* () {
181
- const pino2 = yield* Pino;
182
- const runtime = import_effect.ManagedRuntime.make(
183
- import_effect.Logger.replace(import_effect.Logger.defaultLogger, pino2.effectLogger)
184
- );
45
+ const runPromise = yield* import_effect.FiberSet.makeRuntimePromise();
46
+ const run = (e) => {
47
+ void runPromise(e);
48
+ };
185
49
  return {
186
- info: (...params) => Logger2.info(...params).pipe((e) => runtime.runSync(e)),
187
- debug: (...params) => Logger2.debug(...params).pipe((e) => runtime.runSync(e)),
188
- warn: (...params) => Logger2.warn(...params).pipe((e) => runtime.runSync(e)),
189
- error: (...params) => Logger2.error(...params).pipe((e) => runtime.runSync(e))
50
+ info: (...params) => run(Logger2.info(...params)),
51
+ debug: (...params) => run(Logger2.debug(...params)),
52
+ warn: (...params) => run(Logger2.warn(...params)),
53
+ error: (...params) => run(Logger2.error(...params))
190
54
  };
191
55
  });
192
- Logger2.get = () => Logger2.sync();
193
- Logger2.replace = (logger) => (e) => import_effect.Effect.gen(function* () {
194
- const oldPinoCtx = yield* Pino;
195
- const pino2 = LoggerType.is(logger) ? logger : LoggerType.fromPino(logger);
196
- const pinoCtx = PinoCtx.create(pino2);
197
- return yield* import_effect.Effect.provide(
198
- e,
199
- import_effect.Layer.mergeAll(
200
- import_effect.Logger.replace(oldPinoCtx.effectLogger, pinoCtx.effectLogger),
201
- import_effect.Layer.succeed(Pino, pinoCtx)
202
- )
203
- );
204
- });
205
- Logger2.replaceChild = (...params) => (e) => import_effect.Effect.gen(function* () {
206
- const oldPinoCtx = yield* Pino;
207
- const pino2 = oldPinoCtx.pino.child(...params);
208
- const pinoCtx = PinoCtx.create(pino2);
209
- return yield* import_effect.Effect.provide(
210
- import_effect.Effect.provide(
211
- e,
212
- import_effect.Logger.replace(oldPinoCtx.effectLogger, pinoCtx.effectLogger)
213
- ),
214
- import_effect.Layer.succeed(Pino, pinoCtx)
215
- );
216
- });
217
56
  Logger2.info = (...params) => import_effect.Effect.gen(function* () {
218
57
  const { message, attributes } = extractParams(...params);
219
58
  yield* import_effect.Effect.logInfo(message).pipe(
@@ -238,7 +77,6 @@ var Logger;
238
77
  attributes ? import_effect.Effect.annotateLogs(attributes) : (e) => e
239
78
  );
240
79
  });
241
- Logger2.flush = (..._params) => import_effect.Effect.void;
242
80
  })(Logger || (Logger = {}));
243
81
 
244
82
  // src/http/fetch-handler.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/exports/orpc.ts","../../src/http/orpc.ts","../../src/http/fetch-handler.ts","../../src/logger.ts"],"sourcesContent":["export { oRPCHandler } from '../http/orpc.js';","import type { Context } from '@orpc/server';\nimport type { FetchHandler } from '@orpc/server/fetch';\nimport type { FriendlyStandardHandleOptions } from '@orpc/server/standard';\nimport { Effect } from 'effect';\nimport { Handler } from './fetch-handler.js';\n\ntype MaybeOptionalOptions<TOptions> =\n\tRecord<never, never> extends TOptions\n\t\t? [options?: TOptions]\n\t\t: [options: TOptions];\n\ntype PossibleOpt<T extends Context, E, R> =\n\t| FriendlyStandardHandleOptions<T>\n\t| Effect.Effect<FriendlyStandardHandleOptions<T>, E, R>;\n\nfunction getValue<T extends Context, E, R>(opt: PossibleOpt<T, E, R>) {\n\treturn Effect.isEffect(opt) ? opt : Effect.succeed(opt);\n}\n\nexport function oRPCHandler<T extends Context, E, R>(\n\thandler: FetchHandler<T>,\n\topt?: PossibleOpt<T, E, R> | ((request: Request) => PossibleOpt<T, E, R>),\n) {\n\treturn new Handler('oRPCHandler', ({ request }) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst _opt = (\n\t\t\t\topt\n\t\t\t\t\t? [yield* getValue(typeof opt === 'function' ? opt(request) : opt)]\n\t\t\t\t\t: []\n\t\t\t) as MaybeOptionalOptions<FriendlyStandardHandleOptions<T>>;\n\t\t\treturn yield* Effect.tryPromise(() => handler.handle(request, ..._opt));\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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGA,IAAAA,iBAAuB;;;ACHvB,IAAAC,iBAAiC;AAEjC,oBAAuB;;;ACFvB,oBAUO;AACP,kBAAiB;AAIjB,IAAU;AAAA,CAAV,CAAUC,gBAAV;AACQ,WAAS,SAAS,GAAgC;AACxD,WAAO;AAAA,MACN,MAAM,EAAE,KAAK,KAAK,CAAC;AAAA,MACnB,OAAO,EAAE,MAAM,KAAK,CAAC;AAAA,MACrB,MAAM,EAAE,KAAK,KAAK,CAAC;AAAA,MACnB,OAAO,EAAE,MAAM,KAAK,CAAC;AAAA,MACrB,OAAO,IAAI,WAAuC;AACjD,eAAO;AAAA,UACN,EAAE,MAAM,GAAG,MAAM;AAAA,QAClB;AAAA,MACD;AAAA,MACA,OAAO,EAAE,MAAM,KAAK,CAAC;AAAA,MACrB,OAAO;AAAA,IACR;AAAA,EACD;AAdO,EAAAA,YAAS;AAoBT,WAAS,OAAO,QAAuB;AAC7C,UAAM,aAAS,YAAAC;AAAA,MACd;AAAA,QACC,OAAO;AAAA;AAAA,QACP,aAAa;AAAA,UACZ,OAAO,YAAAA,QAAK,eAAe;AAAA,UAC3B,KAAK,YAAAA,QAAK,eAAe;AAAA,QAC1B;AAAA,QACA,YAAY;AAAA,UACX,OAAO,CAAC,UAAU;AACjB,mBAAO,EAAE,OAAO,MAAM;AAAA,UACvB;AAAA,QACD;AAAA,MACD;AAAA,MACA,QAAQ;AAAA,IACT;AACA,WAAO,SAAS,MAAM;AAAA,EACvB;AAjBO,EAAAD,YAAS;AAqBT,WAAS,GAAG,GAAsB;AACxC,WAAO,WAAW;AAAA,EACnB;AAFO,EAAAA,YAAS;AAAA,GA1CP;AAkDV,IAAM,iBAAiB,CAAC,WACvB,qBAAO,IAAI,aAAa;AACvB,QAAM,QAAQ,qBAAO;AAAA,IACpB,OAAO,qBAAO,QAAQ,KAAK,EAAE,KAAK,qBAAO,MAAM;AAAA,EAChD;AACA,QAAM,UAAU,qBAAO;AAAA,IACtB,OAAO,qBAAO,QAAQ,gBAAgB,EAAE,KAAK,qBAAO,MAAM;AAAA,EAC3D;AAEA,SAAO,WAAW,OAAO;AAAA,IACxB,GAAG;AAAA,IACH,GAAI,SAAS;AAAA,MACZ,QAAQ,UACL,YAAAC,QAAK,UAAU;AAAA,QACf,QAAQ;AAAA,QACR,SAAS;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACR;AAAA,MACD,CAAC,IACA,YAAAA,QAAK,UAAU;AAAA,QACf,QAAQ;AAAA,QACR,SAAS;AAAA,UACR,QAAQ;AAAA,QACT;AAAA,MACD,CAAC;AAAA,IACJ;AAAA,EACD,CAAC;AACF,CAAC;AAKF,SAAS,iBAAiB,CAAC,KAAK,GAAG,GAAc;AAChD,MAAI,OAAO,QAAQ,UAAU;AAC5B,WAAO,EAAE,SAAS,IAAI;AAAA,EACvB;AACA,SAAO,EAAE,SAAS,KAAK,YAAY,IAA2B;AAC/D;AAGA,SAAS,SACR;AAAA,EACC;AAAA,EACA;AACD,GACA,MACC;AACD,QAAM,UAAU,sBAAQ,UAAU,WAAW;AAC7C,MAAI,QAAQ,SAAS,GAAG;AACvB,WAAO,KAAK,OAAO,YAAY,OAAO,GAAG,OAAO,OAAO,CAAC;AAAA,EACzD;AAEA,SAAO,KAAK,OAAO,OAAO,CAAC;AAC5B;AAEA,IAAU;AAAA,CAAV,CAAUC,aAAV;AACC,QAAM,MAAM;AAGL,WAAS,GAAG,KAA2B;AAC7C,WACC,OAAO,QAAQ,YACf,OAAO,QACP,UAAU,OACV,IAAI,SAAS;AAAA,EAEf;AAPO,EAAAA,SAAS;AAST,WAAS,OAAOD,OAAkB;AACxC,WAAO;AAAA,MACN,MAAM;AAAA,MACN,MAAAA;AAAA,MACA,cAAc,cAAAE,OAAa,KAAK,CAAC,EAAE,UAAU,GAAG,MAAM,MAAM;AAC3D,gBAAQ,UAAU;AAAA,UACjB,KAAK,uBAAS;AACb,mBAAO,SAAS,OAAOF,MAAK,IAAI;AAAA,UACjC,KAAK,uBAAS;AACb,mBAAO,SAAS,OAAOA,MAAK,KAAK;AAAA,UAClC,KAAK,uBAAS;AACb,mBAAO,SAAS,OAAOA,MAAK,IAAI;AAAA,UACjC,KAAK,uBAAS;AAAA,UACd,KAAK,uBAAS;AACb,mBAAO,SAAS,OAAOA,MAAK,KAAK;AAAA,UAClC;AACC,mBAAO,SAAS,OAAOA,MAAK,IAAI;AAAA,QAClC;AAAA,MACD,CAAC;AAAA,IACF;AAAA,EACD;AApBO,EAAAC,SAAS;AAAA,GAbP;AAqCV,IAAM,OAAN,cAAmB,sBAAQ,IAAI,cAAc,EAAiB,EAAE;AAAC;AAI1D,IAAU;AAAA,CAAV,CAAUE,YAAV;AACC,EAAMA,QAAA,QAAQ,CAAC,SACrB,cAAAD,OAAa;AAAA,IACZ,cAAAA,OAAa;AAAA,IACb,qBAAO,IAAI,aAAa;AACvB,cAAQ,OAAO,MAAM;AAAA,IACtB,CAAC;AAAA,EACF,EAAE;AAAA,IACD,oBAAM;AAAA,MACL,oBAAM;AAAA,QACL;AAAA,QACA,qBAAO,IAAI,aAAa;AACvB,iBAAO,QAAQ,OAAO,OAAO,eAAe,IAAI,CAAC;AAAA,QAClD,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAIM,EAAMC,QAAA,OAAO,MACnB,qBAAO,IAAI,aAAa;AACvB,UAAMH,QAAO,OAAO;AACpB,UAAM,UAAU,6BAAe;AAAA,MAC9B,cAAAE,OAAa,QAAQ,cAAAA,OAAa,eAAeF,MAAK,YAAY;AAAA,IACnE;AACA,WAAO;AAAA,MACN,MAAM,IAAI,WACTG,QAAO,KAAK,GAAG,MAAM,EAAE,KAAK,CAAC,MAAM,QAAQ,QAAQ,CAAC,CAAC;AAAA,MACtD,OAAO,IAAI,WACVA,QAAO,MAAM,GAAG,MAAM,EAAE,KAAK,CAAC,MAAM,QAAQ,QAAQ,CAAC,CAAC;AAAA,MACvD,MAAM,IAAI,WACTA,QAAO,KAAK,GAAG,MAAM,EAAE,KAAK,CAAC,MAAM,QAAQ,QAAQ,CAAC,CAAC;AAAA,MACtD,OAAO,IAAI,WACVA,QAAO,MAAM,GAAG,MAAM,EAAE,KAAK,CAAC,MAAM,QAAQ,QAAQ,CAAC,CAAC;AAAA,IACxD;AAAA,EACD,CAAC;AAGK,EAAMA,QAAA,MAAM,MAAMA,QAAO,KAAK;AAE9B,EAAMA,QAAA,UACZ,CAAC,WACD,CAAU,MACT,qBAAO,IAAI,aAAa;AACvB,UAAM,aAAa,OAAO;AAC1B,UAAMH,QAAO,WAAW,GAAG,MAAM,IAC9B,SACA,WAAW,SAAS,MAAM;AAC7B,UAAM,UAAU,QAAQ,OAAOA,KAAI;AAEnC,WAAO,OAAO,qBAAO;AAAA,MACpB;AAAA,MACA,oBAAM;AAAA,QACL,cAAAE,OAAa,QAAQ,WAAW,cAAc,QAAQ,YAAY;AAAA,QAClE,oBAAM,QAAQ,MAAM,OAAO;AAAA,MAC5B;AAAA,IACD;AAAA,EACD,CAAC;AAEI,EAAMC,QAAA,eACZ,IAAI,WACJ,CAAU,MACT,qBAAO,IAAI,aAAa;AACvB,UAAM,aAAa,OAAO;AAC1B,UAAMH,QAAO,WAAW,KAAK,MAAM,GAAG,MAAM;AAC5C,UAAM,UAAU,QAAQ,OAAOA,KAAI;AAEnC,WAAO,OAAO,qBAAO;AAAA,MACpB,qBAAO;AAAA,QACN;AAAA,QACA,cAAAE,OAAa,QAAQ,WAAW,cAAc,QAAQ,YAAY;AAAA,MACnE;AAAA,MACA,oBAAM,QAAQ,MAAM,OAAO;AAAA,IAC5B;AAAA,EACD,CAAC;AAII,EAAMC,QAAA,OAAO,IAAI,WACvB,qBAAO,IAAI,aAAa;AACvB,UAAM,EAAE,SAAS,WAAW,IAAI,cAAc,GAAG,MAAM;AACvD,WAAO,qBAAO,QAAQ,OAAO,EAAE;AAAA,MAC9B,aAAa,qBAAO,aAAa,UAAU,IAAI,CAAC,MAAM;AAAA,IACvD;AAAA,EACD,CAAC;AAEK,EAAMA,QAAA,QAAQ,IAAI,WACxB,qBAAO,IAAI,aAAa;AACvB,UAAM,EAAE,SAAS,WAAW,IAAI,cAAc,GAAG,MAAM;AACvD,WAAO,qBAAO,SAAS,OAAO,EAAE;AAAA,MAC/B,aAAa,qBAAO,aAAa,UAAU,IAAI,CAAC,MAAM;AAAA,IACvD;AAAA,EACD,CAAC;AAEK,EAAMA,QAAA,OAAO,IAAI,WACvB,qBAAO,IAAI,aAAa;AACvB,UAAM,EAAE,SAAS,WAAW,IAAI,cAAc,GAAG,MAAM;AACvD,WAAO,qBAAO,WAAW,OAAO,EAAE;AAAA,MACjC,aAAa,qBAAO,aAAa,UAAU,IAAI,CAAC,MAAM;AAAA,IACvD;AAAA,EACD,CAAC;AAEK,EAAMA,QAAA,QAAQ,IAAI,WACxB,qBAAO,IAAI,aAAa;AACvB,UAAM,EAAE,SAAS,WAAW,IAAI,cAAc,GAAG,MAAM;AACvD,WAAO,qBAAO,SAAS,OAAO,EAAE;AAAA,MAC/B,aAAa,qBAAO,aAAa,UAAU,IAAI,CAAC,MAAM;AAAA,IACvD;AAAA,EACD,CAAC;AAGK,EAAMA,QAAA,QAAQ,IAAI,YACxB,qBAAO;AAAA,GAjHQ;;;AD/IV,IAAM,UAAN,MAAsC;AAAA,EAC5C,YACU,MACA,QAIR;AALQ;AACA;AAAA,EAIP;AACJ;;;ADZA,SAAS,SAAkC,KAA2B;AACrE,SAAO,sBAAO,SAAS,GAAG,IAAI,MAAM,sBAAO,QAAQ,GAAG;AACvD;AAEO,SAAS,YACf,SACA,KACC;AACD,SAAO,IAAI;AAAA,IAAQ;AAAA,IAAe,CAAC,EAAE,QAAQ,MAC5C,sBAAO,IAAI,aAAa;AACvB,YAAM,OACL,MACG,CAAC,OAAO,SAAS,OAAO,QAAQ,aAAa,IAAI,OAAO,IAAI,GAAG,CAAC,IAChE,CAAC;AAEL,aAAO,OAAO,sBAAO,WAAW,MAAM,QAAQ,OAAO,SAAS,GAAG,IAAI,CAAC;AAAA,IACvE,CAAC;AAAA,EACF;AACD;","names":["import_effect","import_effect","LoggerType","pino","PinoCtx","EffectLogger","Logger"]}
1
+ {"version":3,"sources":["../../src/exports/orpc.ts","../../src/http/orpc.ts","../../src/http/fetch-handler.ts","../../src/logger.ts"],"sourcesContent":["export { oRPCHandler } from '../http/orpc.js';","import type { Context } from '@orpc/server';\nimport type { FetchHandler } from '@orpc/server/fetch';\nimport type { FriendlyStandardHandleOptions } from '@orpc/server/standard';\nimport { Effect } from 'effect';\nimport { Handler } from './fetch-handler.js';\n\ntype MaybeOptionalOptions<TOptions> =\n\tRecord<never, never> extends TOptions\n\t\t? [options?: TOptions]\n\t\t: [options: TOptions];\n\ntype PossibleOpt<T extends Context, E, R> =\n\t| FriendlyStandardHandleOptions<T>\n\t| Effect.Effect<FriendlyStandardHandleOptions<T>, E, R>;\n\nfunction getValue<T extends Context, E, R>(opt: PossibleOpt<T, E, R>) {\n\treturn Effect.isEffect(opt) ? opt : Effect.succeed(opt);\n}\n\nexport function oRPCHandler<T extends Context, E, R>(\n\thandler: FetchHandler<T>,\n\topt?: PossibleOpt<T, E, R> | ((request: Request) => PossibleOpt<T, E, R>),\n) {\n\treturn new Handler('oRPCHandler', ({ request }) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst _opt = (\n\t\t\t\topt\n\t\t\t\t\t? [yield* getValue(typeof opt === 'function' ? opt(request) : opt)]\n\t\t\t\t\t: []\n\t\t\t) as MaybeOptionalOptions<FriendlyStandardHandleOptions<T>>;\n\t\t\treturn yield* Effect.tryPromise(() => handler.handle(request, ..._opt));\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 { Effect, FiberSet } from 'effect';\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\nexport namespace Logger {\n\texport const sync = () =>\n\t\tEffect.gen(function* () {\n\t\t\tconst runPromise = yield* FiberSet.makeRuntimePromise();\n\n\t\t\tconst run = (e: Effect.Effect<void, never, never>) => {\n\t\t\t\t// Intentionally ignoring the await here\n\t\t\t\tvoid runPromise(e);\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\tinfo: (...params: Parameters<typeof Logger.info>) =>\n\t\t\t\t\trun(Logger.info(...params)),\n\t\t\t\tdebug: (...params: Parameters<typeof Logger.debug>) =>\n\t\t\t\t\trun(Logger.debug(...params)),\n\t\t\t\twarn: (...params: Parameters<typeof Logger.warn>) =>\n\t\t\t\t\trun(Logger.warn(...params)),\n\t\t\t\terror: (...params: Parameters<typeof Logger.error>) =>\n\t\t\t\t\trun(Logger.error(...params)),\n\t\t\t};\n\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"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGA,IAAAA,iBAAuB;;;ACHvB,IAAAC,iBAAiC;AAEjC,oBAAuB;;;ACFvB,oBAAiC;AAGjC,SAAS,iBAAiB,CAAC,KAAK,GAAG,GAAc;AAChD,MAAI,OAAO,QAAQ,UAAU;AAC5B,WAAO,EAAE,SAAS,IAAI;AAAA,EACvB;AACA,SAAO,EAAE,SAAS,KAAK,YAAY,IAA2B;AAC/D;AAEO,IAAU;AAAA,CAAV,CAAUC,YAAV;AACC,EAAMA,QAAA,OAAO,MACnB,qBAAO,IAAI,aAAa;AACvB,UAAM,aAAa,OAAO,uBAAS,mBAAmB;AAEtD,UAAM,MAAM,CAAC,MAAyC;AAErD,WAAK,WAAW,CAAC;AAAA,IAClB;AAEA,WAAO;AAAA,MACN,MAAM,IAAI,WACT,IAAIA,QAAO,KAAK,GAAG,MAAM,CAAC;AAAA,MAC3B,OAAO,IAAI,WACV,IAAIA,QAAO,MAAM,GAAG,MAAM,CAAC;AAAA,MAC5B,MAAM,IAAI,WACT,IAAIA,QAAO,KAAK,GAAG,MAAM,CAAC;AAAA,MAC3B,OAAO,IAAI,WACV,IAAIA,QAAO,MAAM,GAAG,MAAM,CAAC;AAAA,IAC7B;AAAA,EACD,CAAC;AAIK,EAAMA,QAAA,OAAO,IAAI,WACvB,qBAAO,IAAI,aAAa;AACvB,UAAM,EAAE,SAAS,WAAW,IAAI,cAAc,GAAG,MAAM;AACvD,WAAO,qBAAO,QAAQ,OAAO,EAAE;AAAA,MAC9B,aAAa,qBAAO,aAAa,UAAU,IAAI,CAAC,MAAM;AAAA,IACvD;AAAA,EACD,CAAC;AAEK,EAAMA,QAAA,QAAQ,IAAI,WACxB,qBAAO,IAAI,aAAa;AACvB,UAAM,EAAE,SAAS,WAAW,IAAI,cAAc,GAAG,MAAM;AACvD,WAAO,qBAAO,SAAS,OAAO,EAAE;AAAA,MAC/B,aAAa,qBAAO,aAAa,UAAU,IAAI,CAAC,MAAM;AAAA,IACvD;AAAA,EACD,CAAC;AAEK,EAAMA,QAAA,OAAO,IAAI,WACvB,qBAAO,IAAI,aAAa;AACvB,UAAM,EAAE,SAAS,WAAW,IAAI,cAAc,GAAG,MAAM;AACvD,WAAO,qBAAO,WAAW,OAAO,EAAE;AAAA,MACjC,aAAa,qBAAO,aAAa,UAAU,IAAI,CAAC,MAAM;AAAA,IACvD;AAAA,EACD,CAAC;AAEK,EAAMA,QAAA,QAAQ,IAAI,WACxB,qBAAO,IAAI,aAAa;AACvB,UAAM,EAAE,SAAS,WAAW,IAAI,cAAc,GAAG,MAAM;AACvD,WAAO,qBAAO,SAAS,OAAO,EAAE;AAAA,MAC/B,aAAa,qBAAO,aAAa,UAAU,IAAI,CAAC,MAAM;AAAA,IACvD;AAAA,EACD,CAAC;AAAA,GAtDc;;;ADSV,IAAM,UAAN,MAAsC;AAAA,EAC5C,YACU,MACA,QAIR;AALQ;AACA;AAAA,EAIP;AACJ;;;ADZA,SAAS,SAAkC,KAA2B;AACrE,SAAO,sBAAO,SAAS,GAAG,IAAI,MAAM,sBAAO,QAAQ,GAAG;AACvD;AAEO,SAAS,YACf,SACA,KACC;AACD,SAAO,IAAI;AAAA,IAAQ;AAAA,IAAe,CAAC,EAAE,QAAQ,MAC5C,sBAAO,IAAI,aAAa;AACvB,YAAM,OACL,MACG,CAAC,OAAO,SAAS,OAAO,QAAQ,aAAa,IAAI,OAAO,IAAI,GAAG,CAAC,IAChE,CAAC;AAEL,aAAO,OAAO,sBAAO,WAAW,MAAM,QAAQ,OAAO,SAAS,GAAG,IAAI,CAAC;AAAA,IACvE,CAAC;AAAA,EACF;AACD;","names":["import_effect","import_effect","Logger"]}
@@ -2,7 +2,7 @@ import { Context } from '@orpc/server';
2
2
  import { FetchHandler } from '@orpc/server/fetch';
3
3
  import { FriendlyStandardHandleOptions } from '@orpc/server/standard';
4
4
  import { Effect } from 'effect';
5
- import { H as Handler } from '../fetch-handler-Dwj0ax2Z.cjs';
5
+ import { H as Handler } from '../fetch-handler-aDi6CpLx.cjs';
6
6
  import 'effect/Scope';
7
7
  import 'effect/Cause';
8
8
 
@@ -2,7 +2,7 @@ import { Context } from '@orpc/server';
2
2
  import { FetchHandler } from '@orpc/server/fetch';
3
3
  import { FriendlyStandardHandleOptions } from '@orpc/server/standard';
4
4
  import { Effect } from 'effect';
5
- import { H as Handler } from '../fetch-handler-Dwj0ax2Z.js';
5
+ import { H as Handler } from '../fetch-handler-aDi6CpLx.js';
6
6
  import 'effect/Scope';
7
7
  import 'effect/Cause';
8
8
 
@@ -2,192 +2,31 @@
2
2
  import { Effect as Effect3 } from "effect";
3
3
 
4
4
  // src/http/fetch-handler.ts
5
- import { Effect as Effect2, FiberSet } from "effect";
5
+ import { Effect as Effect2, FiberSet as FiberSet2 } from "effect";
6
6
  import { nanoid } from "nanoid";
7
7
 
8
8
  // src/logger.ts
9
- import {
10
- Config,
11
- Context,
12
- Effect,
13
- Logger as EffectLogger,
14
- HashMap,
15
- Layer,
16
- LogLevel,
17
- ManagedRuntime,
18
- Option
19
- } from "effect";
20
- import pino from "pino";
21
- var LoggerType;
22
- ((LoggerType2) => {
23
- function fromPino(x) {
24
- return {
25
- info: x.info.bind(x),
26
- error: x.error.bind(x),
27
- warn: x.warn.bind(x),
28
- debug: x.debug.bind(x),
29
- child: (...params) => {
30
- return fromPino(
31
- x.child(...params)
32
- );
33
- },
34
- flush: x.flush.bind(x),
35
- _pino: x
36
- };
37
- }
38
- LoggerType2.fromPino = fromPino;
39
- function create(params) {
40
- const logger = pino(
41
- {
42
- level: "trace",
43
- // Level is managed by Effect, so we set the lowest here
44
- serializers: {
45
- error: pino.stdSerializers.errWithCause,
46
- err: pino.stdSerializers.errWithCause
47
- },
48
- formatters: {
49
- level: (label) => {
50
- return { level: label };
51
- }
52
- }
53
- },
54
- params?.stream
55
- );
56
- return fromPino(logger);
57
- }
58
- LoggerType2.create = create;
59
- function is(x) {
60
- return "_pino" in x;
61
- }
62
- LoggerType2.is = is;
63
- })(LoggerType || (LoggerType = {}));
64
- var createInstance = (params) => Effect.gen(function* () {
65
- const isDev = Option.getOrNull(
66
- yield* Config.boolean("DEV").pipe(Config.option)
67
- );
68
- const logFile = Option.getOrNull(
69
- yield* Config.boolean("LOGGER_LOGFILE").pipe(Config.option)
70
- );
71
- return LoggerType.create({
72
- ...params,
73
- ...isDev && {
74
- stream: logFile ? pino.transport({
75
- target: "pino/file",
76
- options: {
77
- destination: "./logs/server.log",
78
- mkdir: true
79
- }
80
- }) : pino.transport({
81
- target: "pino-pretty",
82
- options: {
83
- ignore: "pid,hostname"
84
- }
85
- })
86
- }
87
- });
88
- });
9
+ import { Effect, FiberSet } from "effect";
89
10
  function extractParams(...[obj, msg]) {
90
11
  if (typeof obj === "string") {
91
12
  return { message: obj };
92
13
  }
93
14
  return { message: msg, attributes: obj };
94
15
  }
95
- function callPino({
96
- annotations,
97
- message
98
- }, call) {
99
- const entries = HashMap.toEntries(annotations);
100
- if (entries.length > 0) {
101
- return call(Object.fromEntries(entries), String(message));
102
- }
103
- return call(String(message));
104
- }
105
- var PinoCtx;
106
- ((PinoCtx2) => {
107
- const tag = "ff-serv/Pino";
108
- function is(obj) {
109
- return typeof obj === "object" && obj != null && "_tag" in obj && obj._tag === tag;
110
- }
111
- PinoCtx2.is = is;
112
- function create(pino2) {
113
- return {
114
- _tag: tag,
115
- pino: pino2,
116
- effectLogger: EffectLogger.make(({ logLevel, ...input }) => {
117
- switch (logLevel) {
118
- case LogLevel.Info:
119
- return callPino(input, pino2.info);
120
- case LogLevel.Debug:
121
- return callPino(input, pino2.debug);
122
- case LogLevel.Warning:
123
- return callPino(input, pino2.warn);
124
- case LogLevel.Error:
125
- case LogLevel.Fatal:
126
- return callPino(input, pino2.error);
127
- default:
128
- return callPino(input, pino2.info);
129
- }
130
- })
131
- };
132
- }
133
- PinoCtx2.create = create;
134
- })(PinoCtx || (PinoCtx = {}));
135
- var Pino = class extends Context.Tag("ff-serv/Pino")() {
136
- };
137
16
  var Logger;
138
17
  ((Logger2) => {
139
- Logger2.layer = (opts) => EffectLogger.replaceEffect(
140
- EffectLogger.defaultLogger,
141
- Effect.gen(function* () {
142
- return (yield* Pino).effectLogger;
143
- })
144
- ).pipe(
145
- Layer.provideMerge(
146
- Layer.effect(
147
- Pino,
148
- Effect.gen(function* () {
149
- return PinoCtx.create(yield* createInstance(opts));
150
- })
151
- )
152
- )
153
- );
154
18
  Logger2.sync = () => Effect.gen(function* () {
155
- const pino2 = yield* Pino;
156
- const runtime = ManagedRuntime.make(
157
- EffectLogger.replace(EffectLogger.defaultLogger, pino2.effectLogger)
158
- );
19
+ const runPromise = yield* FiberSet.makeRuntimePromise();
20
+ const run = (e) => {
21
+ void runPromise(e);
22
+ };
159
23
  return {
160
- info: (...params) => Logger2.info(...params).pipe((e) => runtime.runSync(e)),
161
- debug: (...params) => Logger2.debug(...params).pipe((e) => runtime.runSync(e)),
162
- warn: (...params) => Logger2.warn(...params).pipe((e) => runtime.runSync(e)),
163
- error: (...params) => Logger2.error(...params).pipe((e) => runtime.runSync(e))
24
+ info: (...params) => run(Logger2.info(...params)),
25
+ debug: (...params) => run(Logger2.debug(...params)),
26
+ warn: (...params) => run(Logger2.warn(...params)),
27
+ error: (...params) => run(Logger2.error(...params))
164
28
  };
165
29
  });
166
- Logger2.get = () => Logger2.sync();
167
- Logger2.replace = (logger) => (e) => Effect.gen(function* () {
168
- const oldPinoCtx = yield* Pino;
169
- const pino2 = LoggerType.is(logger) ? logger : LoggerType.fromPino(logger);
170
- const pinoCtx = PinoCtx.create(pino2);
171
- return yield* Effect.provide(
172
- e,
173
- Layer.mergeAll(
174
- EffectLogger.replace(oldPinoCtx.effectLogger, pinoCtx.effectLogger),
175
- Layer.succeed(Pino, pinoCtx)
176
- )
177
- );
178
- });
179
- Logger2.replaceChild = (...params) => (e) => Effect.gen(function* () {
180
- const oldPinoCtx = yield* Pino;
181
- const pino2 = oldPinoCtx.pino.child(...params);
182
- const pinoCtx = PinoCtx.create(pino2);
183
- return yield* Effect.provide(
184
- Effect.provide(
185
- e,
186
- EffectLogger.replace(oldPinoCtx.effectLogger, pinoCtx.effectLogger)
187
- ),
188
- Layer.succeed(Pino, pinoCtx)
189
- );
190
- });
191
30
  Logger2.info = (...params) => Effect.gen(function* () {
192
31
  const { message, attributes } = extractParams(...params);
193
32
  yield* Effect.logInfo(message).pipe(
@@ -212,7 +51,6 @@ var Logger;
212
51
  attributes ? Effect.annotateLogs(attributes) : (e) => e
213
52
  );
214
53
  });
215
- Logger2.flush = (..._params) => Effect.void;
216
54
  })(Logger || (Logger = {}));
217
55
 
218
56
  // src/http/fetch-handler.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/http/orpc.ts","../../src/http/fetch-handler.ts","../../src/logger.ts"],"sourcesContent":["import type { Context } from '@orpc/server';\nimport type { FetchHandler } from '@orpc/server/fetch';\nimport type { FriendlyStandardHandleOptions } from '@orpc/server/standard';\nimport { Effect } from 'effect';\nimport { Handler } from './fetch-handler.js';\n\ntype MaybeOptionalOptions<TOptions> =\n\tRecord<never, never> extends TOptions\n\t\t? [options?: TOptions]\n\t\t: [options: TOptions];\n\ntype PossibleOpt<T extends Context, E, R> =\n\t| FriendlyStandardHandleOptions<T>\n\t| Effect.Effect<FriendlyStandardHandleOptions<T>, E, R>;\n\nfunction getValue<T extends Context, E, R>(opt: PossibleOpt<T, E, R>) {\n\treturn Effect.isEffect(opt) ? opt : Effect.succeed(opt);\n}\n\nexport function oRPCHandler<T extends Context, E, R>(\n\thandler: FetchHandler<T>,\n\topt?: PossibleOpt<T, E, R> | ((request: Request) => PossibleOpt<T, E, R>),\n) {\n\treturn new Handler('oRPCHandler', ({ request }) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst _opt = (\n\t\t\t\topt\n\t\t\t\t\t? [yield* getValue(typeof opt === 'function' ? opt(request) : opt)]\n\t\t\t\t\t: []\n\t\t\t) as MaybeOptionalOptions<FriendlyStandardHandleOptions<T>>;\n\t\t\treturn yield* Effect.tryPromise(() => handler.handle(request, ..._opt));\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"],"mappings":"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","names":["Effect","Effect","LoggerType","PinoCtx","pino","Logger","Effect"]}
1
+ {"version":3,"sources":["../../src/http/orpc.ts","../../src/http/fetch-handler.ts","../../src/logger.ts"],"sourcesContent":["import type { Context } from '@orpc/server';\nimport type { FetchHandler } from '@orpc/server/fetch';\nimport type { FriendlyStandardHandleOptions } from '@orpc/server/standard';\nimport { Effect } from 'effect';\nimport { Handler } from './fetch-handler.js';\n\ntype MaybeOptionalOptions<TOptions> =\n\tRecord<never, never> extends TOptions\n\t\t? [options?: TOptions]\n\t\t: [options: TOptions];\n\ntype PossibleOpt<T extends Context, E, R> =\n\t| FriendlyStandardHandleOptions<T>\n\t| Effect.Effect<FriendlyStandardHandleOptions<T>, E, R>;\n\nfunction getValue<T extends Context, E, R>(opt: PossibleOpt<T, E, R>) {\n\treturn Effect.isEffect(opt) ? opt : Effect.succeed(opt);\n}\n\nexport function oRPCHandler<T extends Context, E, R>(\n\thandler: FetchHandler<T>,\n\topt?: PossibleOpt<T, E, R> | ((request: Request) => PossibleOpt<T, E, R>),\n) {\n\treturn new Handler('oRPCHandler', ({ request }) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst _opt = (\n\t\t\t\topt\n\t\t\t\t\t? [yield* getValue(typeof opt === 'function' ? opt(request) : opt)]\n\t\t\t\t\t: []\n\t\t\t) as MaybeOptionalOptions<FriendlyStandardHandleOptions<T>>;\n\t\t\treturn yield* Effect.tryPromise(() => handler.handle(request, ..._opt));\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 { Effect, FiberSet } from 'effect';\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\nexport namespace Logger {\n\texport const sync = () =>\n\t\tEffect.gen(function* () {\n\t\t\tconst runPromise = yield* FiberSet.makeRuntimePromise();\n\n\t\t\tconst run = (e: Effect.Effect<void, never, never>) => {\n\t\t\t\t// Intentionally ignoring the await here\n\t\t\t\tvoid runPromise(e);\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\tinfo: (...params: Parameters<typeof Logger.info>) =>\n\t\t\t\t\trun(Logger.info(...params)),\n\t\t\t\tdebug: (...params: Parameters<typeof Logger.debug>) =>\n\t\t\t\t\trun(Logger.debug(...params)),\n\t\t\t\twarn: (...params: Parameters<typeof Logger.warn>) =>\n\t\t\t\t\trun(Logger.warn(...params)),\n\t\t\t\terror: (...params: Parameters<typeof Logger.error>) =>\n\t\t\t\t\trun(Logger.error(...params)),\n\t\t\t};\n\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"],"mappings":";AAGA,SAAS,UAAAA,eAAc;;;ACHvB,SAAS,UAAAC,SAAQ,YAAAC,iBAAgB;AAEjC,SAAS,cAAc;;;ACFvB,SAAS,QAAQ,gBAAgB;AAGjC,SAAS,iBAAiB,CAAC,KAAK,GAAG,GAAc;AAChD,MAAI,OAAO,QAAQ,UAAU;AAC5B,WAAO,EAAE,SAAS,IAAI;AAAA,EACvB;AACA,SAAO,EAAE,SAAS,KAAK,YAAY,IAA2B;AAC/D;AAEO,IAAU;AAAA,CAAV,CAAUC,YAAV;AACC,EAAMA,QAAA,OAAO,MACnB,OAAO,IAAI,aAAa;AACvB,UAAM,aAAa,OAAO,SAAS,mBAAmB;AAEtD,UAAM,MAAM,CAAC,MAAyC;AAErD,WAAK,WAAW,CAAC;AAAA,IAClB;AAEA,WAAO;AAAA,MACN,MAAM,IAAI,WACT,IAAIA,QAAO,KAAK,GAAG,MAAM,CAAC;AAAA,MAC3B,OAAO,IAAI,WACV,IAAIA,QAAO,MAAM,GAAG,MAAM,CAAC;AAAA,MAC5B,MAAM,IAAI,WACT,IAAIA,QAAO,KAAK,GAAG,MAAM,CAAC;AAAA,MAC3B,OAAO,IAAI,WACV,IAAIA,QAAO,MAAM,GAAG,MAAM,CAAC;AAAA,IAC7B;AAAA,EACD,CAAC;AAIK,EAAMA,QAAA,OAAO,IAAI,WACvB,OAAO,IAAI,aAAa;AACvB,UAAM,EAAE,SAAS,WAAW,IAAI,cAAc,GAAG,MAAM;AACvD,WAAO,OAAO,QAAQ,OAAO,EAAE;AAAA,MAC9B,aAAa,OAAO,aAAa,UAAU,IAAI,CAAC,MAAM;AAAA,IACvD;AAAA,EACD,CAAC;AAEK,EAAMA,QAAA,QAAQ,IAAI,WACxB,OAAO,IAAI,aAAa;AACvB,UAAM,EAAE,SAAS,WAAW,IAAI,cAAc,GAAG,MAAM;AACvD,WAAO,OAAO,SAAS,OAAO,EAAE;AAAA,MAC/B,aAAa,OAAO,aAAa,UAAU,IAAI,CAAC,MAAM;AAAA,IACvD;AAAA,EACD,CAAC;AAEK,EAAMA,QAAA,OAAO,IAAI,WACvB,OAAO,IAAI,aAAa;AACvB,UAAM,EAAE,SAAS,WAAW,IAAI,cAAc,GAAG,MAAM;AACvD,WAAO,OAAO,WAAW,OAAO,EAAE;AAAA,MACjC,aAAa,OAAO,aAAa,UAAU,IAAI,CAAC,MAAM;AAAA,IACvD;AAAA,EACD,CAAC;AAEK,EAAMA,QAAA,QAAQ,IAAI,WACxB,OAAO,IAAI,aAAa;AACvB,UAAM,EAAE,SAAS,WAAW,IAAI,cAAc,GAAG,MAAM;AACvD,WAAO,OAAO,SAAS,OAAO,EAAE;AAAA,MAC/B,aAAa,OAAO,aAAa,UAAU,IAAI,CAAC,MAAM;AAAA,IACvD;AAAA,EACD,CAAC;AAAA,GAtDc;;;ADSV,IAAM,UAAN,MAAsC;AAAA,EAC5C,YACU,MACA,QAIR;AALQ;AACA;AAAA,EAIP;AACJ;;;ADZA,SAAS,SAAkC,KAA2B;AACrE,SAAOC,QAAO,SAAS,GAAG,IAAI,MAAMA,QAAO,QAAQ,GAAG;AACvD;AAEO,SAAS,YACf,SACA,KACC;AACD,SAAO,IAAI;AAAA,IAAQ;AAAA,IAAe,CAAC,EAAE,QAAQ,MAC5CA,QAAO,IAAI,aAAa;AACvB,YAAM,OACL,MACG,CAAC,OAAO,SAAS,OAAO,QAAQ,aAAa,IAAI,OAAO,IAAI,GAAG,CAAC,IAChE,CAAC;AAEL,aAAO,OAAOA,QAAO,WAAW,MAAM,QAAQ,OAAO,SAAS,GAAG,IAAI,CAAC;AAAA,IACvE,CAAC;AAAA,EACF;AACD;","names":["Effect","Effect","FiberSet","Logger","Effect"]}
@@ -27,6 +27,6 @@ declare const createFetchHandler: <const HANDLERS extends [Handler<string, unkno
27
27
  onError?: (ctx: {
28
28
  error: Cause<unknown>;
29
29
  }) => Effect.Effect<unknown, unknown>;
30
- }) => Effect.Effect<(request: Request) => Promise<Response>, never, R | effect_Scope.Scope>;
30
+ }) => Effect.Effect<(request: Request) => Promise<Response>, never, effect_Scope.Scope | R>;
31
31
 
32
32
  export { type AnyResponse as A, Handler as H, createFetchHandler as c };
@@ -27,6 +27,6 @@ declare const createFetchHandler: <const HANDLERS extends [Handler<string, unkno
27
27
  onError?: (ctx: {
28
28
  error: Cause<unknown>;
29
29
  }) => Effect.Effect<unknown, unknown>;
30
- }) => Effect.Effect<(request: Request) => Promise<Response>, never, R | effect_Scope.Scope>;
30
+ }) => Effect.Effect<(request: Request) => Promise<Response>, never, effect_Scope.Scope | R>;
31
31
 
32
32
  export { type AnyResponse as A, Handler as H, createFetchHandler as c };