I was trying to use sequalize seed to initialize the table rows, but I got error return:
column "createdAt" of relation "users" does not exist
It actually is "created_at" as the field, so my question is that how can I seed the table with snake or underscore option?
My seed code as following:
"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.bulkInsert(
"users",
[
{
firstname: "John",
lastname: "Doe",
email: "demo#demo.com",
createdAt: new Date(),
updatedAt: new Date()
}
],
{}
);
},
down: (queryInterface, Sequelize) => {
return queryInterface.bulkDelete("users", null, {});
}
};
You pass those information while defining your configurations for database connection like below.
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
config.define = {
"timestamps":true,
"createdAt":"created_at",
"updatedAt":"updated_at"
}
sequelize = new Sequelize(config.database, config.username, config.password,config );
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
Here config is your db configuration. You add other configuration on a separate define
As you can see all in a documentation queryInterface methods work with tables and not models so you should use real column names instead of model props.
Related
I don't know why in another page, I use this way just different query and I can see data in view page source, but in this page , it not work. I wondering it cause I use localStorage value as params, i don't think problem come from query.
interface Props {
__typename?: 'ProductOfBill';
amount: number,
name: string,
totalPrice: number,
type: string,
unitPrice: number,
}
const Cart = () => {
const [products,setProducts] = useState<Props[]>([])
const { data } = useGetSomeProductQuery({
variables: { productList: productListForBill()},
notifyOnNetworkStatusChange: true
});
useEffect(() =>{
if(data?.getSomeProduct){
setProducts(data.getSomeProduct)
}
},[data])
return (
<>
...
</>
);
};
export const getStaticProps: GetStaticProps = async () => {
const apolloClient = initializeApollo();
await apolloClient.query<GetSomeProductQuery>({
query: GetSomeProductDocument,
variables: { productList: productListForBill() },
});
return addApolloState(apolloClient, {
props: {},
});
};
export default Cart;
I get localStorage value from this method.
export const productListForBill = () : GetProductForBill[] =>{
const returnEmtpyArray : GetProductForBill[] = []
if(typeof window !== "undefined"){
if(localStorage.getItem("products"))
{
const tempProduct = JSON.parse(localStorage.getItem("products") || "")
if(Array.isArray(tempProduct)){
return tempProduct
}
}
}
return returnEmtpyArray
}
and I custom Apollo Client like doc of Nextjs in github
import { useMemo } from 'react'
import { ApolloClient, HttpLink, InMemoryCache, NormalizedCacheObject } from '#apollo/client'
import merge from 'deepmerge'
import isEqual from 'lodash/isEqual'
export const APOLLO_STATE_PROP_NAME = '__APOLLO_STATE__'
interface IApolloStateProps {
[APOLLO_STATE_PROP_NAME]?: NormalizedCacheObject
}
let apolloClient : ApolloClient<NormalizedCacheObject>
function createApolloClient() {
return new ApolloClient({
//type of "window"=== undifined
ssrMode: true,
link: new HttpLink({
uri: "http://localhost:4000/graphql",
credentials: "include",
}),
cache: new InMemoryCache()
)}
}
export function initializeApollo(initialState : NormalizedCacheObject | null = null) {
const _apolloClient = apolloClient ?? createApolloClient()
if (initialState) {
const existingCache = _apolloClient.extract()
cache
const data = merge(existingCache, initialState, {
arrayMerge: (destinationArray, sourceArray) => [
...sourceArray,
...destinationArray.filter((d) =>
sourceArray.every((s) => !isEqual(d, s))
),
],
})
_apolloClient.cache.restore(data)
}
if (typeof window === 'undefined') return _apolloClient
if (!apolloClient) apolloClient = _apolloClient
return _apolloClient
}
export function addApolloState(client : ApolloClient<NormalizedCacheObject>, pageProps: { props: IApolloStateProps }) {
if (pageProps?.props) {
pageProps.props[APOLLO_STATE_PROP_NAME] = client.cache.extract()
}
return pageProps
}
export function useApollo(pageProps : IApolloStateProps) {
const state = pageProps[APOLLO_STATE_PROP_NAME]
const store = useMemo(() => initializeApollo(state), [state])
return store
}
Answering
Cannot see data in view page source even though Cache of Apollo Client have data
These are client side methods, value will not be visible in view source but in evaluated source, look in the elements panel in chrome.
This question already has an answer here:
next-redux-wrapper TypeError: nextCallback is not a function error in wrapper.getServerSideProps
(1 answer)
Closed 1 year ago.
Using redux with SSR in Next.js(Typescript) using next-redux-wrapper, but getting error on this line
async ({ req, store })
Says, Type 'Promise' provides no match for the signature '(context: GetServerSidePropsContext<ParsedUrlQuery, PreviewData>): Promise<GetServerSidePropsResult<{ [key: string]: any; }>>
Property 'req' does not exist on type 'Store<EmptyObject & { filterReducer: never; }, any> & { dispatch: unknown; }'.
Property 'store' does not exist on type 'Store<EmptyObject & { filterReducer: never; }, any> & { dispatch: unknown; }'
Here is my SSR code:-
export const getServerSideProps: GetServerSideProps = wrapper.getServerSideProps(async ({ req, store }) => {
let { query } = req
let searchCategory = query.category?.toString().toLowerCase().replace(/ /g, "-");
const apolloClient = initializeApollo();
const response = await apolloClient.query({
query: GET_PRODUCT_BY_CATEGORY,
variables: {
numProducts: 10,
category: searchCategory
}
});
await store.dispatch(getProducts(response));
});
You're calling wrapper.getServerSideProps in a wrong way.
Try like the following:
export const getServerSideProps = wrapper.getServerSideProps(
store => async ({req, res, query}) => {
// do your stuff with store and req
}
);
If you're looking for a working demo, you can visit my old answer
This code base could help you. ("next": "10.1.3")
Try using getInitialProps instead of getServerSideProps.
This works in my case. Like code below:
Try
in _app.js
import { wrapper } from '/store';
function MyApp(props) {
const { Component, pageProps } = props;
...
return (
<Component {...pageProps} />
)
}
App.getInitialProps = async props => {
const { Component, ctx } = props;
const pageProps = Component.getInitialProps
? await Component.getInitialProps(ctx)
: {};
//Anything returned here can be accessed by the client
return { pageProps: pageProps, store: ctx.store };
};
export default wrapper.withRedux(App);
store.js file:
const makeStore = props => {
if (!isEmpty(props)) {
return createStore(reducer, bindMiddleware([thunkMiddleware]));
} else {
const { persistStore, persistReducer } = require('redux-persist');
const persistConfig = {
key: 'root',
};
const persistedReducer = persistReducer(persistConfig, reducer); // Create a new reducer with our existing reducer
const store = createStore(
persistedReducer,
bindMiddleware([thunkMiddleware])
); // Creating the store again
store.__persistor = persistStore(store); // This creates a persistor object & push that persisted object to .__persistor, so that we can avail the persistability feature
return store;
}
};
// Export the wrapper & wrap the pages/_app.js with this wrapper only
export const wrapper = createWrapper(makeStore);
in your page:
HomePage.getInitialProps = async ctx => {
const { store, query, res } = ctx;
};
Developing entirely local, I followed the tutorial here: https://scotch.io/tutorials/super-simple-graphql-with-node#toc-creating-the-graphql-server
Hardly any modification, only to restrict the focus to a "product" table. No "User" or "Recipe" table.
It appears the only issue I have now is retrieving the data from the MySQL DB.
Of course I've Googled and compared tutorials extensively. I've been through the code quite a bit as well to the point it's getting blurry.
If I change the "return" to {"name":"test"}, the data passes through to my local GraphQL dashboard perfectly.
models/index.js
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs.readdirSync(__dirname).filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
}).forEach(file => {
const model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
}); //console.log(db); Object.keys(db).forEach(modelName => { if (db[modelName].associate) { db[modelName].associate(db); } }); db.sequelize = sequelize; db.Sequelize = Sequelize;
module.exports = db;
'use strict';
module.exports = (sequelize, DataTypes) => {
const Product = sequelize.define('Product', {
name: DataTypes.STRING,
urlWordRef: DataTypes.STRING,
seoTitle: DataTypes.STRING,
seoDescription: DataTypes.STRING,
standardEquipment: DataTypes.STRING,
technicalSpecs: DataTypes.STRING
}, {});
Product.associate = function(models) {
// associations can be defined here
//Product.hasMany(models.RefProductOptions)
};
return Product;
};
// src/resolvers.js
const resolvers = {
Query: {
async products (root, { id }, { models }) {
return models.Products.findById(id) // *** THE LINE OF CODE WHICH FAILS ***
return {"name":"test"} // ** SUBSTITUTING THE ABOVE LINE WITH THIS - SUCCESS! ***
}
}
}
module.exports = resolvers
// src/schema.js
const { gql } = require('apollo-server')
const typeDefs = gql `
type Products {
id: Int!
name: String
urlWordRef: String
seoTitle: String
seoDescription: String
standardEquipment: String
technicalSpecs: String
}
type Query {
products(id: Int!): Products
}
`;
module.exports = typeDefs
// src/index.js
const { ApolloServer } = require('apollo-server')
const typeDefs = require('./schema')
const resolvers = require('./resolvers')
const models = require('../models')
const server = new ApolloServer({
typeDefs,
resolvers,
context: { models }
})
server.listen({port: 4000}).then(({ url }) => console.log('Server is running on localhost:4000'))
GraphQL query via the dashboard:
{
products(id: 1) {
name
}
}
I would expect that I can pass the id via the noted GRaphQL query above and get the correct table row result.
Alas, I'm ready to start coding with my forehead!
Error response in GraphQL:
{
"errors": [
{
"message": "Cannot read property 'findById' of undefined",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"products"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"TypeError: Cannot read property 'findById' of undefined",
" at products (/home/bob/graphql-server/src/resolvers.js:6:26)",
" at field.resolve (/home/bob/graphql-server/node_modules/graphql-extensions/dist/index.js:140:26)",
" at resolveFieldValueOrError (/home/bob/graphql-server/node_modules/graphql/execution/execute.js:486:18)",
" at resolveField (/home/bob/graphql-server/node_modules/graphql/execution/execute.js:453:16)",
" at executeFields (/home/bob/graphql-server/node_modules/graphql/execution/execute.js:294:18)",
" at executeOperation (/home/bob/graphql-server/node_modules/graphql/execution/execute.js:238:122)",
" at executeImpl (/home/bob/graphql-server/node_modules/graphql/execution/execute.js:85:14)",
" at Object.execute (/home/bob/graphql-server/node_modules/graphql/execution/execute.js:62:35)",
" at /home/bob/graphql-server/node_modules/apollo-server-core/dist/requestPipeline.js:239:46",
" at Generator.next (<anonymous>)",
" at /home/bob/graphql-server/node_modules/apollo-server-core/dist/requestPipeline.js:7:71",
" at new Promise (<anonymous>)",
" at __awaiter (/home/bob/graphql-server/node_modules/apollo-server-core/dist/requestPipeline.js:3:12)",
" at execute (/home/bob/graphql-server/node_modules/apollo-server-core/dist/requestPipeline.js:218:20)",
" at Object.<anonymous> (/home/bob/graphql-server/node_modules/apollo-server-core/dist/requestPipeline.js:156:42)",
" at Generator.next (<anonymous>)",
" at fulfilled (/home/bob/graphql-server/node_modules/apollo-server-core/dist/requestPipeline.js:4:58)",
" at <anonymous>",
" at process._tickCallback (internal/process/next_tick.js:188:7)"
]
}
}
}
],
"data": {
"products": null
}
}
I have created resolvers(userresolver.js) using 'apollo-resolvers' npm module as below.
import { createResolver } from 'apollo-resolvers';
import { isInstance } from 'apollo-errors';
const baseResolver = createResolver(
null,
(root, args, context, error) => isInstance(error) ? error : new UnknownError()
);
const users = baseResolver.createResolver(
(parent, args, { models, me } ) => {
return Object.values(models.users);
}
);
export default {
Query: {
users
}
}
;
These also work fine when I test the queries after starting the server.
I now want to do unit testing of the resolver functions.
I am not sure how to do that. Can someone help me on how to unit test the resolver functions. I am using mocha with chai for testing my project.
You can try easygraphql-tester, it has a method that'll help you to test the resolvers.
Here is the documentation of it.
Example:
Resolver
"use strict";
const license = (__, args, ctx) => {
const { key } = args;
return {
id: "1234",
body: "This is a test license",
description: `This is a description with key ${key}`
};
};
module.exports = {
Query: {
license
}
};
Test
"use strict";
const fs = require("fs");
const path = require("path");
const { expect } = require("chai");
const EasyGraphQLTester = require("easygraphql-tester");
const resolvers = require("../resolvers");
const schemaCode = fs.readFileSync(
path.join(__dirname, "..", "schema.gql"),
"utf8"
);
describe("Test resolvers", () => {
let tester;
beforeAll(() => {
tester = new EasyGraphQLTester(schemaCode, resolvers);
});
it("should return expected values", async () => {
const query = `
query GET_LICENSE($key: String!) {
license(key: $key) {
id
body
description
}
}
`;
const args = {
key: "1234"
};
const result = await tester.graphql(query, {}, {}, args);
expect(result.data.license.id).to.be.eq("1234");
expect(result.data.license.body).to.be.eq("This is a test license");
expect(result.data.license.description).to.be.eq(
`This is a description with key ${args.key}`
);
});
});
I have written integration tests for graphql-js subscriptions, which are showing weird behavior.
My graphq-js subscription works perfectly in GraphiQL. But when the same subscriptions is called from unit test, it fails.
Ggraphql-Js object, with resolve function and subscribe function
return {
type: outputType,
args: {
input: {type: new GraphQLNonNull(inputType)},
},
resolve(payload, args, context, info) {
const clientSubscriptionId = (payload) ? payload.subscriptionId : null;
const object = (payload) ? payload.object : null;
var where = null;
var type = null;
var target = null;
if (object) {
where = (payload) ? payload.object.where : null;
type = (payload) ? payload.object.type : null;
target = (payload) ? payload.object.target : null;
}
return Promise.resolve(subscribeAndGetPayload(payload, args, context, info))
.then(payload => ({
clientSubscriptionId, where, type, target, object: payload.data,
}));
},
subscribe: withFilter(
() => pubSub.asyncIterator(modelName),
(payload, variables, context, info) => {
const subscriptionPayload = {
clientSubscriptionId: variables.input.clientSubscriptionId,
remove: variables.input.remove,
create: variables.input.create,
update: variables.input.update,
opts: variables.input.options,
};
subscriptionPayload.model = model;
try {
pubSub.subscribe(info.fieldName, null, subscriptionPayload);
} catch (ex) {
console.log(ex);
}
return true;
}
),
};
Subscription query
subscription {
Customer(input: {create: true, clientSubscriptionId: 112}) {
customer {
id
name
age
}
}
}
Mutation query
mutation {
Customer {
CustomerCreate (input:{data:{name:"Atif 50", age:50}}) {
obj {
id
name
}
}
}
}
Integration Test
'use strict';
const ws = require('ws');
const { SubscriptionClient } = require('subscriptions-transport-ws');
const { ApolloClient } = require('apollo-client');
const { HttpLink } = require('apollo-link-http');
const { InMemoryCache } = require('apollo-cache-inmemory');
const Promise = require('bluebird');
const expect = require('chai').expect;
const chai = require('chai').use(require('chai-http'));
const server = require('../server/server');
const gql = require('graphql-tag');
let apollo;
let networkInterface;
const GRAPHQL_ENDPOINT = 'ws://localhost:5000/subscriptions';
describe('Subscription', () => {
before(async () => {
networkInterface = new SubscriptionClient(
GRAPHQL_ENDPOINT, { reconnect: true }, ws);
apollo = new ApolloClient({
networkInterface ,
link: new HttpLink({ uri: 'http://localhost:3000/graphql' }),
cache: new InMemoryCache()
});
});
after(done => {
networkInterface.close() ;
});
it('subscription', async () => {
const client = () => apollo;
// SUBSCRIBE and make a promise
const subscriptionPromise = new Promise((resolve, reject) => {
client().subscribe({
query: gql`
subscription {
Customer(input: {create: true,
clientSubscriptionId: 112,
options: {where: {age: 50}}}) {
customer {
name
}
}
}
`
}).subscribe({
next: resolve,
error: reject
});
});
let execGraphQL;
// MUTATE
await execGraphQL(
`mutation {
Customer {
CustomerCreate (input:{data:{name:"Atif 21", age:50}}) {
obj {
id
name
}
}
}
}`
);
// ASSERT SUBSCRIPTION RECEIVED EVENT
expect(await subscriptionPromise).to.deep.equal({});
});
});
Issue Here
When test in run, payload in the resolve function contains global data, where as it should contain the subscription payload. So the code breaks.