Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jsr support #409

Merged
merged 16 commits into from
Mar 23, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
.idea/
.DS_Store
.vscode/
deno.lock
williamhorning marked this conversation as resolved.
Show resolved Hide resolved
30 changes: 30 additions & 0 deletions deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "@db/mongo",
"version": "0.33.0",
"exports": {
".": "./mod.ts",
"./client": "./src/client.ts",
"./collection": "./src/collection/collection.ts",
"./gridfs": "./src/gridfs/bucket.ts",
"./types": "./src/types.ts"
},
"publish": {
"exclude": [".github", "tests", ".gitattributes", ".gitignore", "deno.lock"]
},
"imports": {
"assert": "jsr:@std/assert@^0.220.1",
"b64": "jsr:@std/encoding@^0.220.1/base64",
"bdd": "jsr:@std/testing@^0.220.1/bdd",
"bytes_eq": "jsr:@std/bytes@^0.220.1/equals",
williamhorning marked this conversation as resolved.
Show resolved Hide resolved
"hex": "jsr:@std/encoding@^0.220.1/hex",
"io": "jsr:@std/io@^0.220.1",
"semver": "jsr:@std/semver@^0.220.1",
"std_crypto": "jsr:@std/crypto@^0.220.1/crypto",
"web-bson": "jsr:@lucsoft/web-bson@^0.3.1"
},
"test": {
"include": [
"tests/cases/*.ts"
]
}
}
6 changes: 0 additions & 6 deletions deps.ts

This file was deleted.

10 changes: 1 addition & 9 deletions mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,14 @@ export { MongoClient } from "./src/client.ts";
export { Database } from "./src/database.ts";
export { Collection } from "./src/collection/mod.ts";
export * from "./src/types.ts";
export * as Bson from "./deps.ts";
export {
Binary,
BSONRegExp,
BSONSymbol,
Code,
DBRef,
Decimal128,
Double,
Int32,
Long,
MaxKey,
MinKey,
ObjectId,
Timestamp,
UUID,
} from "./deps.ts";
export type { Document } from "./deps.ts";
williamhorning marked this conversation as resolved.
Show resolved Hide resolved
} from "web-bson";
export { GridFSBucket } from "./src/gridfs/bucket.ts";
12 changes: 4 additions & 8 deletions src/auth/base.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import { ConnectOptions, Credential } from "../types.ts";
import { WireProtocol } from "../protocol/mod.ts";
import { Document } from "../../deps.ts";
import { ConnectOptions, Credential, Document } from "../types.ts";

export abstract class AuthPlugin {
abstract prepare(
authContext: AuthContext,
): Document;
abstract auth(
authContext: AuthContext,
): Document;
abstract prepare(authContext: AuthContext): Document;
abstract auth(authContext: AuthContext): Document;
williamhorning marked this conversation as resolved.
Show resolved Hide resolved
}

/** Context used during authentication */
export class AuthContext {
/** The connection to authenticate */
Expand Down
25 changes: 14 additions & 11 deletions src/auth/scram.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { Credential } from "../types.ts";
import { saslprep } from "../utils/saslprep/mod.ts";
import { AuthContext, AuthPlugin } from "./base.ts";
import { HandshakeDocument } from "../protocol/handshake.ts";
import { decodeBase64, encodeBase64 } from "b64";
import { encodeHex } from "hex";
import { crypto as stdCrypto } from "std_crypto";
import { Binary } from "web-bson";
import { MongoDriverError } from "../error.ts";
import { b64, Binary, crypto as stdCrypto, Document, hex } from "../../deps.ts";
import { HandshakeDocument } from "../protocol/handshake.ts";
import { driverMetadata } from "../protocol/mod.ts";
import { Credential, Document } from "../types.ts";
import { saslprep } from "../utils/saslprep/mod.ts";
import { AuthContext, AuthPlugin } from "./base.ts";
import { pbkdf2 } from "./pbkdf2.ts";

type CryptoMethod = "sha1" | "sha256";
Expand Down Expand Up @@ -65,7 +68,7 @@ export function clientFirstMessageBare(username: string, nonce: Uint8Array) {
...enc.encode("n="),
...enc.encode(username),
...enc.encode(",r="),
...enc.encode(b64.encodeBase64(nonce)),
...enc.encode(encodeBase64(nonce)),
],
);
}
Expand Down Expand Up @@ -160,7 +163,7 @@ export async function continueScramConversation(
const withoutProof = `c=biws,r=${rnonce}`;
const saltedPassword = await HI(
processedPassword,
b64.decodeBase64(salt),
decodeBase64(salt),
iterations,
cryptoMethod,
);
Expand Down Expand Up @@ -193,7 +196,7 @@ export async function continueScramConversation(
);
if (
!compareDigest(
b64.decodeBase64(parsedResponse.v),
decodeBase64(parsedResponse.v),
new Uint8Array(serverSignature),
)
) {
Expand Down Expand Up @@ -260,7 +263,7 @@ export async function passwordDigest(
"MD5",
enc.encode(`${username}:mongo:${password}`),
);
return hex.encodeHex(new Uint8Array(result));
return encodeHex(new Uint8Array(result));
}

// XOR two buffers
Expand All @@ -275,7 +278,7 @@ export function xor(_a: ArrayBuffer, _b: ArrayBuffer) {
res[i] = a[i] ^ b[i];
}

return b64.encodeBase64(res);
return encodeBase64(res);
}

