How type BehaviorSubject of rxjs with type predicate? - rxjs

Here is my code. I am getting the error below.
type Filters = {
type: 'expenses' | 'income'
week: string
month: string
category: string
}
class SubjectManager {
private subject$: BehaviorSubject<Filters> = new BehaviorSubject({
category: 'all',
week: '1',
month: '10',
type: 'expenses'
})
}
Error
Type 'Filters' cannot be assigned to type '{ category: string; week: string; month: string; type: "expenses";
How can I fix this error?

This works:
class SubjectManager {
private subject$ = new BehaviorSubject<Filters>({
category: 'all',
week: '1',
month: '10',
type: 'expenses'
})
}
The original code doesn't work because the object inside BehaviorSubject has type { type: 'expenses', ... }, not { type: 'expenses' | 'income', ... }.

Related

Category page in elastic ui and nextjs (typescript)

I'm integrating Elasticsearh UI with nextjs as per the tutorial codesandbox, the search and autocomplete page works fine. However I am having problems in the category page.
When using default data everything works fine, But when using data from Elastic local I get the error:
# Browser
An unexpected error occurred: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
# command line
error - TypeError: Cannot read properties of null (reading 'name')
# ...
error - TypeError: Cannot convert undefined or null to object
and
TS2322: Type '{ searchQuery: { filters: { field: string; values: any[]; }[]; facets: { price: { type: string; ranges: ({ from: number; to: number; name: string; } | { from: number; name: string; to?: undefined; })[]; }; categories: { ...; }; manufacturer: { ...; }; rating: { ...; }; }; result_fields: { ...; }; disjunctiveFacets: ...' is not assignable to type 'SearchDriverOptions'. Types of property 'searchQuery' are incompatible. Type '{ filters: { field: string; values: any[]; }[]; facets: { price: { type: string; ranges: ({ from: number; to: number; name: string; } | { from: number; name: string; to?: undefined; })[]; }; categories: { type: string; size: number; }; manufacturer: { ...; }; rating: { ...; }; }; result_fields: { ...; }; disjunctive...' is not assignable to type 'SearchQuery'. Type '{ filters: { field: string; values: any[]; }[]; facets: { price: { type: string; ranges: ({ from: number; to: number; name: string; } | { from: number; name: string; to?: undefined; })[]; }; categories: { type: string; size: number; }; manufacturer: { ...; }; rating: { ...; }; }; result_fields: { ...; }; disjunctive...' is not assignable to type '{ conditionalFacets?: Record<string, ConditionalRule>; filters?: Filter[]; facets?: Record<string, FacetConfiguration>; disjunctiveFacets?: string[]; disjunctiveFacetsAnalyticsTags?: string[]; result_fields?: Record<...>; search_fields?: Record<...>; }'. Types of property 'filters' are incompatible. Type '{ field: string; values: any[]; }[]' is not assignable to type 'Filter[]'. Property 'type' is missing in type '{ field: string; values: any[]; }' but required in type 'Filter'. index.d.ts(29, 5): 'type' is declared here. SearchProvider.d.ts(9, 5): The expected type comes from property 'config' which is declared here on type 'IntrinsicAttributes & SearchProviderProps'
I also had a few similar errors before and, related to facets due to wrong declaration of fields in document.py (I use Django to generate the index).
Maybe I was missing flelds or it was formatted wrong. Any help is highly appreciated.
I've searched a lot and most of the tutorials are just about the search page. With nextjs, I changed Category.js to [category].tsx. Error caused by this line: filters: [{ field: 'parent_category', values: [category] }],
# /category/[category].tsx
const categoryPageconfig = (category) => ({
...Config,
searchQuery: {
...Config.searchQuery,
filters: [{ field: 'parent_category', values: [category] }],
facets: {
...Config.searchQuery.facets,
price: {
type: 'range',
ranges: [
{ from: 0, to: 200000, name: 'Under 200.000' },
{ from: 200000, to: 500000, name: '200.000 to 500.000' },
{ from: 500000, to: 1000000, name: '500.000 to 1.000.000' },
{ from: 1000000, to: 2000000, name: '1.000.000 to 2.000.0000' },
{ from: 2000000, to: 5000000, name: '2.000.000 to 5.000.000' },
{ from: 5000000, name: '5.000.000 & Above' },
],
},
},
},
});
export default function CategoryPage(props) {
const router = useRouter();
const { category } = router.query;
# const category = props?.match?.params.category;
return (
<>
<BrowseHeader category={category} />
<SearchProvider config={categoryPageconfig(category)}>
...
</SearchProvider>
</>
);
}

