Skip to content

Commit

Permalink
BREAKING: refactor constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
erfanium committed Jul 3, 2022
1 parent 26e20f0 commit eaf1208
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 52 deletions.
114 changes: 88 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@

> **atlas_sdk** is a TypeSafe
> [MongoDB Atlas Data API](https://www.mongodb.com/docs/atlas/api/data-api/#introduction)
> SDK for Deno & Deno Deploy
> SDK for Deno & Deno Deploy & Web
[![Discord server](https://img.shields.io/discord/768918486575480863?color=blue&label=Ask%20for%20help%20here&logo=discord&style=flat-square)](https://discord.gg/HEdTCvZUSf)

## Links

- [Docs](https://doc.deno.land/https/deno.land/x/atlas_sdk/mod.ts)

## Permissions

This module needs `net` permission. use `deno run --allow-net` command

### Import

Replace `LATEST_VERSION` with
Expand All @@ -22,20 +26,54 @@ import {
} from "https://deno.land/x/atlas_sdk@LATEST_VERSION/mod.ts";
```

### Connect
### Constructor

#### Authenticate via email and password

[Documentation](https://www.mongodb.com/docs/atlas/app-services/authentication/email-password/#std-label-email-password-authentication)

```ts
const client = new MongoClient({
endpoint: "https://data.mongodb-api.com/app/YOUR_APP_ID/endpoint/data/v1",
dataSource: "YOUR_CLUSTER_NAME", // e.g. "Cluster0"
auth: {
email: "YOUR_EMAIL",
password: "YOUR_PASSWORD",
},
});
```

#### Authenticate via api-key

[Documentation](https://www.mongodb.com/docs/atlas/app-services/authentication/api-key/#std-label-api-key-authentication)

```ts
const client = new MongoClient({
endpoint: "https://data.mongodb-api.com/app/YOUR_APP_ID/endpoint/data/v1",
dataSource: "YOUR_CLUSTER_NAME", // e.g. "Cluster0"
auth: {
apiKey: "YOUR_API_KEY",
},
});
```

#### Authenticate via custom JWT

[Documentation](https://www.mongodb.com/docs/atlas/app-services/authentication/custom-jwt/#std-label-custom-jwt-authentication)

```ts
const client = new MongoClient({
appId: "YOUR_APP_ID", // e.g. "data-omosm"
endpoint: "https://data.mongodb-api.com/app/YOUR_APP_ID/endpoint/data/v1",
dataSource: "YOUR_CLUSTER_NAME", // e.g. "Cluster0"
apiKey: "YOUR_API_KEY",
auth: {
jwtTokenString: "YOUR_JWT",
},
});
```

### Access Collection
### Define Schema Type

```ts
// Defining schema interface
interface UserSchema {
_id: ObjectId;
username: string;
Expand All @@ -48,45 +86,57 @@ const users = db.collection<UserSchema>("users");

### Insert

#### insertOne

```ts
const insertId = await users.insertOne({
username: "user1",
password: "pass1",
});

const insertIds = await users.insertMany([
{
username: "user1",
password: "pass1",
},
{
username: "user2",
password: "pass2",
},
]);
```

### Find
#### insertMany

```ts
const user1 = await users.findOne({ _id: insertId });
const insertIds = await users.insertMany([{
username: "user1",
password: "pass1",
}, {
username: "user2",
password: "pass2",
}]);
```

### Find

const all_users = await users.find({ username: { $ne: null } });
#### findOne

// find by ObjectId
```ts
const user1_id = await users.findOne({
_id: new ObjectId("SOME OBJECTID STRING"),
});
```

#### find

```ts
const allActiveUsers = await users.find({ active: true });
```

### Count

#### countDocuments

```ts
const count = await users.countDocuments({ username: { $ne: null } });
// count of all active users
const count = await users.countDocuments({ active: true });
```

const estimatedCount = await users.estimatedDocumentCount({
username: { $ne: null },
});
#### estimatedDocumentCount

```ts
// estimated count of all active users
const estimatedCount = await users.estimatedDocumentCount({ active: true });
```

### Aggregation
Expand All @@ -100,12 +150,18 @@ const docs = await users.aggregate([

### Update

#### updateOne

```ts
const { matchedCount, modifiedCount, upsertedId } = await users.updateOne(
{ username: { $ne: null } },
{ $set: { username: "USERNAME" } },
);
```

#### updateMany

```ts
const { matchedCount, modifiedCount, upsertedId } = await users.updateMany(
{ username: { $ne: null } },
{ $set: { username: "USERNAME" } },
Expand All @@ -126,8 +182,14 @@ const { matchedCount, modifiedCount, upsertedId } = await users.replaceOne(

### Delete

#### deleteOne

```ts
const deleteCount = await users.deleteOne({ _id: insertId });
```

#### deleteMany

const deleteCount2 = await users.deleteMany({ username: "test" });
```ts
const deleteCount = await users.deleteMany({ username: "test" });
```
17 changes: 17 additions & 0 deletions auth_types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export interface EmailPasswordAuthOptions {
email: string;
password: string;
}

export interface ApiKeyAuthOptions {
apiKey: string;
}

export interface CustomJwtAuthOptions {
jwtTokenString: string;
}

export type AuthOptions =
| EmailPasswordAuthOptions
| ApiKeyAuthOptions
| CustomJwtAuthOptions;
51 changes: 31 additions & 20 deletions client.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,49 @@
import { AuthOptions } from "./auth_types.d.ts";
import { Document, EJSON } from "./deps.ts";

export interface MongoClientConstructorOptions {
appId: string;
dataSource: string;
apiKey: string;
endpoint?: string;
auth: AuthOptions;
endpoint: string;
fetch?: typeof fetch;
}

export class MongoClient {
appId: string;
dataSource: string;
apiKey: string;
endpoint = "https://data.mongodb-api.com";
endpoint: string;
fetch = fetch;
headers = new Headers();

constructor(
{ appId, dataSource, apiKey, endpoint, fetch }:
MongoClientConstructorOptions,
{ dataSource, auth, endpoint, fetch }: MongoClientConstructorOptions,
) {
this.appId = appId;
this.dataSource = dataSource;
this.apiKey = apiKey;
if (endpoint) {
this.endpoint = endpoint;
}
this.endpoint = endpoint;

if (fetch) {
this.fetch = fetch;
}

this.headers.set("Content-Type", "application/ejson");
this.headers.set("Accept", "application/ejson");

if ("apiKey" in auth) {
this.headers.set("api-key", auth.apiKey);
return;
}

if ("jwtTokenString" in auth) {
this.headers.set("jwtTokenString", auth.jwtTokenString);
return;
}

if ("email" in auth && "password" in auth) {
this.headers.set("email", auth.email);
this.headers.set("password", auth.password);
return;
}

throw new Error("Invalid auth options");
}

database(name: string) {
Expand Down Expand Up @@ -191,16 +206,12 @@ class Collection<T> {

// deno-lint-ignore no-explicit-any
async callApi(method: string, extra: Document): Promise<any> {
const { endpoint, appId, apiKey, dataSource } = this.client;
const url = `${endpoint}/app/${appId}/endpoint/data/v1/action/${method}`;
const { endpoint, dataSource, headers } = this.client;
const url = `${endpoint}/action/${method}`;

const response = await this.client.fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/ejson",
"Accept": "application/ejson",
"api-key": apiKey,
},
headers,
body: EJSON.stringify({
collection: this.name,
database: this.database.name,
Expand Down
2 changes: 1 addition & 1 deletion deps.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from "https://deno.land/x/[email protected].2/mod.ts";
export * from "https://deno.land/x/[email protected].3/mod.ts";
12 changes: 7 additions & 5 deletions test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
// deno-lint-ignore-file require-await
import { MongoClient, ObjectId } from "./mod.ts";
import { deferred } from "https://deno.land/std@0.140.0/async/deferred.ts";
import { assertEquals } from "https://deno.land/std@0.140.0/testing/asserts.ts";
import { deferred } from "https://deno.land/std@0.146.0/async/deferred.ts";
import { assertEquals } from "https://deno.land/std@0.146.0/testing/asserts.ts";

Deno.test("Sample Test", async () => {
const fetchMock = deferred<{ url: string; init: RequestInit }>();

const client = new MongoClient({
appId: "appId",
endpoint: "https://data.mongodb-api.com/app/data-abc/endpoint/data/v1",
dataSource: "dataSource",
apiKey: "API_KEY",
auth: {
apiKey: "API_KEY",
},
fetch: (async (url: string, init: RequestInit) => {
fetchMock.resolve({ url, init });
return {
Expand All @@ -28,7 +30,7 @@ Deno.test("Sample Test", async () => {
const { url, init } = await fetchMock;
assertEquals(
url,
"https://data.mongodb-api.com/app/appId/endpoint/data/beta/action/insertOne",
"https://data.mongodb-api.com/app/data-abc/endpoint/data/v1/action/insertOne",
);
assertEquals(init.method, "POST");
assertEquals(
Expand Down

0 comments on commit eaf1208

Please sign in to comment.