@fonderie/adapter-koa 1.0.2 → 2.0.0

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,45 @@
1
+ <!-- GENERATED — do not edit. Regenerate with: npm run docs:signatures -->
2
+
3
+ # @fonderie/adapter-koa — signatures
4
+
5
+ ## @fonderie/adapter-koa
6
+
7
+ ```ts
8
+ function koaContextToWeb(ctx: KoaContext): Request
9
+
10
+ function webResponseToKoa(webRes: Response, ctx: KoaContext): Promise<void>
11
+
12
+ function bridge(fonderie: FonderieApp): KoaMiddleware<any, any>
13
+
14
+ function adapt(middleware: Middleware): KoaMiddleware<any, any>
15
+
16
+ function withWorkspace(store: IStoreAdapter): KoaMiddleware<any, any>
17
+
18
+ function requirePermission(operation: Operation, permissionKey: string): KoaMiddleware<any, any>
19
+
20
+ function requireFeature(key: string): KoaMiddleware<any, any>
21
+
22
+ function mount(app: Application<DefaultState, DefaultContext>, fonderie: FonderieApp): Application<DefaultState, DefaultContext>
23
+
24
+ const OPERATIONS: { readonly CREATE: "create"; readonly READ: "read"; readonly UPDATE: "update"; readonly DELETE: "delete"; }
25
+
26
+ interface KoaContext {
27
+ request: {
28
+ url: string;
29
+ method: string;
30
+ rawBody?: string;
31
+ headers: Record<string, string | string[] | undefined>;
32
+ };
33
+ response: {
34
+ body: unknown;
35
+ status: number;
36
+ set(key: string, value: string | string[]): void;
37
+ };
38
+ req: IncomingMessage;
39
+ state: Record<string, unknown>;
40
+ }
41
+
42
+ type KoaNext = () => Promise<void>;
43
+
44
+ function requireAuth(context: any, next: Next): any
45
+ ```
package/dist/index.cjs CHANGED
@@ -83,7 +83,11 @@ function koaContextToWeb(ctx) {
83
83
  }
84
84
  async function webResponseToKoa(webRes, ctx) {
85
85
  ctx.response.status = webRes.status;
86
- webRes.headers.forEach((value, key) => ctx.response.set(key, value));
86
+ const setCookies = webRes.headers.getSetCookie?.() ?? [];
87
+ if (setCookies.length) ctx.response.set("Set-Cookie", setCookies);
88
+ webRes.headers.forEach((value, key) => {
89
+ if (key.toLowerCase() !== "set-cookie") ctx.response.set(key, value);
90
+ });
87
91
  ctx.response.body = await webRes.text();
88
92
  }
