@taskless/mongo-data-api
v0.5.2
Published
Mongo Data API client using fetch, suitable for lambda and edge functions
Downloads
13
Maintainers
Readme
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 optionsoptions.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 Filteroptions?
- Query optionsoptions.projection?
-Document
A MongoDB Query Projection
find
const { data, error } = await collection.find(filter, options);
filter?
-Filter<TSchema>
A MongoDB Query Filteroptions?
Query optionsoptions.projection?
-Document
A MongoDB Query Projectionoptions.sort?
-Sort
A MongoDB Sort Expressionoptions.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 Filterupdate
-UpdateFilter<TSchema> | Partial<TSchema>
A MongoDB Update Expression that specifies how to modify the matched documentoptions?
Query optionsoptions.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 Filterupdate
-UpdateFilter<TSchema> | Partial<TSchema>
A MongoDB Update Expression that specifies how to modify the matched documentoptions?
Query optionsoptions.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 Filterreplacement
-WithoutId<TSchema>
The replacement document, without an_id
attributeoptions?
Query optionsoptions.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 methodbody
-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 APIerror.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