@taskless/mongo-data-api
TypeScript icon, indicating that this package has built-in type declarations

0.5.2 • Public • Published

🌿🕸️ Mongo Data API
Mongo Client for an HTTPS World. Lambda and edge function friendly

npm  npm  GitHub issues  GitHub 

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 UI https://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 the Data 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 default mongodb-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 custom fetch function conforming to the native fetch API. We recommend cross-fetch, as it asserts a complaint fetch() interface and avoids you having to do fetch: _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 MongoDB Document 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);

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);

deleteMany

const { data, error } = await collection.deleteMany(filter);

aggregate

const { data, error } = await collection.aggregate<TOutput>(pipeline);
  • pipeline - Document[] A MongoDB Aggregation Pipeline
  • <TOutput> - generic A Document 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 of data 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 using tsc, rollup, webpack, etc. You can verify that mongo is not included by looking at the CommonJS build.
  • Why is node-fetch's fetch not of the correct type? node-fetch's fetch isn't a true fetch and wasn't typed as one. To work around this, you can either use cross-fetch which types the fetch API through a type assertion, or perform the type assertion yourself: fetch: _fetch as typeof fetch. It's not ideal, but with proper fetch 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 like p-retry (github) if you want to manage more than just the fetch() operation itself.

License

This library started out as a fork of the excellent deno atlas_sdk module, optimized for node.js.

MIT

Package Sidebar

Install

npm i @taskless/mongo-data-api

Weekly Downloads

1

Version

0.5.2

License

MIT

Unpacked Size

99.2 kB

Total Files

11

Last publish

Collaborators

  • jakobo