89
93
  function bridge(fonderie) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { IncomingMessage } from 'node:http';\nimport type Koa from 'koa';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype KoaMiddleware<S = any, C = any> = Koa.Middleware<S, C>;\n\nimport type { FonderieApp, IFonderieContext, Middleware } from '@fonderie/core';\nimport { requireAuth as _requireAuth, resolveClientIp } from '@fonderie/core/middlewares';\n// Optional peers: type-only imports (erased at runtime). The guard factories\n// below load them lazily so installing this adapter never requires\n// @fonderie/workspaces, @fonderie/permissions, or @fonderie/billing unless\n// the corresponding guard is actually used.\nimport type { withWorkspace as _withWorkspace } from '@fonderie/workspaces';\nimport type { requirePermission as _requirePermission } from '@fonderie/permissions';\n\nexport { OPERATIONS } from '@fonderie/core';\n\nasync function loadOptionalPeer<T>(load: () => Promise<T>, pkg: string, api: string): Promise<T> {\n\ttry {\n\t\treturn await load();\n\t} catch (err) {\n\t\tconst e = err as { code?: string; message?: string } | undefined;\n\t\tconst notFound = e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND';\n\t\t// Only claim the peer is missing when the unresolved specifier IS the\n\t\t// peer — a transitive failure inside an installed peer must surface\n\t\t// as-is, not as a misleading install hint.\n\t\tconst missing = notFound ? /Cannot find (?:package|module) '([^']+)'/.exec(e?.message ?? '')?.[1] : undefined;\n\t\tif (missing === pkg || missing?.startsWith(pkg + '/')) {\n\t\t\tthrow new Error(\n\t\t\t\t`[fonderie] ${api} requires the optional peer dependency \"${pkg}\". Install it: npm install ${pkg}`,\n\t\t\t);\n\t\t}\n\t\tthrow err;\n\t}\n}\n\n// Minimal Koa shape used internally for Web Standard translation.\n// Application code uses Koa's own context types (Koa.ParameterizedContext).\nexport interface KoaContext {\n\trequest: {\n\t\turl: string;\n\t\tmethod: string;\n\t\trawBody?: string;\n\t\theaders: Record<string, string | string[] | undefined>;\n\t};\n\tresponse: {\n\t\tbody: unknown;\n\t\tstatus: number;\n\t\tset(key: string, value: string): void;\n\t};\n\treq: IncomingMessage;\n\tstate: Record<string, unknown>;\n}\n\nexport type KoaNext = () => Promise<void>;\n\n// ── Web Standard ↔ Koa translation ───────────────────────────────\n\nexport function koaContextToWeb(ctx: KoaContext): Request {\n\tconst encrypted = (ctx.req.socket as { encrypted?: boolean }).encrypted;\n\tconst protocol = encrypted ? 'https' : 'http';\n\tconst host = ctx.request.headers['host'] ?? 'localhost';\n\tconst url = `${protocol}://${host}${ctx.request.url}`;\n\n\tconst headers = new Headers();\n\tfor (const [key, value] of Object.entries(ctx.request.headers)) {\n\t\tif (!value) continue;\n\t\tif (Array.isArray(value)) {\n\t\t\tfor (const v of value) headers.append(key, v);\n\t\t} else {\n\t\t\theaders.set(key, value);\n\t\t}\n\t}\n\n\tconst method = ctx.request.method.toUpperCase();\n\tconst hasBody = method !== 'GET' && method !== 'HEAD';\n\n\treturn new Request(url, {\n\t\theaders,\n\t\tmethod,\n\t\tbody: hasBody ? (ctx.request.rawBody ?? null) : null,\n\t});\n}\n\nexport async function webResponseToKoa(webRes: Response, ctx: KoaContext): Promise<void> {\n\tctx.response.status = webRes.status;\n\twebRes.headers.forEach((value, key) => ctx.response.set(key, value));\n\tctx.response.body = await webRes.text();\n}\n\n// ── bridge ────────────────────────────────────────────────────────\n//\n// Koa middleware. Populates ctx.state._fonderie with the fonderie context\n// (user, workspace, meta) for all subsequent route handlers.\n// Requires koa-bodyparser (or equivalent) to run first so rawBody is set.\n//\n// app.use(bodyParser())\n// app.use(bridge(fonderie))\n\nexport function bridge(fonderie: FonderieApp): KoaMiddleware {\n\treturn async (ctx, next) => {\n\t\tconst webReq = koaContextToWeb(ctx as unknown as KoaContext);\n\t\tconst fCtx = await fonderie.buildContext(webReq.clone());\n\t\tconst clientIp = resolveClientIp(\n\t\t\t(ctx as unknown as KoaContext).req.socket?.remoteAddress ?? undefined,\n\t\t\twebReq.headers,\n\t\t);\n\t\tif (clientIp) fCtx.meta.clientIp = clientIp;\n\t\tctx.state['_fonderie'] = fCtx;\n\t\tawait next();\n\t};\n}\n\n// ── adapt ─────────────────────────────────────────────────────────\n//\n// Low-level escape hatch — wraps any fonderie Middleware into a Koa\n// middleware function. Use this for custom fonderie middleware; prefer the\n// named exports below for the built-in fonderie guards.\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function adapt(middleware: Middleware): KoaMiddleware<any, any> {\n\treturn async (ctx, next) => {\n\t\tconst fCtx = (ctx.state as Record<string, unknown>)['_fonderie'] as\n\t\t\t| IFonderieContext\n\t\t\t| undefined;\n\t\tif (!fCtx) throw new Error('[fonderie] bridge() must be registered before adapt()');\n\n\t\tlet continued = false;\n\t\tconst result = await middleware(fCtx, async () => {\n\t\t\tcontinued = true;\n\t\t\treturn new Response();\n\t\t});\n\n\t\tif (continued) {\n\t\t\tawait next();\n\t\t} else {\n\t\t\tawait webResponseToKoa(result, ctx as unknown as KoaContext);\n\t\t}\n\t};\n}\n\n// ── Pre-adapted middleware ────────────────────────────────────────\n//\n// Drop-in replacements for the fonderie middleware functions — no adapt()\n// needed. Import directly from this package instead of from the source\n// packages, and use them as native Koa middleware.\n//\n// router.get('/jobs', requireAuth, withWorkspace(store), ...)\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const requireAuth: KoaMiddleware<any, any> = adapt(_requireAuth);\n\n// The three guards below wrap OPTIONAL peers, so the peer is imported lazily\n// on first request — not at module load. Koa middleware is async either way,\n// so the extra await changes nothing for callers.\n\nexport function withWorkspace(\n\tstore: Parameters<typeof _withWorkspace>[0],\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n): KoaMiddleware<any, any> {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tlet inner: KoaMiddleware<any, any> | undefined;\n\treturn async (ctx, next) => {\n\t\tif (!inner) {\n\t\t\tconst mod = await loadOptionalPeer(\n\t\t\t\t() => import('@fonderie/workspaces'),\n\t\t\t\t'@fonderie/workspaces',\n\t\t\t\t'withWorkspace()',\n\t\t\t);\n\t\t\tinner = adapt(mod.withWorkspace(store));\n\t\t}\n\t\treturn inner(ctx, next);\n\t};\n}\n\nexport function requirePermission(\n\toperation: Parameters<typeof _requirePermission>[0],\n\tpermissionKey: Parameters<typeof _requirePermission>[1],\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n): KoaMiddleware<any, any> {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tlet inner: KoaMiddleware<any, any> | undefined;\n\treturn async (ctx, next) => {\n\t\tif (!inner) {\n\t\t\tconst mod = await loadOptionalPeer(\n\t\t\t\t() => import('@fonderie/permissions'),\n\t\t\t\t'@fonderie/permissions',\n\t\t\t\t'requirePermission()',\n\t\t\t);\n\t\t\tinner = adapt(mod.requirePermission(operation, permissionKey));\n\t\t}\n\t\treturn inner(ctx, next);\n\t};\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function requireFeature(key: string): KoaMiddleware<any, any> {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tlet inner: KoaMiddleware<any, any> | undefined;\n\treturn async (ctx, next) => {\n\t\tif (!inner) {\n\t\t\tconst mod = await loadOptionalPeer(\n\t\t\t\t() => import('@fonderie/billing'),\n\t\t\t\t'@fonderie/billing',\n\t\t\t\t'requireFeature()',\n\t\t\t);\n\t\t\tinner = adapt(mod.requireFeature(key));\n\t\t}\n\t\treturn inner(ctx, next);\n\t};\n}\n\n// ── mount ─────────────────────────────────────────────────────────\n//\n// Wires up fonderie to a Koa app. Uses Koa's onion model to register a\n// single wrap-around middleware: builds fonderie context, calls next()\n// so user routes run, then falls back to fonderie infra only if the\n// request was not handled (ctx.body is still undefined).\n//\n// Routes registered after mount() are included automatically — Koa\n// composes all middlewares lazily at request time, not at registration.\n//\n// app.use(bodyParser())\n// const api = mount(app, fonderie) // returns same app\n// api.use(router.routes())\n// api.use(router.allowedMethods())\n// app.listen(port)\n\nexport function mount(app: Koa, fonderie: FonderieApp): Koa {\n\tapp.use(async (ctx, next) => {\n\t\tconst webReq = koaContextToWeb(ctx as unknown as KoaContext);\n\t\tconst fCtx = await fonderie.buildContext(webReq.clone());\n\t\tconst clientIp = resolveClientIp(\n\t\t\t(ctx as unknown as KoaContext).req.socket?.remoteAddress ?? undefined,\n\t\t\twebReq.headers,\n\t\t);\n\t\tif (clientIp) fCtx.meta.clientIp = clientIp;\n\t\tctx.state['_fonderie'] = fCtx;\n\t\tawait next();\n\t\tif (ctx.body === undefined) {\n\t\t\tconst webRes = await fonderie.handle(webReq);\n\t\t\tawait webResponseToKoa(webRes, ctx as unknown as KoaContext);\n\t\t}\n\t});\n\treturn app;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,yBAA6D;AAQ7D,kBAA2B;AAE3B,eAAe,iBAAoB,MAAwB,KAAa,KAAyB;AAChG,MAAI;AACH,WAAO,MAAM,KAAK;AAAA,EACnB,SAAS,KAAK;AACb,UAAM,IAAI;AACV,UAAM,WAAW,GAAG,SAAS,0BAA0B,GAAG,SAAS;AAInE,UAAM,UAAU,WAAW,2CAA2C,KAAK,GAAG,WAAW,EAAE,IAAI,CAAC,IAAI;AACpG,QAAI,YAAY,OAAO,SAAS,WAAW,MAAM,GAAG,GAAG;AACtD,YAAM,IAAI;AAAA,QACT,cAAc,GAAG,2CAA2C,GAAG,8BAA8B,GAAG;AAAA,MACjG;AAAA,IACD;AACA,UAAM;AAAA,EACP;AACD;AAwBO,SAAS,gBAAgB,KAA0B;AACzD,QAAM,YAAa,IAAI,IAAI,OAAmC;AAC9D,QAAM,WAAW,YAAY,UAAU;AACvC,QAAM,OAAO,IAAI,QAAQ,QAAQ,MAAM,KAAK;AAC5C,QAAM,MAAM,GAAG,QAAQ,MAAM,IAAI,GAAG,IAAI,QAAQ,GAAG;AAEnD,QAAM,UAAU,IAAI,QAAQ;AAC5B,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,QAAQ,OAAO,GAAG;AAC/D,QAAI,CAAC,MAAO;AACZ,QAAI,MAAM,QAAQ,KAAK,GAAG;AACzB,iBAAW,KAAK,MAAO,SAAQ,OAAO,KAAK,CAAC;AAAA,IAC7C,OAAO;AACN,cAAQ,IAAI,KAAK,KAAK;AAAA,IACvB;AAAA,EACD;AAEA,QAAM,SAAS,IAAI,QAAQ,OAAO,YAAY;AAC9C,QAAM,UAAU,WAAW,SAAS,WAAW;AAE/C,SAAO,IAAI,QAAQ,KAAK;AAAA,IACvB;AAAA,IACA;AAAA,IACA,MAAM,UAAW,IAAI,QAAQ,WAAW,OAAQ;AAAA,EACjD,CAAC;AACF;AAEA,eAAsB,iBAAiB,QAAkB,KAAgC;AACxF,MAAI,SAAS,SAAS,OAAO;AAC7B,SAAO,QAAQ,QAAQ,CAAC,OAAO,QAAQ,IAAI,SAAS,IAAI,KAAK,KAAK,CAAC;AACnE,MAAI,SAAS,OAAO,MAAM,OAAO,KAAK;AACvC;AAWO,SAAS,OAAO,UAAsC;AAC5D,SAAO,OAAO,KAAK,SAAS;AAC3B,UAAM,SAAS,gBAAgB,GAA4B;AAC3D,UAAM,OAAO,MAAM,SAAS,aAAa,OAAO,MAAM,CAAC;AACvD,UAAM,eAAW;AAAA,MACf,IAA8B,IAAI,QAAQ,iBAAiB;AAAA,MAC5D,OAAO;AAAA,IACR;AACA,QAAI,SAAU,MAAK,KAAK,WAAW;AACnC,QAAI,MAAM,WAAW,IAAI;AACzB,UAAM,KAAK;AAAA,EACZ;AACD;AASO,SAAS,MAAM,YAAiD;AACtE,SAAO,OAAO,KAAK,SAAS;AAC3B,UAAM,OAAQ,IAAI,MAAkC,WAAW;AAG/D,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,uDAAuD;AAElF,QAAI,YAAY;AAChB,UAAM,SAAS,MAAM,WAAW,MAAM,YAAY;AACjD,kBAAY;AACZ,aAAO,IAAI,SAAS;AAAA,IACrB,CAAC;AAED,QAAI,WAAW;AACd,YAAM,KAAK;AAAA,IACZ,OAAO;AACN,YAAM,iBAAiB,QAAQ,GAA4B;AAAA,IAC5D;AAAA,EACD;AACD;AAWO,IAAM,cAAuC,MAAM,mBAAAA,WAAY;AAM/D,SAAS,cACf,OAE0B;AAE1B,MAAI;AACJ,SAAO,OAAO,KAAK,SAAS;AAC3B,QAAI,CAAC,OAAO;AACX,YAAM,MAAM,MAAM;AAAA,QACjB,MAAM,OAAO,sBAAsB;AAAA,QACnC;AAAA,QACA;AAAA,MACD;AACA,cAAQ,MAAM,IAAI,cAAc,KAAK,CAAC;AAAA,IACvC;AACA,WAAO,MAAM,KAAK,IAAI;AAAA,EACvB;AACD;AAEO,SAAS,kBACf,WACA,eAE0B;AAE1B,MAAI;AACJ,SAAO,OAAO,KAAK,SAAS;AAC3B,QAAI,CAAC,OAAO;AACX,YAAM,MAAM,MAAM;AAAA,QACjB,MAAM,OAAO,uBAAuB;AAAA,QACpC;AAAA,QACA;AAAA,MACD;AACA,cAAQ,MAAM,IAAI,kBAAkB,WAAW,aAAa,CAAC;AAAA,IAC9D;AACA,WAAO,MAAM,KAAK,IAAI;AAAA,EACvB;AACD;AAGO,SAAS,eAAe,KAAsC;AAEpE,MAAI;AACJ,SAAO,OAAO,KAAK,SAAS;AAC3B,QAAI,CAAC,OAAO;AACX,YAAM,MAAM,MAAM;AAAA,QACjB,MAAM,OAAO,mBAAmB;AAAA,QAChC;AAAA,QACA;AAAA,MACD;AACA,cAAQ,MAAM,IAAI,eAAe,GAAG,CAAC;AAAA,IACtC;AACA,WAAO,MAAM,KAAK,IAAI;AAAA,EACvB;AACD;AAkBO,SAAS,MAAM,KAAU,UAA4B;AAC3D,MAAI,IAAI,OAAO,KAAK,SAAS;AAC5B,UAAM,SAAS,gBAAgB,GAA4B;AAC3D,UAAM,OAAO,MAAM,SAAS,aAAa,OAAO,MAAM,CAAC;AACvD,UAAM,eAAW;AAAA,MACf,IAA8B,IAAI,QAAQ,iBAAiB;AAAA,MAC5D,OAAO;AAAA,IACR;AACA,QAAI,SAAU,MAAK,KAAK,WAAW;AACnC,QAAI,MAAM,WAAW,IAAI;AACzB,UAAM,KAAK;AACX,QAAI,IAAI,SAAS,QAAW;AAC3B,YAAM,SAAS,MAAM,SAAS,OAAO,MAAM;AAC3C,YAAM,iBAAiB,QAAQ,GAA4B;AAAA,IAC5D;AAAA,EACD,CAAC;AACD,SAAO;AACR;","names":["_requireAuth"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { IncomingMessage } from 'node:http';\nimport type Koa from 'koa';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype KoaMiddleware<S = any, C = any> = Koa.Middleware<S, C>;\n\nimport type { FonderieApp, IFonderieContext, Middleware } from '@fonderie/core';\nimport { requireAuth as _requireAuth, resolveClientIp } from '@fonderie/core/middlewares';\n// Optional peers: type-only imports (erased at runtime). The guard factories\n// below load them lazily so installing this adapter never requires\n// @fonderie/workspaces, @fonderie/permissions, or @fonderie/billing unless\n// the corresponding guard is actually used.\nimport type { withWorkspace as _withWorkspace } from '@fonderie/workspaces';\nimport type { requirePermission as _requirePermission } from '@fonderie/permissions';\n\nexport { OPERATIONS } from '@fonderie/core';\n\nasync function loadOptionalPeer<T>(load: () => Promise<T>, pkg: string, api: string): Promise<T> {\n\ttry {\n\t\treturn await load();\n\t} catch (err) {\n\t\tconst e = err as { code?: string; message?: string } | undefined;\n\t\tconst notFound = e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND';\n\t\t// Only claim the peer is missing when the unresolved specifier IS the\n\t\t// peer — a transitive failure inside an installed peer must surface\n\t\t// as-is, not as a misleading install hint.\n\t\tconst missing = notFound ? /Cannot find (?:package|module) '([^']+)'/.exec(e?.message ?? '')?.[1] : undefined;\n\t\tif (missing === pkg || missing?.startsWith(pkg + '/')) {\n\t\t\tthrow new Error(\n\t\t\t\t`[fonderie] ${api} requires the optional peer dependency \"${pkg}\". Install it: npm install ${pkg}`,\n\t\t\t);\n\t\t}\n\t\tthrow err;\n\t}\n}\n\n// Minimal Koa shape used internally for Web Standard translation.\n// Application code uses Koa's own context types (Koa.ParameterizedContext).\nexport interface KoaContext {\n\trequest: {\n\t\turl: string;\n\t\tmethod: string;\n\t\trawBody?: string;\n\t\theaders: Record<string, string | string[] | undefined>;\n\t};\n\tresponse: {\n\t\tbody: unknown;\n\t\tstatus: number;\n\t\tset(key: string, value: string | string[]): void;\n\t};\n\treq: IncomingMessage;\n\tstate: Record<string, unknown>;\n}\n\nexport type KoaNext = () => Promise<void>;\n\n// ── Web Standard ↔ Koa translation ───────────────────────────────\n\nexport function koaContextToWeb(ctx: KoaContext): Request {\n\tconst encrypted = (ctx.req.socket as { encrypted?: boolean }).encrypted;\n\tconst protocol = encrypted ? 'https' : 'http';\n\tconst host = ctx.request.headers['host'] ?? 'localhost';\n\tconst url = `${protocol}://${host}${ctx.request.url}`;\n\n\tconst headers = new Headers();\n\tfor (const [key, value] of Object.entries(ctx.request.headers)) {\n\t\tif (!value) continue;\n\t\tif (Array.isArray(value)) {\n\t\t\tfor (const v of value) headers.append(key, v);\n\t\t} else {\n\t\t\theaders.set(key, value);\n\t\t}\n\t}\n\n\tconst method = ctx.request.method.toUpperCase();\n\tconst hasBody = method !== 'GET' && method !== 'HEAD';\n\n\treturn new Request(url, {\n\t\theaders,\n\t\tmethod,\n\t\tbody: hasBody ? (ctx.request.rawBody ?? null) : null,\n\t});\n}\n\nexport async function webResponseToKoa(webRes: Response, ctx: KoaContext): Promise<void> {\n\tctx.response.status = webRes.status;\n\t// Set-Cookie must be forwarded as a LIST — forEach + set() would overwrite all\n\t// but the last cookie (and joining them into one header is invalid).\n\tconst setCookies = webRes.headers.getSetCookie?.() ?? [];\n\tif (setCookies.length) ctx.response.set('Set-Cookie', setCookies);\n\twebRes.headers.forEach((value, key) => {\n\t\tif (key.toLowerCase() !== 'set-cookie') ctx.response.set(key, value);\n\t});\n\tctx.response.body = await webRes.text();\n}\n\n// ── bridge ────────────────────────────────────────────────────────\n//\n// Koa middleware. Populates ctx.state._fonderie with the fonderie context\n// (user, workspace, meta) for all subsequent route handlers.\n// Requires koa-bodyparser (or equivalent) to run first so rawBody is set.\n//\n// app.use(bodyParser())\n// app.use(bridge(fonderie))\n\nexport function bridge(fonderie: FonderieApp): KoaMiddleware {\n\treturn async (ctx, next) => {\n\t\tconst webReq = koaContextToWeb(ctx as unknown as KoaContext);\n\t\tconst fCtx = await fonderie.buildContext(webReq.clone());\n\t\tconst clientIp = resolveClientIp(\n\t\t\t(ctx as unknown as KoaContext).req.socket?.remoteAddress ?? undefined,\n\t\t\twebReq.headers,\n\t\t);\n\t\tif (clientIp) fCtx.meta.clientIp = clientIp;\n\t\tctx.state['_fonderie'] = fCtx;\n\t\tawait next();\n\t};\n}\n\n// ── adapt ─────────────────────────────────────────────────────────\n//\n// Low-level escape hatch — wraps any fonderie Middleware into a Koa\n// middleware function. Use this for custom fonderie middleware; prefer the\n// named exports below for the built-in fonderie guards.\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function adapt(middleware: Middleware): KoaMiddleware<any, any> {\n\treturn async (ctx, next) => {\n\t\tconst fCtx = (ctx.state as Record<string, unknown>)['_fonderie'] as\n\t\t\t| IFonderieContext\n\t\t\t| undefined;\n\t\tif (!fCtx) throw new Error('[fonderie] bridge() must be registered before adapt()');\n\n\t\tlet continued = false;\n\t\tconst result = await middleware(fCtx, async () => {\n\t\t\tcontinued = true;\n\t\t\treturn new Response();\n\t\t});\n\n\t\tif (continued) {\n\t\t\tawait next();\n\t\t} else {\n\t\t\tawait webResponseToKoa(result, ctx as unknown as KoaContext);\n\t\t}\n\t};\n}\n\n// ── Pre-adapted middleware ────────────────────────────────────────\n//\n// Drop-in replacements for the fonderie middleware functions — no adapt()\n// needed. Import directly from this package instead of from the source\n// packages, and use them as native Koa middleware.\n//\n// router.get('/jobs', requireAuth, withWorkspace(store), ...)\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const requireAuth: KoaMiddleware<any, any> = adapt(_requireAuth);\n\n// The three guards below wrap OPTIONAL peers, so the peer is imported lazily\n// on first request — not at module load. Koa middleware is async either way,\n// so the extra await changes nothing for callers.\n\nexport function withWorkspace(\n\tstore: Parameters<typeof _withWorkspace>[0],\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n): KoaMiddleware<any, any> {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tlet inner: KoaMiddleware<any, any> | undefined;\n\treturn async (ctx, next) => {\n\t\tif (!inner) {\n\t\t\tconst mod = await loadOptionalPeer(\n\t\t\t\t() => import('@fonderie/workspaces'),\n\t\t\t\t'@fonderie/workspaces',\n\t\t\t\t'withWorkspace()',\n\t\t\t);\n\t\t\tinner = adapt(mod.withWorkspace(store));\n\t\t}\n\t\treturn inner(ctx, next);\n\t};\n}\n\nexport function requirePermission(\n\toperation: Parameters<typeof _requirePermission>[0],\n\tpermissionKey: Parameters<typeof _requirePermission>[1],\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n): KoaMiddleware<any, any> {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tlet inner: KoaMiddleware<any, any> | undefined;\n\treturn async (ctx, next) => {\n\t\tif (!inner) {\n\t\t\tconst mod = await loadOptionalPeer(\n\t\t\t\t() => import('@fonderie/permissions'),\n\t\t\t\t'@fonderie/permissions',\n\t\t\t\t'requirePermission()',\n\t\t\t);\n\t\t\tinner = adapt(mod.requirePermission(operation, permissionKey));\n\t\t}\n\t\treturn inner(ctx, next);\n\t};\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function requireFeature(key: string): KoaMiddleware<any, any> {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tlet inner: KoaMiddleware<any, any> | undefined;\n\treturn async (ctx, next) => {\n\t\tif (!inner) {\n\t\t\tconst mod = await loadOptionalPeer(\n\t\t\t\t() => import('@fonderie/billing'),\n\t\t\t\t'@fonderie/billing',\n\t\t\t\t'requireFeature()',\n\t\t\t);\n\t\t\tinner = adapt(mod.requireFeature(key));\n\t\t}\n\t\treturn inner(ctx, next);\n\t};\n}\n\n// ── mount ─────────────────────────────────────────────────────────\n//\n// Wires up fonderie to a Koa app. Uses Koa's onion model to register a\n// single wrap-around middleware: builds fonderie context, calls next()\n// so user routes run, then falls back to fonderie infra only if the\n// request was not handled (ctx.body is still undefined).\n//\n// Routes registered after mount() are included automatically — Koa\n// composes all middlewares lazily at request time, not at registration.\n//\n// app.use(bodyParser())\n// const api = mount(app, fonderie) // returns same app\n// api.use(router.routes())\n// api.use(router.allowedMethods())\n// app.listen(port)\n\nexport function mount(app: Koa, fonderie: FonderieApp): Koa {\n\tapp.use(async (ctx, next) => {\n\t\tconst webReq = koaContextToWeb(ctx as unknown as KoaContext);\n\t\tconst fCtx = await fonderie.buildContext(webReq.clone());\n\t\tconst clientIp = resolveClientIp(\n\t\t\t(ctx as unknown as KoaContext).req.socket?.remoteAddress ?? undefined,\n\t\t\twebReq.headers,\n\t\t);\n\t\tif (clientIp) fCtx.meta.clientIp = clientIp;\n\t\tctx.state['_fonderie'] = fCtx;\n\t\tawait next();\n\t\tif (ctx.body === undefined) {\n\t\t\tconst webRes = await fonderie.handle(webReq);\n\t\t\tawait webResponseToKoa(webRes, ctx as unknown as KoaContext);\n\t\t}\n\t});\n\treturn app;\n}\n"],"mappings":"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","names":["_requireAuth"]}