How to implement a reference type on a ObjectType that comes from a class in GraphQL pothos (Next JS)

I am trying to reference the money type onto my cart type I have tried a few different ways and keep getting this error:
:Ref function String() { [native code] } has not been implemented
In my project, I am importing my types as classes as recommended in the docs,
My types:
That are in a separate file from my server
export class CartItem {
id: string;
name: string;
price: number;
quantity: number;
constructor(id: string, name: string, price: number, quantity: number) {
this.id = id;
this.name = name;
this.price = price;
this.quantity = quantity;
}
}
export class Cart {
id: string;
items?: CartItem[];
constructor(id: string, items?: CartItem[]) {
this.id = id;
this.items = items;
}
}
export class Money {
amount: number;
formatted: string;
constructor(amount: number, formatted: string) {
this.amount = amount;
this.formatted = formatted;
}
}
Here is my server:
I have two comments showing where I am likely failing
In my Cart Objecttype
const MoneyType
import { createServer } from '#graphql-yoga/node'
import SchemaBuilder from "#pothos/core"
import { CartItem, Cart, Money } from 'gql';
const CARTS = [
{
id: '1',
items: [
{
id: '1',
name: 'Item 1',
price: 10,
quantity: 1
},
{
id: '2',
name: 'Item 2',
price: 20,
quantity: 2
}
]
},
{
id: '2',
items: [
{
id: '3',
name: 'Item 3',
price: 30,
quantity: 3
},
{
id: '4',
name: 'Item 4',
price: 40,
quantity: 4
}
]
}
]
const builder = new SchemaBuilder({});
builder.objectType(Cart, {
name: "Cart",
description: "A cart",
fields: (t) => ({
id: t.exposeString('id', {}),
items: t.field({
type: [CartItem],
resolve: (cart) => cart.items ?? [],
}),
// This is the field that we want to USE TO REFERENCE
// subTotal: t.field({
// type: Money,
// resolve: (cart) => {
// const total = cart.items?.reduce((acc, item) => acc + item.price * item.quantity, 0) ?? 0;
// return new Money(total, `$${total}`);
// }
// })
}),
});
builder.objectType(CartItem, {
name: "CartItem",
description: "A cart item",
fields: (t) => ({
id: t.exposeString('id', {}),
name: t.exposeString('name', {}),
price: t.exposeInt('price', {}),
quantity: t.exposeInt('quantity', {}),
}),
});
// make a reference to the Money type THAT DOESEN'T WORK
const MoneyType = builder.objectRef<MoneyShape>("Money");
builder.objectType(Money, {
name: "Money",
description: "A money",
fields: (t) => ({
amount: t.exposeInt('amount', {}),
formatted: t.field({
type: String,
resolve: (money) => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(money.amount),
}),
}),
});
builder.queryType({
fields: (t) => ({
cart: t.field({
type: Cart,
nullable: true,
args: {
id: t.arg.id({ required: true, description: "the id of the cart" }),
},
resolve: (_, { id }) => {
const cart = CARTS.find((cart) => cart.id === id);
if (!cart) {
throw new Error(`Cart with id ${id} not found`)
}
return cart
}
}),
carts: t.field({
type: [Cart],
resolve: () => CARTS
}),
}),
})
const server = createServer({
endpoint: '/api',
schema: builder.toSchema(),
})
export default server;
Unfortunately Pothos' error messages are not very good when it comes to the type property. Scalars in Pothos are referenced by their name, so you should put them in quotation marks:
builder.objectType(Money, {
name: "Money",
description: "A money",
fields: (t) => ({
amount: t.exposeInt("amount", {}),
formatted: t.field({
type: "String",
resolve: (money) =>
new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
}).format(money.amount),
}),
}),
});
Alternatively, you can also use t.string:
builder.objectType(Money, {
name: "Money",
description: "A money",
fields: (t) => ({
amount: t.exposeInt("amount", {}),
formatted: t.string({
resolve: (money) =>
new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
}).format(money.amount),
}),
}),
});
Some additional hints:
I would move the formatter out of the resolver as you only have to create one instance.
I personally don't like the class way of doing things in Pothos, as my types mostly come from Prisma. It works really well, if you have service classes for every object type, but if you just have them to wrap things, it is a lot of overhead. You could consider removing the Money class and using number instead:
const moneyFormatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
})
const Money = builder.objectRef<number>('Money').implement({
description: "A money",
fields: (t) => ({
amount: t.int({ resolve: money => money }),
formatted: t.string({
resolve: (money) =>
moneyFormatter.format(money),
}),
}),
});
This issue occurred to me even when I defined my scalars correctly. enter link description herethis solution helped me to resolve the issue.
Quoted from original Answer
The fix is to define the first query type: builder.queryType({}). You
must only do this once, and only once. Usually, it's smart to put this
next to your builder initialization.
Original Answer

