Skip to content

Alternative API to provide context to functions #1021

@8ctavio

Description

@8ctavio

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")
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions