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

Change to use declarative types with @graphql-tools/schema #362

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 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 javascript/MLE-Demo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ For more information, please refer to our [blog post](https://medium.com/@salma.
## Acknowledgements

- Author/Contributors - Lucas Braun, Principal Program Manager, Salma Elbekraoui, MLE team intern
- Last Updated By/Date - Lucas Braun, Principal Program Manager, Salma Elbekraoui, MLE team intern, July 2023
- Last Updated By/Date - Lucas Braun, Principal Program Manager, Salma Elbekraoui, MLE developer, June 2024
225 changes: 81 additions & 144 deletions javascript/MLE-Demo/book-schema.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*Copyright 2023 Oracle and/or its affiliates.
/*Copyright 2024 Oracle and/or its affiliates.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -13,151 +13,88 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import {
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLInt,
GraphQLFloat,
GraphQLList
} from 'graphql';
import 'mle-js-fetch';
import oracledb from 'mle-js-oracledb';

const BASE_URL = "https://www.googleapis.com/books/v1/volumes?q=";

const getBooks = async (SEARCH_URL) => {
import { makeExecutableSchema } from 'graphql-tools-schema';
import 'mle-js-fetch';
import oracledb from 'mle-js-oracledb';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might no longer be necessary to import oracledb. Instead of

const connection = oracledb.defaultConnection();
const result = connection.execute()

you can simply reference the session object in the global scope. This will make it easier later on to bundle the code. Unless of course something else in the oracledb namespace is needed that MLE doesn't provide in the global scope.


const BASE_URL = "https://www.googleapis.com/books/v1/volumes?q=";

const typeDefs = `
type ImageLinks {
thumbnail: String
}

type Author {
name: String
}

type VolumeInfo {
title: String
subtitle: String
publisher: String
description: String
authors: [Author]
publishedDate: String
imageLinks: ImageLinks
averageRating: Float
pageCount: Int
language: String
}

type Book {
id: String
kind: String
etag: String
volumeInfo: VolumeInfo
stock: Int
}

type Volumes {
kind: String
totalItems: Int
items: [Book]
}

type Query {
library(research: String): Volumes
}
`;

const resolvers = {
Query: {
library: async (_, { research }) => {
return await getBooks(research);
}
},
VolumeInfo: {
authors: (volumeInfo) => volumeInfo.authors || [],
},
Book: {
stock: async (book) => {
const conn = oracledb.defaultConnection();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please consider using session.execute() here.

const result = await conn.execute('SELECT stock FROM inventory WHERE id = :id', [book.id], { outFormat: oracledb.OUT_FORMAT_OBJECT });
if (result.rows.length > 0) {
return result.rows[0].STOCK;
} else {
return 0;
}
}
},
};

const getBooks = async (SEARCH_URL) => {
const conn = oracledb.defaultConnection();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please consider using session.execute() instead

conn.execute(`
begin
utl_http.set_wallet('file:/<absolute-path-to-your-wallet-directory>');
end;
await conn.execute(`
begin
utl_http.set_wallet('file:/<absolute-path-to-your-wallet-directory>');
end;
`);

const response = await fetch(`${BASE_URL}${SEARCH_URL}`, { credentials: "include" });

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

beginning with Oracle Database 23.3 it should no longer be necessary to use createntials: include

const result = await response.json();
return result;
}

const imageLinks = new GraphQLObjectType({
name: 'IMAGE_LINKS',
fields: () => ({
thumbnail: {
type: GraphQLString,
},
})
});

const author = new GraphQLObjectType({
name: 'AUTHOR',
fields: () => ({
name: {
type: GraphQLString,
resolve: (author) => author || "Unknown",
},
})
});

const volumeInfo = new GraphQLObjectType({
name: 'VOLUME_INFO',
fields: () => ({
title: {
type: GraphQLString,
},
subtitle: {
type: GraphQLString,
},
publisher: {
type: GraphQLString,
},
description: {
type: GraphQLString,
},
authors: {
type: new GraphQLList(author),
resolve: (volumeInfo) => volumeInfo.authors || [],
},
publishedDate: {
type: GraphQLString,
},
imageLinks: {
type: imageLinks,
},
averageRating: {
type: GraphQLFloat,
},
pageCount: {
type: GraphQLInt,
},
language: {
type: GraphQLString,
}
})
});

const book = new GraphQLObjectType({
name: 'BOOK',
fields: () => ({
id: {
type: GraphQLString,
description: 'The id of the book.',
},
kind: {
type: GraphQLString,
description: 'The kind of the book.',
},
etag: {
type: GraphQLString,
description: 'The etag of the book.',
},
volumeInfo: {
type: volumeInfo,
},
stock: {
type: GraphQLInt,
resolve: (book) => {
const result = session.execute('select stock from inventory where id = :id', [book.id]);
if (result.rows.length > 0) {
return result.rows[0][0];
} else {
return 0;
}
}
},
})
});

const volumes = new GraphQLObjectType({
name: 'VOLUMES',
fields: () => ({
kind: {
type: GraphQLString,
},
totalItems: {
type: GraphQLInt,
},
items: {
type: new GraphQLList(book),
},
}),
});

const queryType = new GraphQLObjectType({
name: 'Query',
fields: () => ({
library: {
args: {
research: {
type: GraphQLString,
},
},
type: volumes,
resolve: async (_source, {research}) => await getBooks(research),
},
}),
});

export const schema = new GraphQLSchema({
query: queryType,
types: [volumes, book, volumeInfo, author, imageLinks]
});
};

export const schema = makeExecutableSchema({
typeDefs,
resolvers
});