Dynamic GraphQL API generation for MongoDB with support for metadata-driven schemas, tracing, logging, and multi-tenant relationships.
npm install @wizeworks/graphql-factory-mongoDynamic GraphQL API generation from metadata definitions โ built for MongoDB.
> Create fully-typed GraphQL schemas, resolvers, and subscriptions dynamically based on JSON metadata, with support for multi-tenant models, relations, tracing, and logging.
---
- ๐ง Metadata-Driven: Define your schema in JSON and generate everything โ types, inputs, filters, and resolvers
- ๐ Relation Support: One-to-one and one-to-many references with dynamic field resolution
- ๐ข Multi-Tenant Ready: Shared collection support with tenant filtering logic
- ๐ Built-in Observability: Plug in your logger and tracer (supports Sentry, OpenTelemetry, and more)
- ๐ก GraphQL Subscriptions: Supports onCreated, onUpdated, and onDeleted PubSub events
- ๐ Pluggable Backend: MongoDB as the backend; Redis or in-memory PubSub for events
---
``bash`
npm install @wizeworks/graphql-factory-mongo๐ Environment Variables
The following environment variables are required to configure the application:
| Variable | Description | Default Value |
|----------------|--------------------------------------------------|-----------------------------------|
| PORT | The port on which the server will run | 3000 |MONGO_URI
| | The connection string for the MongoDB instance | mongodb://localhost:27017/app |SENTRY_DSN
| | The Sentry URI for sending logs and errors to. | ###.ingest.us.sentry.io/### |DB_NAME
| | The API key used for authentication | wize-example |
Make sure to set these variables in your .env file or your deployment environment.
`env`
PORT=3000
MONGO_URI=mongodb://localhost:27017/wize-example
DB_NAME=wize-example
SENTRY_DSN=https://
---
`ts
import express from 'express';
import { MongoClient } from 'mongodb';
import { createYoga } from 'graphql-yoga';
import { createServerSchema, createServerContext, registerSchemaRoutes, ILogger } from '@wizeworks/graphql-factory-mongo';
const port = process.env.PORT ? parseInt(process.env.PORT, 10) : 3000;
const MONGO_URI = process.env.MONGO_URI || 'mongodb://localhost:27017/';
const database = process.env.DB_NAME || 'wize-example';
const mongoClient = new MongoClient(MONGO_URI);
const logger: ILogger = {
error: (message: string) => {
const date = new Date();
const formattedDate = date.toISOString().replace(/T/, ' ').replace(/\..+/, '');
console.error([${formattedDate}] ERROR: ${message});[${formattedDate}] WARNING: ${message}
},
warn: (message: string) => {
const date = new Date();
const formattedDate = date.toISOString().replace(/T/, ' ').replace(/\..+/, '');
console.warn();[${formattedDate}] INFO: ${message}
},
info: (message: string) => {
const date = new Date();
const formattedDate = date.toISOString().replace(/T/, ' ').replace(/\..+/, '');
console.info();[${formattedDate}] DEBUG: ${message}
},
debug: (message: string) => {
const date = new Date();
const formattedDate = date.toISOString().replace(/T/, ' ').replace(/\..+/, '');
console.debug();
},
};
const start = async () => {
await mongoClient.connect();
const yoga = createYoga({
graphqlEndpoint: '/graphql',
schema: (args) => createServerSchema(args.request, mongoClient,database),
context: async ({request}) => {
const baseContext = await createServerContext(request, mongoClient);
return {
...baseContext,
database,
};
},
graphiql: true
});
const app = express();
app.use(express.json());
const schema = registerSchemaRoutes(app, mongoClient, database);
// Use Yoga as middleware in Express
app.use(yoga.graphqlEndpoint, yoga);
app.listen(port, () => {
console.log(๐ wize-example API ready at http://localhost:${port}/graphql);
});
};
start();
`
---
`ts`
{
table: "example",
metadata: {
fields: [
{
_id: "string",
name: {
type: "string",
required: true,
}
}
],
subscriptions: {
onCreated: true,
onUpdated: true,
onDeleted: true
}
},
clientApp: "example-client-app"
}
---
By default, the package uses a console logger and a no-op tracer. To connect a real logger (e.g. Sentry, Pino) or tracer (e.g. OpenTelemetry), use:
`ts
import { useLogger, useTracer } from '@wizeworks/graphql-factory-mongo'
import { SentryLogger, SentryTracer } from './my-sentry-setup'
useLogger(SentryLogger)
useTracer(SentryTracer)
`
You can plug in any provider by implementing the following interfaces:
`ts
interface ILogger {
info(msg: string, meta?: object): void
warn(msg: string, meta?: object): void
error(msg: string | Error, meta?: object): void
debug?(msg: string, meta?: object): void
}
interface ITracer {
startSpan
}
`
---
Supports pluggable:
- ILogger: Console, Sentry, Logtail, etc.ITracer
- : Noop, Sentry.startSpan, OpenTelemetry
---
| Adapter | Module | Notes |
|------------|-------------------------------|----------------------|
| In-memory | graphql-subscriptions | Default |graphql-redis-subscriptions
| Redis | | Opt-in, via adapter |
---
`bash`
npm run build
npm run dev
npm run clean
npm run semantic-release
---
MIT ยฉ WizeWorks
---
You can now use the _in operator to filter enum fields by providing a list of possible values. For example:
`graphql`
query {
findProjects(filter: { status_in: ["PLANNING", "IN_PROGRESS"] }) {
count
data {
_id
name
status
}
}
}
This query will return all projects where the status is either PLANNING or IN_PROGRESS`.