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

feat: v0.2.0 #5

Merged
merged 8 commits into from
Mar 21, 2022
Merged
Show file tree
Hide file tree
Changes from 7 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
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
# For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages
# Fork from: https://github.com/actions/starter-workflows/blob/master/ci/npm-publish.yml
# Fork from: https://github.com/actions/starter-workflows/blob/main/ci/npm-publish.yml

name: Publish

Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

All notable changes to this project will be documented in this file.

### v0.2.0 (2022-03-09)

**Feature**

- New creator function `createMongoDBDataAPI`

**Fix**

- [#3 Adjust typescript generics](https://github.com/surmon-china/mongodb-data-api/pull/3)
- [#4 Disable parameter inference](https://github.com/surmon-china/mongodb-data-api/pull/4)

### v0.1.0 (2022-01-31)

- Implements Beta API
69 changes: 47 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
 
[![Test Codecov](https://img.shields.io/codecov/c/github/surmon-china/mongodb-data-api?style=for-the-badge)](https://codecov.io/gh/surmon-china/mongodb-data-api)
 
[![GitHub license](https://img.shields.io/github/license/surmon-china/mongodb-data-api.svg?style=for-the-badge)](https://github.com/surmon-china/mongodb-data-api/blob/master/LICENSE)
[![GitHub license](https://img.shields.io/github/license/surmon-china/mongodb-data-api.svg?style=for-the-badge)](/LICENSE)

> MongoDB Atlas [Data API](https://docs.atlas.mongodb.com/api/data-api/) SDK for Node.js.
MongoDB Atlas [Data API](https://docs.atlas.mongodb.com/api/data-api/) SDK for Node.js.

---

Expand All @@ -33,22 +33,22 @@ yarn add mongodb-data-api
#### Init

```ts
import { MongoDBDataAPI, Region } from 'mongodb-data-api'
import { createMongoDBDataAPI, Region } from 'mongodb-data-api'

// init by URL Endpoint
const api = new MongoDBDataAPI({
const api = createMongoDBDataAPI({
apiKey: '<your_mongodb_api_key>',
urlEndpoint: 'https://data.mongodb-api.com/app/<your_mongodb_app_id>/endpoint/data/beta'
})

// or init by app ID
const api = new MongoDBDataAPI({
const api = createMongoDBDataAPI({
apiKey: '<your_mongodb_api_key>',
appId: '<your_mongodb_app_id>'
})

// specific region of app
const api = new MongoDBDataAPI({
const api = createMongoDBDataAPI({
apiKey: '<your_mongodb_api_key>',
appId: '<your_mongodb_app_id>',
region: Region.Virginia
Expand Down Expand Up @@ -126,27 +126,30 @@ api
#### Method chaining

```ts
// api.$cluster
// select cluster
const clusterA = api.$cluster('a')

// api.$cluster.$database
// select database
const databaseB = clusterA.$database('b')
const databaseC = clusterA.$database('c')

// api.$cluster.$database.$collection
const bItemCollection = databaseB.$collection('item')
const cItemCollection = databaseC.$collection('item')

// actions
bItemCollection.findOne({ filter: {/*...*/} })
cItemCollection.insertOne({ document: {/*...*/} })
// select collection
const collectionC = databaseB.$collection<C>('c')
// data actions
const data = await collectionC.findOne({
filter: {
/*...*/
}
})
const result = await collectionC.insertOne({
document: {
/*...*/
}
})

// -------------

// chaining is equivalent to the api call
api.$cluster('a').$database('b').$collection('c').findOne({ filter: {} })
api.$cluster('a').$database('b').$collection<C>('c').findOne({ filter: {} })
// the same as
api.findOne({
api.findOne<C>({
dataSource: 'a',
database: 'b',
collection: 'c',
Expand All @@ -167,6 +170,28 @@ api.$$action('findOne', {
})
```

#### Original Class

You can use the original Class to implement some special requirements.

```ts
import { MongoDBDataAPI } from 'mongodb-data-api'

const customerCollection = new MongoDBDataAPI<CustomerDocument>(
{
apiKey: '<your_mongodb_api_key>',
appId: '<your_mongodb_app_id>'
},
{
dataSource: '<target_cluster_name>',
database: '<target_database_name>',
collection: '<target_collection_name>'
}
)

const customer = await customerCollection.findOne({ ... })
```

### Development

```bash
Expand All @@ -185,8 +210,8 @@ yarn build

### Changelog

Detailed changes for each release are documented in the [release notes](https://github.com/surmon-china/mongodb-data-api/blob/master/CHANGELOG.md).
Detailed changes for each release are documented in the [release notes](/CHANGELOG.md).

### License

[MIT](https://github.com/surmon-china/mongodb-data-api/blob/master/LICENSE)
[MIT](/LICENSE)
9 changes: 5 additions & 4 deletions libundler.config.js → libundler.config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
/** @type {import('@surmon-china/libundler/lib/interface').LibundlerConfigObject} */
module.exports = {
import { defineConfig } from '@surmon-china/libundler'

export default defineConfig({
libName: 'MongoDBDataAPI',
outFileName: 'mongodb-data-api',
targets: ['cjs', 'esm'],
entry: './src/index.ts',
outDir: './dist',
external: ['axios', 'mongodb'],
minimize: false,
terser: false,
sourcemap: false
}
})
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mongodb-data-api",
"version": "0.1.0",
"version": "0.2.0",
"description": "MongoDB atlas data API SDK for Node.js",
"keywords": [
"MongoDB data API",
Expand All @@ -24,7 +24,9 @@
"scripts": {
"lint": "eslint --ext .ts src/**",
"format": "prettier --write --parser typescript \"src/**/*.ts\"",
"test": "jest",
"test": "npm run test:type && npm run test:unit",
"test:unit": "jest",
"test:type": "tsc -p ./tests-dts/tsconfig.json && tsc -p ./tests-dts/tsconfig.build.json",
"build": "libundler",
"rebirth": "npm run lint && npm run test && npm run build",
"release": ". ./scripts/release.sh"
Expand All @@ -34,7 +36,7 @@
"mongodb": "^4.0.0"
},
"devDependencies": {
"@surmon-china/libundler": "^1.1.1",
"@surmon-china/libundler": "^2.1.0",
"@types/jest": "^27.4.0",
"@typescript-eslint/eslint-plugin": "^5.9.1",
"@typescript-eslint/parser": "^5.9.1",
Expand Down
81 changes: 49 additions & 32 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import _axios, { AxiosInstance, AxiosRequestConfig } from 'axios'
import type { Filter, Projection, Sort, UpdateFilter, Document } from 'mongodb'
import type { Filter, FindOptions, Sort, UpdateFilter, Document } from 'mongodb'

// https://github.com/surmon-china/mongodb-data-api/pull/3/files @maxfi
type Projection = FindOptions['projection']

// https://github.com/surmon-china/mongodb-data-api/pull/4/files @maxfi
type NoInfer<A extends any> = [A][A extends any ? 0 : never]

type AnyKeys<T> = { [P in keyof T]?: T[P] | any }
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never }
Expand Down Expand Up @@ -59,7 +65,7 @@ interface PackEndpointConfig extends BaseConfig {

export type Config = XOR<UrlEndpointConfig, PackEndpointConfig>

export class MongoDBDataAPI<InnerDoc = any> {
export class MongoDBDataAPI<InnerDoc = Document> {
#config: Config
#baseParams: BaseParams
#axios: AxiosInstance
Expand All @@ -84,11 +90,11 @@ export class MongoDBDataAPI<InnerDoc = any> {
)
}

/** Select a collection. */
public $collection<Doc = InnerDoc>(collection: string) {
return this.#newAPI<Doc>({ collection }) as Omit<
MongoDBDataAPI<Doc>,
'$cluster' | '$database' | '$collection'
/** Select a cluster. */
public $cluster(clusterName: string) {
return this.#newAPI<InnerDoc>({ dataSource: clusterName }) as Omit<
MongoDBDataAPI<InnerDoc>,
'$cluster' | '$collection'
>
}

Expand All @@ -100,19 +106,19 @@ export class MongoDBDataAPI<InnerDoc = any> {
>
}

/** Select a cluster. */
public $cluster(clusterName: string) {
return this.#newAPI<InnerDoc>({ dataSource: clusterName }) as Omit<
MongoDBDataAPI<InnerDoc>,
'$cluster' | '$collection'
/** Select a collection. */
public $collection<Doc = InnerDoc>(collection: string) {
return this.#newAPI<Doc>({ collection }) as Omit<
MongoDBDataAPI<Doc>,
'$cluster' | '$database' | '$collection'
>
}

/**
* Execute a API action.
* @link https://docs.atlas.mongodb.com/api/data-api-resources/
*/
public $$action<Result = any>(
public $$action<Result = unknown>(
name: string,
params: BaseParams = {},
axiosConfig?: AxiosRequestConfig
Expand Down Expand Up @@ -156,8 +162,11 @@ export class MongoDBDataAPI<InnerDoc = any> {
* Find a Single Document.
* @link https://docs.atlas.mongodb.com/api/data-api-resources/#find-a-single-document
*/
public findOne<D = InnerDoc>(
params?: ExtendBaseParams<{ filter?: Filter<D>; projection?: Projection<D> }>
public findOne<D = InnerDoc, T = NoInfer<D>>(
params?: ExtendBaseParams<{
filter?: Filter<T>
projection?: Projection
}>
) {
return this.$$action<{ document: D | null }>('findOne', params)
}
Expand All @@ -166,10 +175,10 @@ export class MongoDBDataAPI<InnerDoc = any> {
* Find Multiple Documents.
* @link https://docs.atlas.mongodb.com/api/data-api-resources/#find-multiple-documents
*/
public find<D = InnerDoc>(
public find<D = InnerDoc, T = NoInfer<D>>(
params?: ExtendBaseParams<{
filter?: Filter<D>
projection?: Projection<D>
filter?: Filter<T>
projection?: Projection
sort?: Sort
limit?: number
skip?: number
Expand All @@ -182,8 +191,8 @@ export class MongoDBDataAPI<InnerDoc = any> {
* Insert a Single Document.
* @link https://docs.atlas.mongodb.com/api/data-api-resources/#insert-a-single-document
*/
public insertOne<D = InnerDoc>(
params: ExtendBaseParams<{ document: AnyKeys<D> | Document }>
public insertOne<D = InnerDoc, T = NoInfer<D>>(
params: ExtendBaseParams<{ document: AnyKeys<T> | Document }>
) {
return this.$$action<{ insertedId: string }>('insertOne', params)
}
Expand All @@ -192,8 +201,8 @@ export class MongoDBDataAPI<InnerDoc = any> {
* Insert Multiple Documents.
* @link https://docs.atlas.mongodb.com/api/data-api-resources/#insert-multiple-documents
*/
public insertMany<D = InnerDoc>(
params: ExtendBaseParams<{ documents: Array<AnyKeys<D> | Document> }>
public insertMany<D = InnerDoc, T = NoInfer<D>>(
params: ExtendBaseParams<{ documents: Array<AnyKeys<T> | Document> }>
) {
return this.$$action<{ insertedIds: Array<string> }>('insertMany', params)
}
Expand All @@ -202,10 +211,10 @@ export class MongoDBDataAPI<InnerDoc = any> {
* Update a Single Document.
* @link https://docs.atlas.mongodb.com/api/data-api-resources/#update-a-single-document
*/
public updateOne<D = InnerDoc>(
public updateOne<D = InnerDoc, T = NoInfer<D>>(
params: ExtendBaseParams<{
filter: Filter<D>
update: UpdateFilter<D>
filter: Filter<T>
update: UpdateFilter<T>
upsert?: boolean
}>
) {
Expand All @@ -220,10 +229,10 @@ export class MongoDBDataAPI<InnerDoc = any> {
* Update Multiple Documents.
* @link https://docs.atlas.mongodb.com/api/data-api-resources/#update-multiple-documents
*/
public updateMany<D = InnerDoc>(
public updateMany<D = InnerDoc, T = NoInfer<D>>(
params: ExtendBaseParams<{
filter: Filter<D>
update: UpdateFilter<D>
filter: Filter<T>
update: UpdateFilter<T>
upsert?: boolean
}>
) {
Expand All @@ -238,9 +247,9 @@ export class MongoDBDataAPI<InnerDoc = any> {
* Replace a Single Document.
* @link https://docs.atlas.mongodb.com/api/data-api-resources/#replace-a-single-document
*/
public replaceOne<D = InnerDoc>(
public replaceOne<D = InnerDoc, T = NoInfer<D>>(
params: ExtendBaseParams<{
filter: Filter<D>
filter: Filter<T>
replacement: any
upsert?: boolean
}>
Expand All @@ -256,15 +265,19 @@ export class MongoDBDataAPI<InnerDoc = any> {
* Delete a Single Document.
* @link https://docs.atlas.mongodb.com/api/data-api-resources/#delete-a-single-document
*/
public deleteOne<D = InnerDoc>(params: ExtendBaseParams<{ filter: Filter<D> }>) {
public deleteOne<D = InnerDoc, T = NoInfer<D>>(
params: ExtendBaseParams<{ filter: Filter<T> }>
) {
return this.$$action<{ deletedCount: number }>('deleteOne', params)
}

/**
* Delete Multiple Documents.
* @link https://docs.atlas.mongodb.com/api/data-api-resources/#delete-multiple-documents
*/
public deleteMany<D = InnerDoc>(params: ExtendBaseParams<{ filter: Filter<D> }>) {
public deleteMany<D = InnerDoc, T = NoInfer<D>>(
params: ExtendBaseParams<{ filter: Filter<T> }>
) {
return this.$$action<{ deletedCount: number }>('deleteMany', params)
}

Expand All @@ -278,3 +291,7 @@ export class MongoDBDataAPI<InnerDoc = any> {
return this.$$action<{ documents: T }>('pipeline', params)
}
}

export const createMongoDBDataAPI = (config: Config, axios?: AxiosInstance) => {
return new MongoDBDataAPI(config, void 0, axios)
}
Loading