Methods in nile's SDK need access to a context object which is mainly provided with nile.withContext(ctx, cb). This is convenient for frameworks like express because the whole request lifecycle can have the context provided with a single call of withContext. However, in a framework like h3 (and hono, I think) this approach is not possible.
In h3 it is required to call nile.withContext in every request and middleware handler, passing logic that requires context through the callback argument, so that async operations may reliably have access to the context object. This however becomes somewhat cumbersome, especially in cases where just a single function that requires context needs to be called:
nile.withContext({/*...*/}, () => {
nile.doSomething()
})
I think a good measure to improve DX for frameworks like h3 would be to introduce an alternative signature to call methods. In particular, support directly providing context items as parameters:
nile.resource.operation(headers)
nile.resource.operation(tenantId)
nile.resource.operation(userId)
This also would serve as documentation of which context items each method requires.
In addition, other alternative which closely aligns with h3's API would be optionally accepting a context object as a first argument, which would also be helpful for methods that require most or all context items:
const nileContext = nile.createContext({ headers, tenantId, userId })
nile.resource.operation(nileContext)
nile.resource.operation(nileContext, header) // individual items could still be provided to override context object
nile.resource.operation(nileContext, tenantId, userId)
In order to introduce this new API along with the current AsyncLocalStorage implementation, functions would need to handle their arguments in a similar way to the following example:
function doSomethingWithTenantId(...args) {
const flag = isNileContext(args[0])
const nileContext = flag ? args[0] : nileStorage.getStore() // If context is explicitly provided, use it instead of async store.
const offset = Number(flag)
const tenantId = args[offset] ?? nileContext?.tenantId // If context item is explicitly provided, use it instead of context object.
if (!tenantId) throw Error("Tenant id required")
}
Methods in nile's SDK need access to a context object which is mainly provided with
nile.withContext(ctx, cb). This is convenient for frameworks likeexpressbecause the whole request lifecycle can have the context provided with a single call ofwithContext. However, in a framework likeh3(andhono, I think) this approach is not possible.In
h3it is required to callnile.withContextin every request and middleware handler, passing logic that requires context through the callback argument, so that async operations may reliably have access to the context object. This however becomes somewhat cumbersome, especially in cases where just a single function that requires context needs to be called:I think a good measure to improve DX for frameworks like
h3would be to introduce an alternative signature to call methods. In particular, support directly providing context items as parameters:This also would serve as documentation of which context items each method requires.
In addition, other alternative which closely aligns with
h3's API would be optionally accepting a context object as a first argument, which would also be helpful for methods that require most or all context items:In order to introduce this new API along with the current
AsyncLocalStorageimplementation, functions would need to handle their arguments in a similar way to the following example: