'next-session' is not working with 'connect-pg-simple' - next.js

Documentation or an example on 'next-session' on how to connect it to Postgres was very dry.
Following the compatibility example on npm did not work.
const session = require("express-session");
const RedisStore = require("connect-redis")(session);
// Use `expressSession` from `next-session/lib/compat` as the replacement
import { expressSession } from "next-session/lib/compat";
const pgSession = require("connect-pg-simple")(expressSession)
export const getSession = nextSession({
cookie: {
maxAge: 432000,
},
store: new pgStore({...config}},
});
Error: ...failed to prune "session"

Not as simple as 'express-session' to get it working but it was a lot simpler than learning how to use jwt 'iron-session' library...
I managed to get it working by doing this:
import nextSession from "next-session";
import pgPool from "./db";
import { promisifyStore } from "next-session/lib/compat";
import { expressSession } from "next-session/lib/compat";
const pgSession = require("connect-pg-simple")(expressSession);
const connectStore = new pgSession({
pool: pgPool,
tableName: "session",
});
export const getSession = nextSession({
cookie: {
maxAge: 432000,
},
store: promisifyStore(connectStore),
});

Related

Coinbase wallet not open always ask to install even its installed on deploy to server but opens in local, using wagmi and next js

I have used wagmi for wallet connect and using next js , the wallet trigger and open extension of coinbase in local but when we deploy it on sever it always tell to install even though it is already installed. I am sharing my connection tried using both alchemy and infura provider but not working . Any idea anybody.shared pic the wallet is installed but still it ask to install
import {
configureChains,
createClient,
goerli,
mainnet,
WagmiConfig,
} from "wagmi";
import { alchemyProvider } from "wagmi/providers/alchemy";
import { infuraProvider } from "wagmi/providers/infura";
import { publicProvider } from "wagmi/providers/public";
import { ReactNode } from "react";
import { CoinbaseWalletConnector } from "wagmi/connectors/coinbaseWallet";
import { MetaMaskConnector } from "wagmi/connectors/metaMask";
import { WalletConnectConnector } from "wagmi/connectors/walletConnect";
interface WalletProviderInterface {
children: ReactNode;
}
const WalletProvider = ({ children }: WalletProviderInterface) => {
const { chains, provider, webSocketProvider } = configureChains(
[mainnet],
[
alchemyProvider({
apiKey: process.env.NEXT_PUBLIC_ALCHEMY_KEY || "",
}),
infuraProvider({ apiKey: process.env.NEXT_PUBLIC_INFURA_KEY || "" }),
]
);
const connectors = [
new MetaMaskConnector({
chains,
options: {
shimDisconnect: true,
shimChainChangedDisconnect: false,
},
}),
new CoinbaseWalletConnector({
chains,
options: {
appName: `test app`,
jsonRpcUrl: `https://ethmainnet.g.alchemy.com/v2/${process.env.NEXT_PUBLIC_ALCHEMY_KEY}`,
},
}),
new WalletConnectConnector({
chains,
options: {
// alchemyId:process.env.NEXT_PUBLIC_ALCHEMY_KEY,
qrcode: true,
},
}),
];
const client = createClient({
autoConnect: true,
connectors,
provider,
webSocketProvider,
});
return <WagmiConfig client={client}>{children}</WagmiConfig>;
};
export default WalletProvider;

nextjs: TypeError: createServer is not a function

I am trying to follow this tutorial:
I am stuck at step 3, which is where the server is defined as follows:
import { createServer } from "#graphql-yoga/node";
import { join } from "path";
import { readFileSync } from "fs";
const typeDefs = readFileSync(join(process.cwd(), "schema.graphql"), {
encoding: "utf-8",
});
const resolvers = {
Query: {
cart: (_, { id }) => {
return {
id,
totalItems: 0,
};
},
},
};
const server = createServer({
cors: false,
endpoint: "/api",
logging: {
prettyLog: false,
},
schema: {
typeDefs,
resolvers,
},
});
export default server;
When I try to use that definition and start the local host, I get an error that says:
TypeError: (0 ,
graphql_yoga_node__WEBPACK_IMPORTED_MODULE_0_.createServer) is not a function at eval
Can anyone see if this tutorial is now out of date. I can see that I am using next v 13.1.1 and the tutorial uses v12. I've been having an awful time trying to find an explanation of how to use these packages, in their current formats. Is this one now out of date?
Can anyone see how to define a server for next v13?
There are some change between graph-yoga v2 and v3, you can look this tutorial to solve it.
For others that might be stuck, this might be a way to define the schema using graphql-yoga (now instead of graphql-yoga/node)
import { createSchema, createYoga } from 'graphql-yoga'
import { createServer } from 'node:http'
import { join } from "path";
import { readFileSync } from "fs";
const typeDefs = readFileSync(join(process.cwd(), "schema.graphql"), {
encoding: "utf-8",
});
const resolvers = {
Query: {
cart: (_, { id }) => {
return {
id,
totalItems: 0,
};
},
},
};
const yoga = createYoga({
cors: false,
endpoint: "/api",
logging: {
prettyLog: false,
},
schema: createSchema({
typeDefs,
resolvers,
}),
});
const server = createServer(yoga);
server.listen(3000, () => {
console.info('Server is running on http://localhost:3000/graphql')
});
export default server;

getStatic Path not working for base URL "/" in NextJS

I'm using Prismic and NextJS for the first time.
What I'm trying to is make it so when the user goes to the base url for the page localhost:3000/ in dev something will load. /About and /Pricing are working fine the base url doesn't work.
import { GetStaticPaths, GetStaticProps } from 'next'
import { SliceZone } from '#prismicio/react'
import * as prismicH from "#prismicio/helpers";
import { createClient, linkResolver } from '../../prismicio'
import { components } from '../../slices'
interface HomePageProps {
page: any
}
const HomePage = (props:HomePageProps) => {
return <SliceZone slices={props.page.data.slices} components={components} />
}
export default HomePage
interface HomePageStaticProps {
params: any
previewData:any
}
export async function getStaticProps(props:HomePageStaticProps) {
console.log("DOES NOT FIRE FOR localhost:3000")
const client = createClient({ previewData:props.previewData })
const params = props.params;
const uid = params?.pagePath?.[params.pagePath.length - 1] || "home";
const page = await client.getByUID("page", uid);
return {
props: {
page,
},
}
}
export const getStaticPaths: GetStaticPaths = async () => {
const client = createClient();
const pages = await client.getAllByType("page");
const paths = pages.map((page) => prismicH.asLink(page, linkResolver)) as string[];
console.log(paths) // [ '/pricing', '/about', '/' ]
return {
paths,
fallback: false,
};
}
or to simplify it further
[[...pagePath]].tsx fails when going to localhost:3000/ but does not fail on localhost:3000/about or localhost:3000/pricing.
import { GetStaticPaths, GetStaticProps } from 'next'
interface HomePageProps {
page: string
}
const HomePage = (props:HomePageProps) => {
return <>{props.page}</>
}
export default HomePage
interface HomePageStaticProps {
params: any
previewData:any
}
export async function getStaticProps(props:HomePageStaticProps) {
const params = props.params;
const uid = params?.pagePath?.[params.pagePath.length - 1] || "home";
//const page = await client.getByUID("page", uid);
return {
props: {
page:uid,
},
}
}
export const getStaticPaths: GetStaticPaths = async () => {
const paths = [ '/pricing', '/about', '/' ];
return {
paths,
fallback: false,
};
}
As far as I can see your'e not fetching the right way. In order to to have a clean project I would recommend to use a const var where you can determine between dev and production enviorenment. To do so you can simply create a file for example: constants.js containing the following:
export const baseurl = process.env.NODE_ENV === "production"
? process.env.NEXT_PUBLIC_DOMAIN // <-- your domain on live
: "http://localhost:3000"; // localhost on dev
Now with this you automatically have localhost on your dev. Notice that you need http:// which your'e missing at the moment. Now the next example shows you how to fetch something on your root / by entering the following code:
import { baseurl } from "../utils/constants"; // <-- importing the constant
// This function gets called at build time on server-side.
// It won't be called on client-side, so you can even do
// direct database queries.
export async function getStaticProps() {
// Call an external API endpoint to get posts.
// You can use any data fetching library
const res = await fetch(`${baseurl}/api/posts`)
const posts = await res.json()
// By returning { props: { posts } }, the Blog component
// will receive `posts` as a prop at build time
return {
props: {
posts,
},
}
}
If you are using Create-T3-App
https://github.com/t3-oss/create-t3-app
then
your next.config.mjs will default to this as of Nov 7, 2022
const config = {
reactStrictMode: true,
swcMinify: true,
i18n: {
locales: ["en"],
defaultLocale: "en",
},
};
export default config;
remove
const config = {
reactStrictMode: true,
swcMinify: true,
//i18n: {
// locales: ["en"],
// defaultLocale: "en",
//},
};
export default config;
This will make default "/" pathing work, if you require i18n, I'm sorry I can't help.

trpc v10 - Error: Query data cannot be undefined

