datopian / portal.js.bak

🌀 The JS data presentation framework. For a single dataset to a full catalog.
https://portal-78qurbwf9-datopian1.vercel.app/
MIT License
22 stars 2 forks source link

Connect CKAN API into Apollo GraphQL client #29

Closed anuveyatsu closed 4 years ago

anuveyatsu commented 4 years ago

Job story:

When building frontend for my CKAN portal using this framework I want to configure my CKAN backend so that all the metadata shows up in the portal

Acceptance criteria

Tasks

Analysis

There are 2 ways of connecting CKAN API with Apollo:

  1. Build Apollo Server with data source as CKAN API.
  2. Use REST link to connect REST API to Apollo client so no server is needed: https://www.apollographql.com/docs/link/links/rest/

Apollo client in Next.js (assuming there is a graphql server):

// `/lib/apolloClient.js`
import { useMemo } from 'react';
import getConfig from 'next/config';
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';

let apolloClient;

function createApolloClient() {
  const { publicRuntimeConfig } = getConfig();
  return new ApolloClient({
    ssrMode: typeof window === 'undefined',
    link: x // This is where we connect the API...,
    cache: new InMemoryCache(),
  });
}

export function initializeApollo(initialState = null) {
  const _apolloClient = apolloClient ?? createApolloClient();

  // If your page has Next.js data fetching methods that use Apollo Client, the initial state
  // gets hydrated here
  if (initialState) {
    _apolloClient.cache.restore(initialState);
  }
  // For SSG and SSR always create a new Apollo Client
  if (typeof window === 'undefined') return _apolloClient;
  // Create the Apollo Client once in the client
  if (!apolloClient) apolloClient = _apolloClient;

  return _apolloClient;
}

export function useApollo(initialState) {
  const store = useMemo(() => initializeApollo(initialState), [initialState]);
  return store;
}

Apollo Server

server:

const { ApolloServer } = require('apollo-server');
const typeDefs = require('./schema');
const { createStore } = require('./utils');

const ckanAPI = require('...');

const store = createStore();

const server = new ApolloServer({
  typeDefs,
  dataSources: () => ({
    ckanAPI: new ckanAPI()
  })
});

server.listen().then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`);
});

ckanAPI:

const { DataSource } = require('apollo-datasource');

class ckanAPI extends DataSource {
  constructor({ store }) {
    super();
    this.store = store;
  }

  /**
   * This is a function that gets called by ApolloServer when being setup.
   * This function gets called with the datasource config including things
   * like caches and context. We'll assign this.context to the request context
   * here, so we can know about the user making requests
   */
  initialize(config) {
    this.context = config.context;
  }

  // Search method that searches CKAN portal
  async search({ query }) {
    // ...
    return result;
  }

  async getDataPackage({ name }) {
    // ...
    return datapackage;
  }
}

module.exports = ckanAPI;

schema:

const { gql } = require('apollo-server');

const typeDefs = gql`
  type DataPackage {
    id: ID!
    name: String
    title: String
    resources: Resources
  }
`;

module.exports = typeDefs;

Without Apollo Server

References:

anuveyatsu commented 4 years ago

Closing this as FIXED: