Skip to main content
zerotal

Documentation


Documentation / zerotal / http / negotiate

Function: negotiate()

negotiate(ctx): <TWeb, TJson, TCli>(map) => Promise<void | TWeb | TJson | TCli>

Defined in: packages/core/src/http/negotiate.ts:197

Polymorphic execution primitive — routes handling to the channel-appropriate closure based on how the request arrived.

Works in controllers to return channel-appropriate responses:

Parameters

ctx

HttpContext

Returns

<TWeb, TJson, TCli>(map) => Promise<void | TWeb | TJson | TCli>

Examples

async store(ctx: HttpContext) {
  const post = await Post.create(await ctx.body());
  return negotiate(ctx)({
    web:  (w) => { w.flash('success', 'Post created!'); w.redirect('/posts'); },
    json: (a) => a.json({ data: post }, 201),
    cli:  (c) => c.success(`Post #${post.id} created.`),
  });
}

Works in middleware to block, redirect, or pass through per channel:
async handle(ctx, next) {
  if (!ctx.user) {
    await negotiate(ctx)({
      web:  (w) => w.redirect('/login'),
      json: (a) => a.json({ message: 'Unauthenticated.' }, 401),
      cli:  (c) => c.error('Authentication required.'),
    });
    return ctx; // short-circuit — response is already set
  }
  return next(ctx);
}

When no `cli` handler is provided, CLI requests fall back to the `json` branch
(curl / wget users expect structured output).