npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ambiten/adapter-graphql

v2.0.2

Published

Ambiten adapter for GraphQL

Downloads

227

Readme


Overview

@ambiten/adapter-graphql connects GraphQL execution to the Ambiten runtime.

The adapter establishes an Ambiten execution boundary around the actual GraphQL operation so runtime context remains active while resolvers, nested asynchronous calls, application services, and models execute.

This allows tenant identity, request metadata, logging, instrumentation, and other execution-scoped state to move through the application without being passed manually through every resolver.

The package currently provides integrations for:

  • Apollo Server
  • GraphQL Yoga

The GraphQL server may change.

The Ambiten execution model does not.


Installation

Install the GraphQL adapter:

npm install @ambiten/adapter-graphql

Most applications will also use the Ambiten core runtime:

npm install @ambiten/core @ambiten/adapter-graphql

Install the GraphQL server separately according to your application.

Apollo Server

npm install @apollo/server graphql

GraphQL Yoga

npm install graphql-yoga graphql

@ambiten/adapter-graphql does not require Ambiten applications to adopt a particular GraphQL server internally.

Apollo Server

Use createApolloAdapter() to establish the Ambiten runtime around Apollo GraphQL execution.

import {
  ApolloServer
} from "@apollo/server";

import {
  startStandaloneServer
} from "@apollo/server/standalone";

import {
  createApolloAdapter
} from "@ambiten/adapter-graphql";

import {
  MultiTenantManager
} from "@ambiten/core";

const server =
  new ApolloServer({
    typeDefs,
    resolvers
  });

const adapter =
  createApolloAdapter();

adapter.install(
  server,
  {
    tenancy: {
      header:
        "x-tenant-id",

      validate:
        async (
          tenantId
        ) => {
          const tenant =
            await MultiTenantManager
              .resolveTenant(
                tenantId
              );

          if (!tenant) {
            throw new Error(
              `Tenant with ID "${tenantId}" not found.`
            );
          }

          return true;
        }
    }
  }
);

await startStandaloneServer(
  server,
  {
    listen: {
      port: 4000
    }
  }
);

The application does not need to interact with adapter-runtime internals.

The execution flow becomes:

HTTP Request
      ↓
Apollo Server
      ↓
createApolloAdapter()
      ↓
Ambiten Adapter Runtime
      ↓
Tenant Resolution
      ↓
AmbitenContext
      ↓
Resolvers
      ↓
Services
      ↓
AmbitenModel
      ↓
MongoDB

The Ambiten context remains active until GraphQL execution completes.

GraphQL Yoga

Use createYogaAdapter() as a Yoga plugin.

import {
  createSchema,
  createYoga
} from "graphql-yoga";

import {
  createYogaAdapter
} from "@ambiten/adapter-graphql";

import {
  MultiTenantManager
} from "@ambiten/core";

const yoga =
  createYoga({
    schema:
      createSchema({
        typeDefs,
        resolvers
      }),

    plugins: [
      createYogaAdapter({
        tenancy: {
          header:
            "x-tenant-id",

          validate:
            async (
              tenantId
            ) => {
              const tenant =
                await MultiTenantManager
                  .resolveTenant(
                    tenantId
                  );

              if (!tenant) {
                throw new Error(
                  `Tenant with ID "${tenantId}" not found.`
                );
              }

              return true;
            }
        }
      })
    ]
  });

Yoga queries, mutations, subscriptions, and supported streaming execution enter the same Ambiten runtime model.

Runtime Flow

Regardless of the GraphQL server, the execution architecture remains consistent:

GraphQL Request
        ↓
Apollo Server / GraphQL Yoga
        ↓
Ambiten GraphQL Adapter
        ↓
Adapter Runtime
        ↓
Tenant Resolution
        ↓
AmbitenContext
        ↓
Resolver
        ↓
Application Service
        ↓
AmbitenModel
        ↓
Effective ModelContext
        ↓
Tenant Infrastructure
        ↓
MongoDB

The adapter owns the framework execution boundary.

Application code remains focused on GraphQL and business logic.

Resolver Execution

Resolvers do not need to manually forward tenant identity or request metadata through application layers.

export const resolvers = {
  Query: {
    users:
      async () => {
        return UserModel.find(
          {}
        );
      }
  },

  Mutation: {
    createUser:
      async (
        _parent,
        args
      ) => {
        return UserModel.create(
          args.input
        );
      }
  }
};

Conceptually:

Resolver
   ↓
Service
   ↓
Nested async work
   ↓
AmbitenModel
   ↓
MongoDB

The active Ambiten execution context remains available throughout the chain.

Multi-Tenancy