New to trpc. Trying to get basic query functionality but it's not working. Not sure what I'm missing. In v9 it used createReactQueryHooks(), but it seems in v10 you only need to use createTRPCNext() if I'm not mistaken inside util/trpc.tsx.
Error:
next-dev.js:32 Error: Query data cannot be undefined - affected query key: ["greeting"]
at Object.onSuccess (query.mjs:320:19)
at resolve (retryer.mjs:64:50)
// utils/trpc.ts
export const trpc = createTRPCNext<AppRouter, SSRContext>({
config({ ctx }) {
return {
transformer: superjson, // optional - adds superjson serialization
links: [
httpBatchLink({
/**
* If you want to use SSR, you need to use the server's full URL
* #link https://trpc.io/docs/ssr
**/
url: `${getBaseUrl()}/api/trpc`,
}),
],
/**
* #link https://react-query-v3.tanstack.com/reference/QueryClient
**/
// queryClientConfig: { defaultOptions: { queries: { staleTime: 60 } } },
headers() {
if (ctx?.req) {
// To use SSR properly, you need to forward the client's headers to the server
// This is so you can pass through things like cookies when we're server-side rendering
// If you're using Node 18, omit the "connection" header
const {
// eslint-disable-next-line #typescript-eslint/no-unused-vars
connection: _connection,
...headers
} = ctx.req.headers;
return {
...headers,
// Optional: inform server that it's an SSR request
"x-ssr": "1",
};
}
return {};
},
};
},
ssr: true,
});
// server/router/_app.ts
import { t } from '#/server/trpc';
import { userRouter } from '#/server/router/user';
import { postRouter } from '#/server/router/posts';
import { authRouter } from './authy';
export const appRouter = t.router({
user: userRouter,
post: postRouter,
authy: authRouter,
greeting: t.procedure.query(() => 'hello tRPC v10!'),
});
export type AppRouter = typeof appRouter;
// server/router/authy.ts
import { t } from "#/server/trpc";
import * as trpc from "#trpc/server";
import { z } from "zod";
export const authRouter = t.router({
hello: t.procedure
// using zod schema to validate and infer input values
.input(
z.object({
text: z.string().nullish(),
})
.nullish().optional()
)
.query(({ input }) => {
return {
greeting: `hello ${input?.text ?? "world"}`,
};
}),
});
export type AuthRouter = typeof authRouter;
None of the routes work. They all show a similar error.
// pages/test.tsx
import React from "react";
import { NextPage } from "next";
import { trpc } from "#/utils/trpc";
const TestPage: NextPage = () => {
const helloNoArgs = trpc.authy.hello.useQuery();
const helloWithArgs = trpc.authy.hello.useQuery({ text: "client" });
const greeting = trpc.greeting.useQuery();
return (
<div>
<h1>Hello World Example</h1>
<ul>
<li>
helloNoArgs ({helloNoArgs.status}):{" "}
<pre>{JSON.stringify(helloNoArgs.data, null, 2)}</pre>
</li>
<li>
helloWithArgs ({helloWithArgs.status}):{" "}
<pre>{JSON.stringify(helloWithArgs.data, null, 2)}</pre>
</li>
<li>
greeting ({greeting.status}):{" "}
<pre>{JSON.stringify(greeting.data, null, 2)}</pre>
</li>
</ul>
</div>
);
};
export default TestPage;
It seems you are using superjson. You need to add superjson transformer at initTRPC.
routers/router/_app.ts
import { initTRPC } from '#trpc/server';
import superjson from 'superjson';
export const t = initTRPC.create({
transformer: superjson,
});
more detailed instruction can be found here: TRPC v10
Omgosh... it was because I was using "^10.0.0-proxy-beta.7" and not "^10.0.0-proxy-beta.8"
Edit: Somehow I had another error and encountered my own question again 22 days later and solved it again. In general, when using trpc it seems updating to all the #next packages is best as it seems to be somewhat easy to have packages not talking to each other as they improve.
https://trpc.io/docs/v10/quickstart#installation-snippets
On my side I was using a mocked trpc server that was not using superjson (whereas the real one was). I just used superjson.serialize(...) before adding the JSON body to my response (in my server mock), then it worked :)

How to get storybook addon options

When we load a storybook addon we can pass some options:
// .storybook/main.js
module.exports = {
addons: [
'a-storybook-addon-without-options',
{
name: 'a-storybook-addon-with-options',
options: {
mainColor: 'hotpink',
},
},
],
};
To write my addon I use the addon API:
// /a-storybook-addon-with-options/src/register.js
import React from 'react';
import { addons, types } from '#storybook/addons';
import MyComponent from './myComponent.js';
const ADDON_ID = 'myaddon';
const PANEL_ID = `${ADDON_ID}/panel`;
addons.register(ADDON_ID, (api) => {
addons.add(PANEL_ID, {
type: types.PANEL,
title: 'My Addon',
render: MyComponent,
});
});
I don't know how to get the developer options from the addon code. Is there an official way? I didn't get a clear help from the documentation.
I think here you should use a parameter instead of this option in the config.
This kind of config (the options field) is more for presets that alter webpack or babel config.
If you add a parameter in the preview with the key that you specify in the register file then you can easily access that parameter in the addon code.
in preview.js
export const parameters = {
myAddon: {
mainColor: 'red'
},
};
in the addon code
import { useParameter } from '#storybook/api';
const PARAM_KEY = 'myAddon';
const MyPanel = () => {
const value = useParameter(PARAM_KEY, null);
const mainColor = value ? value.mainColor : 'No mainColor defined';
return <div>{mainColor}</div>;
};
You could set some default by setting a value when they don't set any value on the parameter like:
const mainColor = value ? value.mainColor : 'red';

Resources