#ibm-cloud/cloudant: includeDocs: true, still not able to get the entire details of the documents

service.postAllDocs({
db: 'orders',
includeDocs: true,
limit: 10
}).then(response => { console.log(response.result)});
result only returns:
id, key and value(only contains rev)
To fetch the first 10 docs from the database, including the doc bodies, this code works:
const { CloudantV1 } = require('#ibm-cloud/cloudant')
const client = CloudantV1.newInstance()
const DBNAME = 'orders'
const main = async function () {
const response = await client.postAllDocs({ db: DBNAME, includeDocs: true, limit: 10 })
console.log(response.result.rows)
}
main()
This produces the following output:
[
{
id: '1',
key: '1',
value: { rev: '1-0fdc08a2625917344e37eb91661a5568' },
doc: {
_id: '1',
_rev: '1-0fdc08a2625917344e37eb91661a5568',
fruit: 'banana'
}
},
{
id: '2',
key: '2',
value: { rev: '1-8c4d4385540143ea87f8663193105425' },
doc: {
_id: '2',
_rev: '1-8c4d4385540143ea87f8663193105425',
fruit: 'apple'
}
}
]
The document body is under the doc attribute in each object.

How to implement interface using GraphQL and node

I want to achieve the fields of one object type within another object type
Here is my schema file.
const Films = new GraphQLInterfaceType({
name: 'films',
fields: () => ({
id:{
type: GraphQLID
},
name: {
type: GraphQLString,
},
})
})
const MovieStream = new GraphQLObjectType({
name: 'MovieStream',
interfaces: () => [Films],
fields: () => ({
id: {
type: GraphQLID,
},
movie_id: {
type: GraphQLString,
},
})
})
Here I am trying to use the interface. But It shows error:
{
"errors": [
{
"message": "Query root type must be Object type, it cannot be { __validationErrors: undefined, __allowedLegacyNames: [], _queryType: undefined, _mutationType: undefined, _subscriptionType: undefined, _directives: [#include, #skip, #deprecated], astNode: undefined, extensionASTNodes: undefined, _typeMap: { __Schema: __Schema, __Type: __Type, __TypeKind: __TypeKind, String: String, Boolean: Boolean, __Field: __Field, __InputValue: __InputValue, __EnumValue: __EnumValue, __Directive: __Directive, __DirectiveLocation: __DirectiveLocation, films: films, ID: ID, Date: Date, JSON: JSON, MovieStream: MovieStream }, _possibleTypeMap: {}, _implementations: { films: [] } }."
},
{
"message": "Expected GraphQL named type but got: { __validationErrors: undefined, __allowedLegacyNames: [], _queryType: undefined, _mutationType: undefined, _subscriptionType: undefined, _directives: [#include, #skip, #deprecated], astNode: undefined, extensionASTNodes: undefined, _typeMap: { __Schema: __Schema, __Type: __Type, __TypeKind: __TypeKind, String: String, Boolean: Boolean, __Field: __Field, __InputValue: __InputValue, __EnumValue: __EnumValue, __Directive: __Directive, __DirectiveLocation: __DirectiveLocation, films: films, ID: ID, Date: Date, JSON: JSON, MovieStream: MovieStream }, _possibleTypeMap: {}, _implementations: { films: [] } }."
}
]
}
Here is Query type:
const QueryRoot = new GraphQLObjectType({
name: 'Query',
fields: () => ({
getContentList:{
type: new GraphQLList(contentCategory),
args: {
id: {
type: GraphQLInt
},
permalink: {
type: GraphQLString
},
language: {
type: GraphQLString
},
content_types_id: {
type: GraphQLString
},
oauth_token:{
type: GraphQLString
}
},
resolve: (parent, args, context, resolveInfo) => {
var category_flag = 0;
var menuItemInfo = '';
user_id = args.user_id ? args.user_id : 0;
// console.log("context"+context['oauth_token']);
return AuthDb.models.oauth_registration.findAll({attributes: ['oauth_token', 'studio_id'],where:{
// oauth_token:context['oauth_token'],
$or: [
{
oauth_token:
{
$eq: context['oauth_token']
}
},
{
oauth_token:
{
$eq: args.oauth_token
}
},
]
},limit:1}).then(oauth_registration => {
var oauthRegistration = oauth_registration[0]
// for(var i = 0;i<=oauth_registration.ength;i++){
if(oauth_registration && oauthRegistration && oauthRegistration.oauth_token == context['oauth_token'] || oauthRegistration.oauth_token == args.oauth_token){
studio_id = oauthRegistration.studio_id;
return joinMonster.default(resolveInfo,{}, sql => {
return contentCategoryDb.query(sql).then(function(result) {
return result[0];
});
} ,{dialect: 'mysql'});
}else{
throw new Error('Invalid OAuth Token');
}
})
},
where: (filmTable, args, context) => {
return getLanguage_id(args.language).then(language_id=>{
return ` ${filmTable}.permalink = "${args.permalink}" and ${filmTable}.studio_id = "${studio_id}" and (${filmTable}.language_id = "${language_id}" OR ${filmTable}.parent_id = 0 AND ${filmTable}.id NOT IN (SELECT ${filmTable}.parent_id FROM content_category WHERE ${filmTable}.permalink = "${args.permalink}" and ${filmTable}.language_id = "${language_id}" and ${filmTable}.studio_id = "${studio_id}"))`
})
},
}
})
})
module.exports = new GraphQLSchema({
query: QueryRoot
})
Please help me out. have i done something wrong in the use of interface?
I have found the answer through this post
Is it possible to fetch data from multiple tables using GraphQLList
Anyone please tell me the exact way to use the interface in my code.
Although the error you have printed does not really relate to interfaces implementations, in order for you to use interfaces, you have to implement the methods/types the interface references. So in your situation your object MovieStream is missing the type name that you refer in the object Films.
Your code should look something like:
const Films = new GraphQLInterfaceType({
name: 'films',
fields: () => ({
id:{
type: GraphQLID
},
name: {
type: GraphQLString,
},
})
})
const MovieStream = new GraphQLObjectType({
name: 'MovieStream',
interfaces: () => [Films],
fields: () => ({
id: {
type: GraphQLID,
},
name: {
type: GraphQLString // You're missing this!
},
movie_id: {
type: GraphQLString,
},
})
})
Now back to the error you have printed "message": "Query root type must be Object type, it cannot be...
This seems to be related to your QueryRoot object, it seems that GraphQLSchema is not recognizing the root object. If this issue is still there once you fix the interface, have a look at this answer here