export function H(method: CryptoMethod, text: BufferSource) {
Expand Down Expand Up @@ -333,7 +336,7 @@ export async function HI(
cryptoMethod: CryptoMethod,
): Promise<ArrayBuffer> {
// omit the work if already generated
const key = [data, b64.encodeBase64(salt), iterations].join(
const key = [data, encodeBase64(salt), iterations].join(
"_",
);
if (_hiCache[key] !== undefined) {
Expand Down
5 changes: 2 additions & 3 deletions src/auth/x509.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Credential } from "../types.ts";
import { AuthContext, AuthPlugin } from "./base.ts";
import { HandshakeDocument } from "../protocol/handshake.ts";
import { driverMetadata } from "../protocol/mod.ts";
import { Document } from "../../deps.ts";
import { Credential, Document } from "../types.ts";
import { AuthContext, AuthPlugin } from "./base.ts";

export interface X509Command extends Document {
authenticate: number;
Expand Down
40 changes: 33 additions & 7 deletions src/client.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
import { Cluster } from "./cluster.ts";
import { Database } from "./database.ts";
import { BuildInfo, ConnectOptions, ListDatabaseInfo } from "./types.ts";
import { parse } from "./utils/uri.ts";
import { MongoDriverError } from "./error.ts";
import { Cluster } from "./cluster.ts";
import { Document } from "../deps.ts";
import {
BuildInfo,
ConnectOptions,
Document,
ListDatabaseInfo,
} from "./types.ts";
import { parse } from "./utils/uri.ts";

/**
* A client that allows you to interact with a MongoDB Server
* @module
*/

/** A client that allows you to interact with a MongoDB Server */
export class MongoClient {
#cluster?: Cluster;
#defaultDbName = "admin";
#buildInfo?: BuildInfo;

get buildInfo() {
/** Get information about your server's build */
get buildInfo(): BuildInfo | undefined {
return this.#buildInfo;
}

getCluster() {
/** Get the cluster associated with the client */
getCluster(): Cluster {
if (!this.#cluster) {
throw new MongoDriverError(
"MongoClient is not connected to the Database",
Expand All @@ -24,6 +36,11 @@ export class MongoClient {
return this.#cluster;
}

/**
* Connect to the given MongoDB server
*
* @param options Connection options or a MongoDB URI
*/
async connect(
options: ConnectOptions | string,
): Promise<Database> {
Expand All @@ -48,6 +65,12 @@ export class MongoClient {
return this.database((options as ConnectOptions).db);
}

/**
* List all databases on the connected server
*
* @param options Options to pass to the `listDatabases` command
* @returns A list of databases including their name, size on disk, and whether they are empty
*/
async listDatabases(options: {
filter?: Document;
nameOnly?: boolean;
Expand All @@ -64,15 +87,18 @@ export class MongoClient {
return databases;
}

/** Run a command on the connected server */
// deno-lint-ignore no-explicit-any
runCommand<T = any>(db: string, body: Document): Promise<T> {
return this.getCluster().protocol.commandSingle(db, body);
}

database(name = this.#defaultDbName): Database {
/** Get a database instance on the connected server */
database(name: string = this.#defaultDbName): Database {
return new Database(this.getCluster(), name);
}

/** Close the connection to the server */
close() {
if (this.#cluster) this.#cluster.close();
}
Expand Down
21 changes: 13 additions & 8 deletions src/cluster.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { WireProtocol } from "./protocol/mod.ts";
import { ConnectOptions } from "./types.ts";
import { AuthContext, ScramAuthPlugin, X509AuthPlugin } from "./auth/mod.ts";
import { MongoDriverError } from "./error.ts";
import { Server } from "./types.ts";
import { WireProtocol } from "./protocol/mod.ts";
import { ConnectOptions, Server } from "./types.ts";

export class Cluster {
#options: ConnectOptions;
Expand All @@ -24,7 +23,10 @@ export class Cluster {
);
}

connectToServer(server: Server, options: ConnectOptions) {
connectToServer(
server: Server,
options: ConnectOptions,
): Promise<Deno.TlsConn | Deno.TcpConn> {
const denoConnectOps: Deno.ConnectTlsOptions = {
hostname: server.host,
port: server.port,
Expand Down Expand Up @@ -57,7 +59,10 @@ export class Cluster {
);
}

async authenticateToServer(conn: Deno.Conn, options: ConnectOptions) {
async authenticateToServer(
conn: Deno.Conn,
options: ConnectOptions,
): Promise<WireProtocol> {
const protocol = new WireProtocol(conn);
if (options.credential) {
const authContext = new AuthContext(
Expand Down Expand Up @@ -111,16 +116,16 @@ export class Cluster {
};
}

get protocol() {
get protocol(): WireProtocol {
return this.getMaster().protocol;
}

close() {
for (const conn of this.#connections) {
try {
conn.close();
} catch (error) {
console.error(`Error closing connection: ${error}`);
} catch {
// this is safe to ignore
}
}
}
Expand Down
Loading
Loading