🌿🕸️ Mongo Data API
Mongo Client for an HTTPS World. Lambda and edge function friendly
A Mongo-like API for accessing the http-based Mongo Data API. Uses BSON to provide access to standard Mongo data types. BYO
fetch()
for maximum portability.
Usage
import { MongoClient } from "@taskless/mongo-data-api";
const mc = new MongoClient({
/** @type URL | string */
endpoint: new URL(process.env.MONGO_HTTP_URL ?? "[not defined]"),
/** @type string */
dataSource: process.env.MONGO_HTTP_DATA_SOURCE ?? "[not defined]",
/* See "Authentication" below */
auth: {
/* ... */
},
});
const { data, error } = await mc.findOne({
/* good 'ole mongo! See the Collection Methods for what's available */
});
Authentication
Authentication Method | Supported |
---|---|
API Key | ✅ |
Email & Password | ✅ |
Custom JWT | ✅ |
Bearer |
Using a Data API api key (preferred)
{
// ...
auth: {
/** @type string */
apiKey: process.env.MONGO_HTTP_API_KEY ?? "[not defined]",
},
}
Using Email and Password
{
// ...
auth: {
/** @type string */
email: process.env.MONGO_EMAIL ?? "",
/** @type string */
password: process.env.MONGO_PASSWORD ?? "",
},
}
Using a custom JWT
{
// ...
auth: {
/** @type string */
jwtTokenString: request.headers.get("jwt"),
},
}
Using Bearer Auth (required for browser)
Read more about authenticating Realm users in the browser
{
// ...
auth: {
/** @type string */
bearerToken: tokenFromRealm,
},
}
Supported Methods and API
Create a Mongo Client
const client = new MongoClient(options);
-
options
- MongoClient options-
options.endpoint
-string | URL
an endpoint for sending requests to. Your Data API Endpoint is available at your Mongo Data API UIhttps://cloud.mongodb.com/v2/<projectId>#/dataAPI
, where<projectId>
is your project ID. A single Data API is usable for the entire project, with individual data sources routing to specific atlas instances. -
options.dataSource
-string
theData Source
for your Data API. On the Data API UI, this is the "Data Source" column, and usually is either a 1:1 mapping of your cluster name, or the defaultmongodb-atlas
if you enabled Data API through the Atlas Admin UI. -
options.auth
-AuthOptions
one of the authentication methods, either api key, email & password, or a custom JWT string. At this time, only Credential Authentication is supported. -
options.fetch?
- A customfetch
function conforming to the native fetch API. We recommend cross-fetch, as it asserts a complaintfetch()
interface and avoids you having to dofetch: _fetch as typeof fetch
to satisfy the TypeScript compiler
-
Select a Database
const db = client.db(databaseName);
-
databaseName
-string
the name of the database to connect to
Select a Collection
const collection = db.collection<TSchema>(collectionName);
-
collectionName
-string
the name of the collection to connect to -
<TSchema>
- generic A Type or Interface that describes the documents in this collection. Defaults to the generic MongoDBDocument
type
Collection Methods
The following Data API resources are supported
resource | support |
---|---|
findOne |
✅ |
find |
✅ |
insertOne |
✅ |
insertMany |
✅ |
updateOne |
✅ |
updateMany |
✅ |
replaceOne |
✅ |
deleteOne |
✅ |
deleteMany |
✅ |
aggregate |
✅ |
Should Data API add support for other resources, the callApi
method allows you to pass arbitrary JSON to a Data API resource. mongo-data-api
automatically merges the dataSource
, database
, and collection
parameters in if not specified.
Return Type
All collection methods return an object containing data?
and error?
. This avoids throwing during requests, making it easier to handle the response without nesting try/catch operations.
interface DataAPIResponse {
data?: TSchema;
error?: DataAPIError;
}
Specifying Operation Names
To help with tracing and debugging, any Mongo Data API operation can be named by passing a string as the first parameter. This value is converted to the x-realm-op-name
header and can be seen in the Mongo Data API logs.
const { data, error } = await collection./*operation*/("operation name for tracing", filter, options);
Methods
findOne
const { data, error } = await collection.findOne(filter, options);
-
filter?
-Filter<TSchema>
A MongoDB Query Filter -
options?
- Query options-
options.projection?
-Document
A MongoDB Query Projection
-
find
const { data, error } = await collection.find(filter, options);
-
filter?
-Filter<TSchema>
A MongoDB Query Filter -
options?
Query options-
options.projection?
-Document
A MongoDB Query Projection -
options.sort?
-Sort
A MongoDB Sort Expression -
options.limit?
-number
The maximum number of matched documents to include in the returned result set. Each request may return up to 50,000 documents. -
options.skip?
-number
The number of matched documents to skip before adding matched documents to the result set.
-
insertOne
const { data, error } = await collection.insertOne(document);
-
document
-TSchema
The document to insert
insertMany
const { data, error } = await collection.insertMany(documents);
-
documents
-TSchema[]
The documents to insert
updateOne
const { data, error } = await collection.updateOne(filter, update, options);
-
filter
-Filter<TSchema>
A MongoDB Query Filter -
update
-UpdateFilter<TSchema> | Partial<TSchema>
A MongoDB Update Expression that specifies how to modify the matched document -
options?
Query options-
options.upsert
-boolean
The upsert flag only applies if no documents match the specified filter. If true, the updateOne action inserts a new document that matches the filter with the specified update applied to it.
-
updateMany
const { data, error } = await collection.updateMany(filter, update, options);
-
filter
-Filter<TSchema>
A MongoDB Query Filter -
update
-UpdateFilter<TSchema> | Partial<TSchema>
A MongoDB Update Expression that specifies how to modify the matched document -
options?
Query options-
options.upsert
-boolean
The upsert flag only applies if no documents match the specified filter. If true, the updateOne action inserts a new document that matches the filter with the specified update applied to it.
-
replaceOne
const { data, error } = await collection.replaceOne(
filter,
replacement,
options
);
-
filter
-Filter<TSchema>
A MongoDB Query Filter -
replacement
-WithoutId<TSchema>
The replacement document, without an_id
attribute -
options?
Query options-
options.upsert
-boolean
The upsert flag only applies if no documents match the specified filter. If true, the updateOne action inserts a new document that matches the filter with the specified update applied to it.
-
deleteOne
const { data, error } = await collection.deleteOne(filter);
-
filter
-Filter<TSchema>
A MongoDB Query Filter
deleteMany
const { data, error } = await collection.deleteMany(filter);
-
filter
-Filter<TSchema>
A MongoDB Query Filter
aggregate
const { data, error } = await collection.aggregate<TOutput>(pipeline);
-
pipeline
-Document[]
A MongoDB Aggregation Pipeline -
<TOutput>
- generic ADocument
like object that describes the output of the aggregation pipeline
callApi
const { data, error } = await collection.callApi<T>(method, body);
-
method
-string
A supported Mongo Data API Request method -
body
-Record<string, unknown>
An arbitrary key/value JSON-like data structure representing the body payload sent to the Mongo Data API -
<T>
- generic Describes the return type ofdata
on a successful API call
Errors
Requests via fetch()
have their resposne codes checked against the Data API Error Codes and on error, set the error
property of the response to a MongoDataAPIError
.
-
error.code
-number
Contains the HTTP error code from the Mongo Data API -
error.message
-string
Contains the response status text or error message included from the Data API call
FAQ
-
Why is
mongodb
in the dependencies? TypeScript requires it, however, the mongodb dependency is types-only and will not be included in your built lambda when usingtsc
,rollup
,webpack
, etc. You can verify that mongo is not included by looking at the CommonJS build. -
Why is
node-fetch
'sfetch
not of the correct type?node-fetch
'sfetch
isn't a truefetch
and wasn't typed as one. To work around this, you can either usecross-fetch
which types thefetch
API through a type assertion, or perform the type assertion yourself:fetch: _fetch as typeof fetch
. It's not ideal, but with properfetch
coming to node.js, it's a small inconvienence in the short term. -
How do I retry failed
fetch
calls?fetch-retry
(github) is an excellent library. You can also use a lower level retry tool likep-retry
(github) if you want to manage more than just thefetch()
operation itself.
License
This library started out as a fork of the excellent deno atlas_sdk module, optimized for node.js.
MIT