Tenant identity can be resolved at the GraphQL ingress boundary.

createApolloAdapter()
  .install(
    server,
    {
      tenancy: {
        header:
          "x-tenant-id",

        validate:
          async (
            tenantId
          ) => {
            const tenant =
              await MultiTenantManager
                .resolveTenant(
                  tenantId
                );

            return Boolean(
              tenant
            );
          }
      }
    }
  );

or with Yoga:

createYogaAdapter({
  tenancy: {
    header:
      "x-tenant-id",

    validate:
      async (
        tenantId
      ) => {
        const tenant =
          await MultiTenantManager
            .resolveTenant(
              tenantId
            );

        return Boolean(
          tenant
        );
      }
  }
});

Once resolved, the tenant identity becomes part of the active Ambiten execution.

Models and services can then participate in tenant-aware infrastructure resolution without manually receiving the tenant ID through resolver arguments.

Tenant resolution does not replace authentication or authorization.

Applications remain responsible for deciding whether a caller is permitted to act for a resolved tenant.

Application Context

Ambiten does not replace the normal GraphQL context object.

Application-specific values such as:

  • authenticated users
  • DataLoaders
  • API clients
  • feature flags
  • domain services

can continue to use the framework's normal GraphQL context.

Ambiten separately maintains execution-scoped runtime state such as:

tenantId
requestId
dbName
collectionName
debug
logger metadata
runtime metadata

Conceptually:

GraphQL Context
→ application data
→ authenticated user
→ loaders
→ services

AmbitenContext
→ execution identity
→ tenant identity
→ request metadata
→ infrastructure state

The two contexts can coexist.

Concurrent Execution

Ambiten uses execution-scoped context propagation so concurrent GraphQL operations remain isolated.

Operation A
tenant-a
request-a
        ↓
resolver chain
        ↓
tenant-a remains active


Operation B
tenant-b
request-b
        ↓
resolver chain
        ↓
tenant-b remains active

One operation does not need to manually protect itself from another operation's runtime state.

Subscriptions and Streaming

The GraphQL adapter supports runtime continuity for subscription and streaming execution.

A subscription may outlive the initial GraphQL execution call, so Ambiten restores the already-resolved execution snapshot when the asynchronous iterator continues.

Conceptually:

GraphQL Subscription
        ↓
Tenant resolved once
        ↓
Execution snapshot
        ↓
Async iterator
        ↓
next()
        ↓
Ambiten execution restored
        ↓
resolver / service / model work

This preserves execution identity without treating each emitted payload as a new ingress request.

Transactions

Automatic GraphQL-operation-wide transactions are intentionally not supported through:

enableTransactions: true

GraphQL may complete an operation successfully at the transport level while still reporting resolver failures in the GraphQL result.

For that reason, transaction ownership should remain aligned with the business workflow rather than the entire GraphQL operation.

Use an explicit transaction boundary inside the mutation or application service that requires atomicity.

Mutation Resolver
        ↓
Application Service
        ↓
Explicit Transaction Boundary
        ↓
Model A
        ↓
Model B
        ↓
Commit / Rollback

This keeps transaction semantics aligned with the actual unit of work.

Framework-Neutral Design

@ambiten/adapter-graphql intentionally keeps its runtime integration independent from GraphQL framework type hierarchies.

Internally, framework-specific requests are normalized into Ambiten's adapter request contract:

Apollo ─────┐
            │
Yoga ───────┤
            ↓
AmbitenRequestLike
            ↓
Adapter Runtime
            ↓
AmbitenContext

This reduces coupling between Ambiten and framework release cycles while preserving a stable execution model.

Applications remain free to choose and upgrade their GraphQL server independently.

Legacy Context Factories

Earlier versions exposed:

createApolloContextFactory()
createYogaContextFactory()

These APIs may remain available for compatibility, but they are not the recommended integration path for new applications.

Creating a GraphQL context object is not the same as keeping the Ambiten runtime active while resolvers execute.

For new applications, use:

createApolloAdapter()

or:

createYogaAdapter()

These APIs establish the runtime around actual GraphQL execution.

Execution Boundary

The central rule is simple:

GraphQL context creation
≠
GraphQL execution

Ambiten therefore establishes its runtime around:

GraphQL Operation
        ↓
Resolvers
        ↓
Services
        ↓
Models

rather than only around the earlier context-construction lifecycle.

This ensures execution state remains available where application work actually happens.

Documentation

Complete documentation is available at:

https://docs.ambiten.dev

Related Packages

  • @ambiten/core
  • @ambiten/adapter-runtime
  • @ambiten/adapter-types
  • @ambiten/logger
  • @ambiten/create

License

MIT