diff --git a/README.md b/README.md index ca3cb6e..69553e6 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,45 @@ export default function doWork () { } ``` +### enterWith + +If you need to alter the current asynchronous context, you can use the `enterWith` helper. + +```js +import { before, describe, it } from "node:test"; +import Fastify from "fastify"; +import { app, start } from "fastify-asyncforge"; +import assert from "node:assert/strict"; + +let fastify; + +async function build(config) { + const server = await Fastify(); + + server.decorate("config", config); + await start(server); + console.log("config from memo", app().config); + + return server; +} + +describe("support exiting from a context", () => { + before(async () => { + fastify = await build({ foo: "bar" }); + }); + + it("throws", () => { + assert.throws(app); + }); + + it("does not throw using enterWith", () => { + fastify.enterWith(); + assert.equal(app(), fastify); + }); +}); +``` + + ## License MIT diff --git a/index.js b/index.js index 503dda0..28dd03b 100644 --- a/index.js +++ b/index.js @@ -3,12 +3,23 @@ const fp = require('fastify-plugin') const { memo, setAll } = require('asyncforge') -const app = memo() -const request = memo() -const reply = memo() -const logger = memo() +const app = memo('fastify.app') +const request = memo('fastify.request') +const reply = memo('fastify.reply') +const logger = memo('fastify.logger') const fastifyAsyncForge = fp(function (fastify, opts, next) { + fastify.decorate('enterWith', function () { + try { + app() + } catch { + setAll({ + [app.key]: this, + [logger.key]: this.log + }) + } + }) + fastify.addHook('onRequest', async function (req, res) { setAll({ [app.key]: this, diff --git a/test/basic.test.js b/test/basic.test.js index 0daf570..205bca7 100644 --- a/test/basic.test.js +++ b/test/basic.test.js @@ -60,3 +60,32 @@ test('basic helpers without start', async (t) => { await p.complete }) + +test('fastify.enterWith', async (t) => { + const p = tspl(t, { plan: 7 }) + const fastify = Fastify() + + await fastify.register(fastifyAsyncForge) + + fastify.enterWith() + + p.strictEqual(logger(), fastify.log) + p.strictEqual(app(), fastify) + + fastify.get('/', async function (_request, _reply) { + p.strictEqual(app(), this) + p.strictEqual(request(), _request) + p.strictEqual(reply(), _reply) + p.strictEqual(logger(), _request.log) + return { hello: 'world' } + }) + + const res = await fastify.inject({ + method: 'GET', + url: '/' + }) + + p.strictEqual(res.statusCode, 200) + + await p.complete +}) diff --git a/test/issue-7.test.mjs b/test/issue-7.test.mjs new file mode 100644 index 0000000..fee7d8a --- /dev/null +++ b/test/issue-7.test.mjs @@ -0,0 +1,30 @@ +import { before, describe, it } from 'node:test' +import Fastify from 'fastify' +import { app, start } from '../index.js' +import assert from 'node:assert/strict' + +let fastify + +async function build (config) { + const server = await Fastify() + + server.decorate('config', config) + await start(server) + + return server +} + +describe('support exiting from a context', () => { + before(async () => { + fastify = await build({ foo: 'bar' }) + }) + + it('throws', () => { + assert.throws(app) + }) + + it('does not throw using enterWith', () => { + fastify.enterWith() + assert.equal(app(), fastify) + }) +})