package/dist/index.d.cts CHANGED
@@ -17,7 +17,7 @@ interface KoaContext {
17
17
  response: {
18
18
  body: unknown;
19
19
  status: number;
20
- set(key: string, value: string): void;
20
+ set(key: string, value: string | string[]): void;
21
21
  };
22
22
  req: IncomingMessage;
23
23
  state: Record<string, unknown>;
package/dist/index.d.ts CHANGED
@@ -17,7 +17,7 @@ interface KoaContext {
17
17
  response: {
18
18
  body: unknown;
19
19
  status: number;
20
- set(key: string, value: string): void;
20
+ set(key: string, value: string | string[]): void;
21
21
  };
22
22
  req: IncomingMessage;
23
23
  state: Record<string, unknown>;
package/dist/index.js CHANGED
@@ -40,7 +40,11 @@ function koaContextToWeb(ctx) {
40
40
  }
41
41
  async function webResponseToKoa(webRes, ctx) {
42
42
  ctx.response.status = webRes.status;
43
- webRes.headers.forEach((value, key) => ctx.response.set(key, value));
43
+ const setCookies = webRes.headers.getSetCookie?.() ?? [];
44
+ if (setCookies.length) ctx.response.set("Set-Cookie", setCookies);
45
+ webRes.headers.forEach((value, key) => {
46
+ if (key.toLowerCase() !== "set-cookie") ctx.response.set(key, value);
47
+ });
44
48
  ctx.response.body = await webRes.text();
45
49
  }
46
50
  function bridge(fonderie) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { IncomingMessage } from 'node:http';\nimport type Koa from 'koa';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype KoaMiddleware<S = any, C = any> = Koa.Middleware<S, C>;\n\nimport type { FonderieApp, IFonderieContext, Middleware } from '@fonderie/core';\nimport { requireAuth as _requireAuth, resolveClientIp } from '@fonderie/core/middlewares';\n// Optional peers: type-only imports (erased at runtime). The guard factories\n// below load them lazily so installing this adapter never requires\n// @fonderie/workspaces, @fonderie/permissions, or @fonderie/billing unless\n// the corresponding guard is actually used.\nimport type { withWorkspace as _withWorkspace } from '@fonderie/workspaces';\nimport type { requirePermission as _requirePermission } from '@fonderie/permissions';\n\nexport { OPERATIONS } from '@fonderie/core';\n\nasync function loadOptionalPeer<T>(load: () => Promise<T>, pkg: string, api: string): Promise<T> {\n\ttry {\n\t\treturn await load();\n\t} catch (err) {\n\t\tconst e = err as { code?: string; message?: string } | undefined;\n\t\tconst notFound = e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND';\n\t\t// Only claim the peer is missing when the unresolved specifier IS the\n\t\t// peer — a transitive failure inside an installed peer must surface\n\t\t// as-is, not as a misleading install hint.\n\t\tconst missing = notFound ? /Cannot find (?:package|module) '([^']+)'/.exec(e?.message ?? '')?.[1] : undefined;\n\t\tif (missing === pkg || missing?.startsWith(pkg + '/')) {\n\t\t\tthrow new Error(\n\t\t\t\t`[fonderie] ${api} requires the optional peer dependency \"${pkg}\". Install it: npm install ${pkg}`,\n\t\t\t);\n\t\t}\n\t\tthrow err;\n\t}\n}\n\n// Minimal Koa shape used internally for Web Standard translation.\n// Application code uses Koa's own context types (Koa.ParameterizedContext).\nexport interface KoaContext {\n\trequest: {\n\t\turl: string;\n\t\tmethod: string;\n\t\trawBody?: string;\n\t\theaders: Record<string, string | string[] | undefined>;\n\t};\n\tresponse: {\n\t\tbody: unknown;\n\t\tstatus: number;\n\t\tset(key: string, value: string): void;\n\t};\n\treq: IncomingMessage;\n\tstate: Record<string, unknown>;\n}\n\nexport type KoaNext = () => Promise<void>;\n\n// ── Web Standard ↔ Koa translation ───────────────────────────────\n\nexport function koaContextToWeb(ctx: KoaContext): Request {\n\tconst encrypted = (ctx.req.socket as { encrypted?: boolean }).encrypted;\n\tconst protocol = encrypted ? 'https' : 'http';\n\tconst host = ctx.request.headers['host'] ?? 'localhost';\n\tconst url = `${protocol}://${host}${ctx.request.url}`;\n\n\tconst headers = new Headers();\n\tfor (const [key, value] of Object.entries(ctx.request.headers)) {\n\t\tif (!value) continue;\n\t\tif (Array.isArray(value)) {\n\t\t\tfor (const v of value) headers.append(key, v);\n\t\t} else {\n\t\t\theaders.set(key, value);\n\t\t}\n\t}\n\n\tconst method = ctx.request.method.toUpperCase();\n\tconst hasBody = method !== 'GET' && method !== 'HEAD';\n\n\treturn new Request(url, {\n\t\theaders,\n\t\tmethod,\n\t\tbody: hasBody ? (ctx.request.rawBody ?? null) : null,\n\t});\n}\n\nexport async function webResponseToKoa(webRes: Response, ctx: KoaContext): Promise<void> {\n\tctx.response.status = webRes.status;\n\twebRes.headers.forEach((value, key) => ctx.response.set(key, value));\n\tctx.response.body = await webRes.text();\n}\n\n// ── bridge ────────────────────────────────────────────────────────\n//\n// Koa middleware. Populates ctx.state._fonderie with the fonderie context\n// (user, workspace, meta) for all subsequent route handlers.\n// Requires koa-bodyparser (or equivalent) to run first so rawBody is set.\n//\n// app.use(bodyParser())\n// app.use(bridge(fonderie))\n\nexport function bridge(fonderie: FonderieApp): KoaMiddleware {\n\treturn async (ctx, next) => {\n\t\tconst webReq = koaContextToWeb(ctx as unknown as KoaContext);\n\t\tconst fCtx = await fonderie.buildContext(webReq.clone());\n\t\tconst clientIp = resolveClientIp(\n\t\t\t(ctx as unknown as KoaContext).req.socket?.remoteAddress ?? undefined,\n\t\t\twebReq.headers,\n\t\t);\n\t\tif (clientIp) fCtx.meta.clientIp = clientIp;\n\t\tctx.state['_fonderie'] = fCtx;\n\t\tawait next();\n\t};\n}\n\n// ── adapt ─────────────────────────────────────────────────────────\n//\n// Low-level escape hatch — wraps any fonderie Middleware into a Koa\n// middleware function. Use this for custom fonderie middleware; prefer the\n// named exports below for the built-in fonderie guards.\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function adapt(middleware: Middleware): KoaMiddleware<any, any> {\n\treturn async (ctx, next) => {\n\t\tconst fCtx = (ctx.state as Record<string, unknown>)['_fonderie'] as\n\t\t\t| IFonderieContext\n\t\t\t| undefined;\n\t\tif (!fCtx) throw new Error('[fonderie] bridge() must be registered before adapt()');\n\n\t\tlet continued = false;\n\t\tconst result = await middleware(fCtx, async () => {\n\t\t\tcontinued = true;\n\t\t\treturn new Response();\n\t\t});\n\n\t\tif (continued) {\n\t\t\tawait next();\n\t\t} else {\n\t\t\tawait webResponseToKoa(result, ctx as unknown as KoaContext);\n\t\t}\n\t};\n}\n\n// ── Pre-adapted middleware ────────────────────────────────────────\n//\n// Drop-in replacements for the fonderie middleware functions — no adapt()\n// needed. Import directly from this package instead of from the source\n// packages, and use them as native Koa middleware.\n//\n// router.get('/jobs', requireAuth, withWorkspace(store), ...)\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const requireAuth: KoaMiddleware<any, any> = adapt(_requireAuth);\n\n// The three guards below wrap OPTIONAL peers, so the peer is imported lazily\n// on first request — not at module load. Koa middleware is async either way,\n// so the extra await changes nothing for callers.\n\nexport function withWorkspace(\n\tstore: Parameters<typeof _withWorkspace>[0],\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n): KoaMiddleware<any, any> {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tlet inner: KoaMiddleware<any, any> | undefined;\n\treturn async (ctx, next) => {\n\t\tif (!inner) {\n\t\t\tconst mod = await loadOptionalPeer(\n\t\t\t\t() => import('@fonderie/workspaces'),\n\t\t\t\t'@fonderie/workspaces',\n\t\t\t\t'withWorkspace()',\n\t\t\t);\n\t\t\tinner = adapt(mod.withWorkspace(store));\n\t\t}\n\t\treturn inner(ctx, next);\n\t};\n}\n\nexport function requirePermission(\n\toperation: Parameters<typeof _requirePermission>[0],\n\tpermissionKey: Parameters<typeof _requirePermission>[1],\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n): KoaMiddleware<any, any> {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tlet inner: KoaMiddleware<any, any> | undefined;\n\treturn async (ctx, next) => {\n\t\tif (!inner) {\n\t\t\tconst mod = await loadOptionalPeer(\n\t\t\t\t() => import('@fonderie/permissions'),\n\t\t\t\t'@fonderie/permissions',\n\t\t\t\t'requirePermission()',\n\t\t\t);\n\t\t\tinner = adapt(mod.requirePermission(operation, permissionKey));\n\t\t}\n\t\treturn inner(ctx, next);\n\t};\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function requireFeature(key: string): KoaMiddleware<any, any> {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tlet inner: KoaMiddleware<any, any> | undefined;\n\treturn async (ctx, next) => {\n\t\tif (!inner) {\n\t\t\tconst mod = await loadOptionalPeer(\n\t\t\t\t() => import('@fonderie/billing'),\n\t\t\t\t'@fonderie/billing',\n\t\t\t\t'requireFeature()',\n\t\t\t);\n\t\t\tinner = adapt(mod.requireFeature(key));\n\t\t}\n\t\treturn inner(ctx, next);\n\t};\n}\n\n// ── mount ─────────────────────────────────────────────────────────\n//\n// Wires up fonderie to a Koa app. Uses Koa's onion model to register a\n// single wrap-around middleware: builds fonderie context, calls next()\n// so user routes run, then falls back to fonderie infra only if the\n// request was not handled (ctx.body is still undefined).\n//\n// Routes registered after mount() are included automatically — Koa\n// composes all middlewares lazily at request time, not at registration.\n//\n// app.use(bodyParser())\n// const api = mount(app, fonderie) // returns same app\n// api.use(router.routes())\n// api.use(router.allowedMethods())\n// app.listen(port)\n\nexport function mount(app: Koa, fonderie: FonderieApp): Koa {\n\tapp.use(async (ctx, next) => {\n\t\tconst webReq = koaContextToWeb(ctx as unknown as KoaContext);\n\t\tconst fCtx = await fonderie.buildContext(webReq.clone());\n\t\tconst clientIp = resolveClientIp(\n\t\t\t(ctx as unknown as KoaContext).req.socket?.remoteAddress ?? undefined,\n\t\t\twebReq.headers,\n\t\t);\n\t\tif (clientIp) fCtx.meta.clientIp = clientIp;\n\t\tctx.state['_fonderie'] = fCtx;\n\t\tawait next();\n\t\tif (ctx.body === undefined) {\n\t\t\tconst webRes = await fonderie.handle(webReq);\n\t\t\tawait webResponseToKoa(webRes, ctx as unknown as KoaContext);\n\t\t}\n\t});\n\treturn app;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { IncomingMessage } from 'node:http';\nimport type Koa from 'koa';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype KoaMiddleware<S = any, C = any> = Koa.Middleware<S, C>;\n\nimport type { FonderieApp, IFonderieContext, Middleware } from '@fonderie/core';\nimport { requireAuth as _requireAuth, resolveClientIp } from '@fonderie/core/middlewares';\n// Optional peers: type-only imports (erased at runtime). The guard factories\n// below load them lazily so installing this adapter never requires\n// @fonderie/workspaces, @fonderie/permissions, or @fonderie/billing unless\n// the corresponding guard is actually used.\nimport type { withWorkspace as _withWorkspace } from '@fonderie/workspaces';\nimport type { requirePermission as _requirePermission } from '@fonderie/permissions';\n\nexport { OPERATIONS } from '@fonderie/core';\n\nasync function loadOptionalPeer<T>(load: () => Promise<T>, pkg: string, api: string): Promise<T> {\n\ttry {\n\t\treturn await load();\n\t} catch (err) {\n\t\tconst e = err as { code?: string; message?: string } | undefined;\n\t\tconst notFound = e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND';\n\t\t// Only claim the peer is missing when the unresolved specifier IS the\n\t\t// peer — a transitive failure inside an installed peer must surface\n\t\t// as-is, not as a misleading install hint.\n\t\tconst missing = notFound ? /Cannot find (?:package|module) '([^']+)'/.exec(e?.message ?? '')?.[1] : undefined;\n\t\tif (missing === pkg || missing?.startsWith(pkg + '/')) {\n\t\t\tthrow new Error(\n\t\t\t\t`[fonderie] ${api} requires the optional peer dependency \"${pkg}\". Install it: npm install ${pkg}`,\n\t\t\t);\n\t\t}\n\t\tthrow err;\n\t}\n}\n\n// Minimal Koa shape used internally for Web Standard translation.\n// Application code uses Koa's own context types (Koa.ParameterizedContext).\nexport interface KoaContext {\n\trequest: {\n\t\turl: string;\n\t\tmethod: string;\n\t\trawBody?: string;\n\t\theaders: Record<string, string | string[] | undefined>;\n\t};\n\tresponse: {\n\t\tbody: unknown;\n\t\tstatus: number;\n\t\tset(key: string, value: string | string[]): void;\n\t};\n\treq: IncomingMessage;\n\tstate: Record<string, unknown>;\n}\n\nexport type KoaNext = () => Promise<void>;\n\n// ── Web Standard ↔ Koa translation ───────────────────────────────\n\nexport function koaContextToWeb(ctx: KoaContext): Request {\n\tconst encrypted = (ctx.req.socket as { encrypted?: boolean }).encrypted;\n\tconst protocol = encrypted ? 'https' : 'http';\n\tconst host = ctx.request.headers['host'] ?? 'localhost';\n\tconst url = `${protocol}://${host}${ctx.request.url}`;\n\n\tconst headers = new Headers();\n\tfor (const [key, value] of Object.entries(ctx.request.headers)) {\n\t\tif (!value) continue;\n\t\tif (Array.isArray(value)) {\n\t\t\tfor (const v of value) headers.append(key, v);\n\t\t} else {\n\t\t\theaders.set(key, value);\n\t\t}\n\t}\n\n\tconst method = ctx.request.method.toUpperCase();\n\tconst hasBody = method !== 'GET' && method !== 'HEAD';\n\n\treturn new Request(url, {\n\t\theaders,\n\t\tmethod,\n\t\tbody: hasBody ? (ctx.request.rawBody ?? null) : null,\n\t});\n}\n\nexport async function webResponseToKoa(webRes: Response, ctx: KoaContext): Promise<void> {\n\tctx.response.status = webRes.status;\n\t// Set-Cookie must be forwarded as a LIST — forEach + set() would overwrite all\n\t// but the last cookie (and joining them into one header is invalid).\n\tconst setCookies = webRes.headers.getSetCookie?.() ?? [];\n\tif (setCookies.length) ctx.response.set('Set-Cookie', setCookies);\n\twebRes.headers.forEach((value, key) => {\n\t\tif (key.toLowerCase() !== 'set-cookie') ctx.response.set(key, value);\n\t});\n\tctx.response.body = await webRes.text();\n}\n\n// ── bridge ────────────────────────────────────────────────────────\n//\n// Koa middleware. Populates ctx.state._fonderie with the fonderie context\n// (user, workspace, meta) for all subsequent route handlers.\n// Requires koa-bodyparser (or equivalent) to run first so rawBody is set.\n//\n// app.use(bodyParser())\n// app.use(bridge(fonderie))\n\nexport function bridge(fonderie: FonderieApp): KoaMiddleware {\n\treturn async (ctx, next) => {\n\t\tconst webReq = koaContextToWeb(ctx as unknown as KoaContext);\n\t\tconst fCtx = await fonderie.buildContext(webReq.clone());\n\t\tconst clientIp = resolveClientIp(\n\t\t\t(ctx as unknown as KoaContext).req.socket?.remoteAddress ?? undefined,\n\t\t\twebReq.headers,\n\t\t);\n\t\tif (clientIp) fCtx.meta.clientIp = clientIp;\n\t\tctx.state['_fonderie'] = fCtx;\n\t\tawait next();\n\t};\n}\n\n// ── adapt ─────────────────────────────────────────────────────────\n//\n// Low-level escape hatch — wraps any fonderie Middleware into a Koa\n// middleware function. Use this for custom fonderie middleware; prefer the\n// named exports below for the built-in fonderie guards.\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function adapt(middleware: Middleware): KoaMiddleware<any, any> {\n\treturn async (ctx, next) => {\n\t\tconst fCtx = (ctx.state as Record<string, unknown>)['_fonderie'] as\n\t\t\t| IFonderieContext\n\t\t\t| undefined;\n\t\tif (!fCtx) throw new Error('[fonderie] bridge() must be registered before adapt()');\n\n\t\tlet continued = false;\n\t\tconst result = await middleware(fCtx, async () => {\n\t\t\tcontinued = true;\n\t\t\treturn new Response();\n\t\t});\n\n\t\tif (continued) {\n\t\t\tawait next();\n\t\t} else {\n\t\t\tawait webResponseToKoa(result, ctx as unknown as KoaContext);\n\t\t}\n\t};\n}\n\n// ── Pre-adapted middleware ────────────────────────────────────────\n//\n// Drop-in replacements for the fonderie middleware functions — no adapt()\n// needed. Import directly from this package instead of from the source\n// packages, and use them as native Koa middleware.\n//\n// router.get('/jobs', requireAuth, withWorkspace(store), ...)\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const requireAuth: KoaMiddleware<any, any> = adapt(_requireAuth);\n\n// The three guards below wrap OPTIONAL peers, so the peer is imported lazily\n// on first request — not at module load. Koa middleware is async either way,\n// so the extra await changes nothing for callers.\n\nexport function withWorkspace(\n\tstore: Parameters<typeof _withWorkspace>[0],\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n): KoaMiddleware<any, any> {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tlet inner: KoaMiddleware<any, any> | undefined;\n\treturn async (ctx, next) => {\n\t\tif (!inner) {\n\t\t\tconst mod = await loadOptionalPeer(\n\t\t\t\t() => import('@fonderie/workspaces'),\n\t\t\t\t'@fonderie/workspaces',\n\t\t\t\t'withWorkspace()',\n\t\t\t);\n\t\t\tinner = adapt(mod.withWorkspace(store));\n\t\t}\n\t\treturn inner(ctx, next);\n\t};\n}\n\nexport function requirePermission(\n\toperation: Parameters<typeof _requirePermission>[0],\n\tpermissionKey: Parameters<typeof _requirePermission>[1],\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n): KoaMiddleware<any, any> {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tlet inner: KoaMiddleware<any, any> | undefined;\n\treturn async (ctx, next) => {\n\t\tif (!inner) {\n\t\t\tconst mod = await loadOptionalPeer(\n\t\t\t\t() => import('@fonderie/permissions'),\n\t\t\t\t'@fonderie/permissions',\n\t\t\t\t'requirePermission()',\n\t\t\t);\n\t\t\tinner = adapt(mod.requirePermission(operation, permissionKey));\n\t\t}\n\t\treturn inner(ctx, next);\n\t};\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function requireFeature(key: string): KoaMiddleware<any, any> {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tlet inner: KoaMiddleware<any, any> | undefined;\n\treturn async (ctx, next) => {\n\t\tif (!inner) {\n\t\t\tconst mod = await loadOptionalPeer(\n\t\t\t\t() => import('@fonderie/billing'),\n\t\t\t\t'@fonderie/billing',\n\t\t\t\t'requireFeature()',\n\t\t\t);\n\t\t\tinner = adapt(mod.requireFeature(key));\n\t\t}\n\t\treturn inner(ctx, next);\n\t};\n}\n\n// ── mount ─────────────────────────────────────────────────────────\n//\n// Wires up fonderie to a Koa app. Uses Koa's onion model to register a\n// single wrap-around middleware: builds fonderie context, calls next()\n// so user routes run, then falls back to fonderie infra only if the\n// request was not handled (ctx.body is still undefined).\n//\n// Routes registered after mount() are included automatically — Koa\n// composes all middlewares lazily at request time, not at registration.\n//\n// app.use(bodyParser())\n// const api = mount(app, fonderie) // returns same app\n// api.use(router.routes())\n// api.use(router.allowedMethods())\n// app.listen(port)\n\nexport function mount(app: Koa, fonderie: FonderieApp): Koa {\n\tapp.use(async (ctx, next) => {\n\t\tconst webReq = koaContextToWeb(ctx as unknown as KoaContext);\n\t\tconst fCtx = await fonderie.buildContext(webReq.clone());\n\t\tconst clientIp = resolveClientIp(\n\t\t\t(ctx as unknown as KoaContext).req.socket?.remoteAddress ?? undefined,\n\t\t\twebReq.headers,\n\t\t);\n\t\tif (clientIp) fCtx.meta.clientIp = clientIp;\n\t\tctx.state['_fonderie'] = fCtx;\n\t\tawait next();\n\t\tif (ctx.body === undefined) {\n\t\t\tconst webRes = await fonderie.handle(webReq);\n\t\t\tawait webResponseToKoa(webRes, ctx as unknown as KoaContext);\n\t\t}\n\t});\n\treturn app;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fonderie/adapter-koa",
3
- "version": "1.0.2",
3
+ "version": "2.0.0",
4
4
  "description": "Koa adapter for fonderie-js — bridge(), adapt(), mount() to use fonderie middleware in native Koa routes.",
5
5
  "keywords": [
6
6
  "fonderie-js",
@@ -35,10 +35,10 @@
35
35
  "check": "biome check --write src"
36
36
  },
37
37
  "peerDependencies": {
38
- "@fonderie/core": "^0.1.1",
39
- "@fonderie/workspaces": "^1.0.1",
40
- "@fonderie/permissions": "^1.0.1",
41
- "@fonderie/billing": "^1.0.1",
38
+ "@fonderie/core": "^0.2.0",
39
+ "@fonderie/workspaces": "^2.0.0",
40
+ "@fonderie/permissions": "^2.0.0",
41
+ "@fonderie/billing": "^2.0.0",
42
42
  "koa": "^2.0.0"
43
43
  },
44
44
  "peerDependenciesMeta": {
@@ -69,16 +69,17 @@
69
69
  },
70
70
  "files": [
71
71
  "dist",
72
+ "brain",
72
73
  "LICENSE",
73
74
  "README.md"
74
75
  ],
75
76
  "repository": {
76
77
  "type": "git",
77
- "url": "git+https://github.com/fonderie-js/sdk.git",
78
+ "url": "git+https://github.com/fonderiejs/sdk.git",
78
79
  "directory": "packages/adapter-koa"
79
80
  },
80
- "homepage": "https://github.com/fonderie-js/sdk/tree/main/packages/adapter-koa#readme",
81
+ "homepage": "https://github.com/fonderiejs/sdk/tree/main/packages/adapter-koa#readme",
81
82
  "bugs": {
82
- "url": "https://github.com/fonderie-js/sdk/issues"
83
+ "url": "https://github.com/fonderiejs/sdk/issues"
83
84
  }
84
85
  }