Coder Social home page Coder Social logo

apollo-datasource-cosmosdb's Introduction

Apollo DataSource for CosmosDB

This is a CosmosDB DataSource for the Apollo GraphQL Server. It was adapted from the MongoDB Data Source project.

Usage

Use by creating a new class, inheriting from CosmosDataSource passing in the CosmosDb container instance (created from the CosmosDB Javascript API). Use a separate DataSource for each data type.

Example:

data-sources/Users.ts

export interface UserDoc {
  id: string; // a string id value is required for entities using this library
  name: string;
}

export class UserDataSource extends CosmosDataSource<UserDoc> {}
export class PostDataSource extends CosmosDataSource<PostDoc> {}

server.ts

import { CosmosClient } from "@azure/cosmos";
import { CosmosDataSource } from "apollo-datasource-cosmosdb";

const cosmosClient = new CosmosClient({
  endpoint: "https://my-cosmos-db.documents.azure.com:443/",
  key: "--------key-goes-here---==",
});
const cosmosContainer = cosmosClient.database("MyDatabase").container("Items");

import UserDataSource from "./data-sources/Users.js";
import PostDataSource from "./data-sources/Users.js";

const server = new ApolloServer({
  typeDefs,
  resolvers,
  dataSources: () => ({
    users: new UserDataSource(cosmosContainer),
    posts: new PostDataSource(cosmosContainer),
  }),
});

Context

It is often useful to define a context. See Apollo docs on context To make this strongly typed, there is a second type paramater on the CosmosDbDataSource:

interface MyQueryContext {
  currentUserId: string
}

/////

const userDataSource extends CosmosDataSource<UserDoc, MyQueryContext> {}

Custom Queries

CosmosDataSource exposes a findManyByQuery method that accepts a ComosDB SQL query either as a string or a SqlQuerySpec object containing the query and a parameter collection. This can be used directly in the resolvers, but probably better to create wrappers that hide the query details.

Creating a derived class with custom query methods, you can hide all of your query logic in the DataSource class:

export class UserDataSource extends CosmosDataSource<UserDoc, ApolloContext> {
  findManyByGroupID = async (group_id, args: FindArgs = {}) => {
    log.debug(`UserDataSource: getGroupUsers ${group_id}`);
    const query = `SELECT * FROM c where c.type = "User" and exists(select * from g in c.groups where g = @group_id) `;
    const results = await this.findManyByQuery(
      {
        query,
        parameters: [{ name: "@group_id", value: group_id }],
      },
      args
    );
    log.debug(`Result count ${results.resources.length}`);
    return results.resources;
  };
  findOneByUserName = async (userName: string, args: FindArgs = {}) => {
    const results = await this.findManyByQuery(
      {
        query: `SELECT * FROM c WHERE c.userName = @userName AND c.type = 'User'`,
        parameters: [{ name: "@userName", value: userName }],
      },
      args
    );
    if (results.resources && results.resources.length)
      return results.resources[0];
    return undefined;
  };
}

Write Operations

This DataSource has some built in mutation methods to create, update and delete items. They can be used directly in resolvers or wrapped with custom methods.

await context.dataSources.users.createOne(userDoc);

await context.dataSources.users.updateOne(userDoc);

await context.dataSources.users.updateOnePartial(user_id, { name: "Bob" });

await context.dataSources.users.deleteOne(userId);

The data loader (and cache, if used) are updated after mutation operations.

Batching

Batching is provided on all queries using the DataLoader library.

Caching

Caching is available on an opt-in basis by passing a ttl option on queries.

Typescript

This library is written in Typescript and exports full type definitions, but usable in pure Javascript as well. This works really well with GraphQL Codegen's typed resolvers.

API

const thisUser = await users.findOneById(id: string, {ttl})  // => Promise<T | undefined>

const userPair = await users.findManyByIds([id1, id2], {ttl}) // => Promise<(T | undefined)[]>

await users.deleteFromCacheById(id}) // => Promise<void>

// query method; note that this returns the CosmosDB FeedResponse object because sometimes this extra information is useful
const userListResponse = await users.findManyByQuery('SELECT * from c where c.type="User"', {ttl, requestOptions}) // => Promise<FeedResponse<T>>
console.log(userListResponse.resources) // user array from query

// create method returns the CosmosDB ItemResponse object
const createResponse = await users.createOne(newUser) // => Promise<ItemResponse<T>>
console.log(createResponse.resource)  // user object returned from create, with CosmosDB-added values

const updateUserResponse = await users.updateOne(thisUser) // => Promise<ItemResponse<T>>

const updatePartialResponse = await users.updateOnePartial(id, {firstName: "Bob"}) // => Promise<ItemResponse<T>>
console.log(updatePartialResponse.resource) // full user object from DB after updates

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.