GraphQL association issue

Before diving into the code, here is a high-level explanation of my question:
In my GraphQL schema, I have two root types: Developers and Projects. I'm attempting to find all developers who are part of a given project. The query might look like this:
{
project(id:2) {
title
developers {
firstName
lastName
}
}
}
Currently, I'm getting a null value for developers.
Dummy data
const developers = [
{
id: '1',
firstName: 'Brent',
lastName: 'Journeyman',
projectIds: ['1', '2']
},
{
id: '2',
firstName: 'Laura',
lastName: 'Peterson',
projectIds: ['2']
}
]
const projects = [
{
id: '1',
title: 'Experimental Drug Bonanza',
company: 'Pfizer',
duration: 20,
},
{
id: '2',
title: 'Terrible Coffee Holiday Sale',
company: 'Starbucks',
duration: 45,
}
]
So, Brent has worked on both projects. Laura has worked on the second project. My issue is in the resolve function in ProjectType. I've tried many queries, but none seem to work.
ProjectType
const ProjectType = new GraphQLObjectType({
name: 'Project',
fields: () => ({
id: { type: GraphQLID },
title: { type: GraphQLString },
company: { type: GraphQLString },
duration: { type: GraphQLInt },
developers: {
type: GraphQLList(DeveloperType),
resolve(parent, args) {
///////////////////////
// HERE IS THE ISSUE //
//////////////////////
return _.find(developers, { id: ? });
}
}
})
})
DeveloperType
const DeveloperType = new GraphQLObjectType({
name: 'Developer',
fields: () => ({
id: { type: GraphQLID },
firstName: { type: GraphQLString },
lastName: { type: GraphQLString }
})
})
So you need to return all the developers having current project's id in their .projectIds, right?
First, _.find cannot help since it returns first matched element and you need to get array with developers(since field has GraphQLList type).
So how about
resolve(parent, args) {
return developers.filter(
({projectIds}) => projectIds.indexOf(parent.id) !== -1
);
}

Resources