Can anybody help me understand why i'm getting this error:
My setup :
New sveltekit project.
ASP.net core backend for graphql.
Querying was working before I modified it to include subscriptions.
error msg:
Cannot read property 'executeQuery' of null
TypeError: Cannot read property 'executeQuery' of null
at C:\Repos\AGScada\node_modules\#urql\svelte\dist\urql-svelte.js:234:11
at C:\Repos\AGScada\node_modules\wonka\dist\wonka.js:254:18
at Object.next (C:\Repos\AGScada\node_modules\wonka\dist\wonka.js:1161:14)
at C:\Repos\AGScada\node_modules\#urql\svelte\dist\urql-svelte.js:173:11
at Object.subscribe (C:\Repos\AGScada\node_modules\svelte\store\index.js:53:9)
at Object.subscribe (C:\Repos\AGScada\node_modules\#urql\svelte\dist\urql-svelte.js:96:14)
at C:\Repos\AGScada\node_modules\#urql\svelte\dist\urql-svelte.js:168:14
at C:\Repos\AGScada\node_modules\wonka\dist\wonka.js:1159:9
at C:\Repos\AGScada\node_modules\wonka\dist\wonka.js:247:7
at C:\Repos\AGScada\node_modules\wonka\dist\wonka.js:590:18
Source Code index.svelte:
import { setClient, query, operationStore, subscription } from '#urql/svelte';
import { createClient, defaultExchanges, subscriptionExchange } from '#urql/svelte';
import { createClient as createWSClient } from 'graphql-ws';
const wsClient = process.browser ? createWSClient({url: 'ws://localhost:5000/graphql',}):null;
const client = process.browser ? createClient({
url: 'http://localhost:5000/graphql',
exchanges: [
...defaultExchanges,
subscriptionExchange({
forwardSubscription: (operation) => ({
subscribe: (sink) => ({
unsubscribe: wsClient.subscribe(operation, sink),
}),
}),
}),
],
}): null;
let tags = operationStore(`query {tags{tagName value}}`);
let onTagUpdated = operationStore(`subscription {onTagUpdated{tagName value}}`);
query(tags);
subscription(onTagUpdated);
setClient(client);
if($tags.fetching)
{
console.log("loading");
}
else
{
console.log($tags.data);
}
Thankyou for any help.
I got sveltekit and URQL working with the subscription support.
Source can be found here:
https://github.com/ruban258/sveltekit_urql_test
import { Client, setClient, operationStore, subscription, defaultExchanges, subscriptionExchange, query, createClient } from '#urql/svelte';
import {SubscriptionClient} from 'subscriptions-transport-ws';
import { browser } from '$app/env';
import { createClient as createWSClient } from 'graphql-ws';
const subscriptionClient = browser ? new SubscriptionClient('ws://localhost:5000/graphql', { reconnect: true }): null;
const wsClient = browser? createWSClient({
url: 'ws://localhost:5000/graphql',
}):null;
const client = browser ? new Client({
url: 'http://localhost:5000/graphql',
exchanges: [
...defaultExchanges,
subscriptionExchange({
forwardSubscription: (operation) => subscriptionClient.request(operation)
}),
],
}): null;
const messages = operationStore(`
subscription onTagUpdated{
onTagUpdated{
tagName
value
}
}
`);
const tags = operationStore(`
query{
tags{
tagName
value
}
}
`);
const handleSubscription = (messages = [], data) => {
return [data.newMessages, ...messages];
};
setClient(client);
Related
I recently started writing Discordbots and just can't seem to get anywhere pushing the slash commands. I already have a handler file (pushSlash.js) but for some reason the commands are never loaded or I get an error in the console (mostly simply this: chalk.blue is not a function). My bot also doesn't get the badge that it supports slash commands.
Can anyone help me further?
Here is my code (pushSlash.js):
module.exports = (client) => {
const fs = require('fs');
const { PermissionsBitField } = require('discord.js');
const { Routes } = require('discord-api-types/v9');
const { REST } = require('#discordjs/rest');
const AsciiTable = require('ascii-table');
const table = new AsciiTable().setHeading('Slash Commands', 'Stats').setBorder('|', '=', "0", "0");
const TOKEN = process.env.BOT_TOKEN;
const CLIENT_ID = process.env.CLIENT_ID;
const rest = new REST({ version: '9' }).setToken(TOKEN);
import( 'chalk').then(chalk => {
const slashCommands = [];
fs.readdirSync('/home/container/src/slashCommands/').forEach(async dir => {
const files = fs.readdirSync(`/home/container/src/slashCommands/${dir}/`).filter(file => file.endsWith('.js'));
for(const file of files) {
const slashCommand = require(`/home/container/src/slashCommands/${dir}/${file}`);
slashCommands.push({
name: slashCommand.name,
description: slashCommand.description,
options: slashCommand.options ? slashCommand.options : null,
default_permission: slashCommand.default_permission ? slashCommand.default_permission : null,
default_member_permissions: slashCommand.default_member_permissions ? PermissionsBitField.resolve(slashCommand.default_member_permissions).toString() : null
});
if(slashCommand.name) {
client.slashCommands.set(slashCommand.name, slashCommand);
table.addRow(file.split('.js')[0], '✅');
} else {
table.addRow(file.split('.js')[0], '⛔');
}
}
});
console.log(chalk.blue(table.toString()));
(async () => {
try {
await rest.put(
process.env.GUILD_ID ?
Routes.applicationGuildCommands(CLIENT_ID, process.env.GUILD_ID) :
Routes.applicationCommands(CLIENT_ID),
{ body: slashCommands }
);
console.log(chalk.green('Successfully registered application commands.'));
} catch (error) {
console.log(error);
}
})();
});
};
I've already tried everything possible, but since I'm relatively new to discord.js, I don't know that much yet either.
Actually everything should work and exactly 2 different commands should be loaded, but I only get error messages or the handler was loaded on console but nothing is displayed on Discord.
first download chalk#4.1.2 with
npm install chalk#4.1.2
and import chalk normally.
const chalk = require('chalk')
There your code modified version:
module.exports = (client) => {
const fs = require('fs');
const { PermissionsBitField } = require('discord.js');
const { Routes } = require('discord-api-types/v9');
const { REST } = require('#discordjs/rest');
const AsciiTable = require('ascii-table');
const table = new AsciiTable().setHeading('Slash Commands', 'Stats').setBorder('|', '=', "0", "0");
const TOKEN = process.env.BOT_TOKEN;
const CLIENT_ID = process.env.CLIENT_ID;
const rest = new REST({ version: '9' }).setToken(TOKEN);
// Imported chalk normally
const chalk = require('chalk')
// removed `import( 'chalk').then(chalk => {})`
const slashCommands = [];
fs.readdirSync('/home/container/src/slashCommands/').forEach(async dir => {
const files = fs.readdirSync(`/home/container/src/slashCommands/${dir}/`).filter(file => file.endsWith('.js'));
for(const file of files) {
const slashCommand = require(`/home/container/src/slashCommands/${dir}/${file}`);
slashCommands.push({
name: slashCommand.name,
description: slashCommand.description,
options: slashCommand.options ? slashCommand.options : null,
default_permission: slashCommand.default_permission ? slashCommand.default_permission : null,
default_member_permissions: slashCommand.default_member_permissions ? PermissionsBitField.resolve(slashCommand.default_member_permissions).toString() : null
});
if(slashCommand.name) {
client.slashCommands.set(slashCommand.name, slashCommand);
table.addRow(file.split('.js')[0], '✅');
} else {
table.addRow(file.split('.js')[0], '⛔');
}
}
});
console.log(chalk.blue(table.toString()));
(async () => {
try {
await rest.put(
process.env.GUILD_ID ?
Routes.applicationGuildCommands(CLIENT_ID, process.env.GUILD_ID) :
Routes.applicationCommands(CLIENT_ID),
{ body: slashCommands }
);
console.log(chalk.green('Successfully registered application commands.'));
} catch (error) {
console.log(error);
}
})();
};
I'm currently migrating my Gatsby V3 to Gatsby V4.
I have a createNode using a function that retrieve some data from GraphQL using getNodesByType("myType").
function getSecteur(realisation) {
const secteurs = getNodesByType(`StrapiSecteurs`);
console.log(secteurs)
if (realisation.client && realisation.client.secteur) {
return secteurs.find(
(secteur) => secteur.strapiId === realisation.client.secteur
);
}
exports.onCreateNode = async ({
node,
actions,
getNodesByType,
}) => {
const { createNode } = actions;
if (node.internal.type === "StrapiRealisations") {
createNode({
...node,
id: `${node.id}-markdown`,
parent: node.id,
children: [],
client: {
...node.client,
secteur: getSecteur(node),
},
citation: getCitation(node),
internal: {
type: "MDRealisation",
contentDigest: digest(node),
},
});
}
But in V4 this function does not retrieve any data, but I cannot found an alternative for getNodesByType.
Any idea(s) ?
Thanks
Have you tried something like:
exports.sourceNodes = ({ actions, getNodesByType }) => {
getNodesByType("StrapiSecteurs").forEach(node => actions.touchNode(node))
}
does anyone know what this means, and how i can debug it - i've tried react dev tools - and the states and everything disappear as soon as this message pops up:
Server Error
TypeError: Cannot destructure property 'id' of 'undefined' as it is undefined.
This error happened while generating the page. Any console logs will be displayed in the terminal window.
Call Stack
<unknown>
file:///home/abda_react/abdn2/node_modules/next-auth/server/lib/providers.js (29:5)
Array.find
<anonymous>
parseProviders
file:///home/abda_react/abdn2/node_modules/next-auth/server/lib/providers.js (28:30)
NextAuthHandler
file:///home/abda_react/abdn2/node_modules/next-auth/server/index.js (88:30)
<unknown>
file:///home/abda_react/abdn2/node_modules/next-auth/server/index.js (251:38)
Object.apiResolver
file:///home/abda_react/abdn2/node_modules/next/dist/server/api-utils.js (101:15)
runMicrotasks
<anonymous>
processTicksAndRejections
node:internal/process/task_queues (96:5)
async DevServer.handleApiRequest
file:///home/abda_react/abdn2/node_modules/next/dist/server/next-server.js (770:9)
async Object.fn
file:///home/abda_react/abdn2/node_modules/next/dist/server/next-server.js (661:37)
my nextauth config file:
import NextAuth from "next-auth"
import EmailProvider from 'next-auth/providers/email';
import GoogleProvider from "next-auth/providers/google";
export default NextAuth({
// Configure one or more authentication providers
providers: [
,EmailProvider({
server: process.env.EMAIL_SERVER,
from: process.env.EMAIL_FROM,
})
,GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
// ...add more providers here
],
jwt: {
encryption: true,
},
secret: process.env.secret,
//https://www.youtube.com/watch?v=QK24lEvRTI8
callback: {
// async jwt(token, account) {
// if (account?.accessToken) {
// token.accessToken = account.accessToken;
// }
// return token;
// },
// redirect: async (url, _baseUrl) => {
// if (url === '/') {
// return Promise.resolve('/index');
// }
// return Promise.resolve('/index');
// }
},
pages: {
// signIn: '/auth/signin',
// signOut: '/auth/signout',
// error: '/auth/error', // Error code passed in query string as ?error=
// verifyRequest: '/auth/verify-request', // (used for check email message)
// newUser: '/auth/new-user' // New users will be directed here on first sign in (leave the property out if not of interest)
}
})
// https://console.cloud.google.com/projectselector2/apis/credentials?authuser=1&pli=1&supportedpurview=project
//All requests to /api/auth/* (signIn, callback, signOut, etc.) will automatically be handled by NextAuth.js.
could it be something that's wrongly configured?? but i dont understand why it would work before i installed auto prefixer...
here is the providers file(i did not write a single code of it):
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = parseProviders;
var _merge = require("../../lib/merge");
function parseProviders(params) {
const {
base,
providerId
} = params;
const providers = params.providers.map(({
options,
...rest
}) => {
var _userOptions$id, _userOptions$id2;
const defaultOptions = normalizeProvider(rest);
const userOptions = normalizeProvider(options);
return (0, _merge.merge)(defaultOptions, { ...userOptions,
signinUrl: `${base}/signin/${(_userOptions$id = userOptions === null || userOptions === void 0 ? void 0 : userOptions.id) !== null && _userOptions$id !== void 0 ? _userOptions$id : rest.id}`,
callbackUrl: `${base}/callback/${(_userOptions$id2 = userOptions === null || userOptions === void 0 ? void 0 : userOptions.id) !== null && _userOptions$id2 !== void 0 ? _userOptions$id2 : rest.id}`
});
});
const provider = providers.find(({
id
}) => id === providerId);
return {
providers,
provider
};
}
function normalizeProvider(provider) {
var _provider$version;
if (!provider) return;
const normalizedProvider = Object.entries(provider).reduce((acc, [key, value]) => {
if (["authorization", "token", "userinfo"].includes(key) && typeof value === "string") {
var _url$searchParams;
const url = new URL(value);
acc[key] = {
url: `${url.origin}${url.pathname}`,
params: Object.fromEntries((_url$searchParams = url.searchParams) !== null && _url$searchParams !== void 0 ? _url$searchParams : [])
};
} else {
acc[key] = value;
}
return acc;
}, {});
if (provider.type === "oauth" && !((_provider$version = provider.version) !== null && _provider$version !== void 0 && _provider$version.startsWith("1.")) && !provider.checks) {
normalizedProvider.checks = ["state"];
}
return normalizedProvider;
}
so..from what i am guessing, there is no property id in there...but i have no idea why that would change after installing autoprefixer, and also i have no idea how to even consider adding id into this.
update
changed the providers variable to see maybe it's just google...and it seems i have another issue which i think might be related. here is the error:
./pages/api/auth/[...nextauth].js:3:0
Module not found: Package path ./providers is not exported from package /home/abda_react/abdn2/node_modules/next-auth (see exports field in /home/abda_react/abdn2/node_modules/next-auth/package.json)
1 | import NextAuth from "next-auth"
2 | import EmailProvider from 'next-auth/providers/email';
> 3 | import Providers from "next-auth/providers";
4 |
5 | export default NextAuth({
6 | // Configure one or more authentication providers
Import trace for requested module:
https://nextjs.org/docs/messages/module-not-found
here is what i changed:
import NextAuth from "next-auth"
import EmailProvider from 'next-auth/providers/email';
import Providers from "next-auth/providers";
export default NextAuth({
// Configure one or more authentication providers
providers: [
// ,EmailProvider({
// server: process.env.EMAIL_SERVER,
// from: process.env.EMAIL_FROM,
// })
,Providers.Google({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
// ...add more providers here
package.json:
"exports": {
".": "./index.js",
"./jwt": "./jwt/index.js",
"./react": "./react/index.js",
"./providers/*": "./providers/*.js"
},
ok two things:
my email provider credentials were placeholders - that's not good.
your signin page needs to be set
for completion, here's what i did:
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google";
export default NextAuth({
// Configure one or more authentication providers
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
]
,callback: {
async jwt(token, account) {
if (account?.accessToken) {
token.accessToken = account.accessToken;
}
return token;
},
redirect: async (url, _baseUrl) => {
if (url === '/') {
return Promise.resolve('/index');
}
return Promise.resolve('/index');
}
,pages: {
signIn: '/index',
signOut: '/index',
}
,debug: false
}
})
even though i still cant import all providers - it works, so good enough for now
but again...not sure why it worked before autoprefix...
I have hosted a peer to peer meeting react app on netlify. I have used Peerjs for my video purpose. Everything is working as expected except the video. For some networks the video of the the remote person is working and for some others it is not working. I looked up and found out that it may be a STUN/TURN issue. I then implemented all the STUN/TURN servers in my code. However the video is still not getting setup in some cases. In some cases it is working fine, in others the video is not showing up. Herewith, I am attaching th code for the video and the link to the site.
import React,{useEffect,useState} from 'react';
import {io} from "socket.io-client";
import {useParams} from 'react-router-dom';
import {Grid} from "#material-ui/core";
import Peer from 'peerjs';
var connectionOptions = {
"force new connection" : true,
"reconnectionAttempts": "Infinity",
"timeout" : 10000,
"transports" : ["websocket"]
};
const Videobox = ({isVideoMute,isAudioMute}) => {
var myPeer = new Peer(
{
config: {'iceServers': [
{urls:'stun:stun01.sipphone.com'},
{urls:'stun:stun.ekiga.net'},
{urls:'stun:stun.fwdnet.net'},
{urls:'stun:stun.ideasip.com'},
{urls:'stun:stun.iptel.org'},
{urls:'stun:stun.rixtelecom.se'},
{urls:'stun:stun.schlund.de'},
{urls:'stun:stun.l.google.com:19302'},
{urls:'stun:stun1.l.google.com:19302'},
{urls:'stun:stun2.l.google.com:19302'},
{urls:'stun:stun3.l.google.com:19302'},
{urls:'stun:stun4.l.google.com:19302'},
{urls:'stun:stunserver.org'},
{urls:'stun:stun.softjoys.com'},
{urls:'stun:stun.voiparound.com'},
{urls:'stun:stun.voipbuster.com'},
{urls:'stun:stun.voipstunt.com'},
{urls:'stun:stun.voxgratia.org'},
{urls:'stun:stun.xten.com'},
{
urls: 'turn:numb.viagenie.ca',
credential: 'muazkh',
username: 'webrtc#live.com'
},
{
urls: 'turn:192.158.29.39:3478?transport=udp',
credential: 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
username: '28224511:1379330808'
},
{
urls: 'turn:192.158.29.39:3478?transport=tcp',
credential: 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
username: '28224511:1379330808'
}
]} /* Sample servers, please use appropriate ones */
}
);
const peers = {}
const [socket, setSocket] = useState()
const {id:videoId} = useParams();
const videoGrid = document.getElementById('video-grid')
useEffect(()=> {
const s=io("https://weconnectbackend.herokuapp.com",connectionOptions);
setSocket(s);
return () => {
s.disconnect();
}
},[])
// let myVideoStream;
const [myVideoStream, setmyVideoStream] = useState()
const muteUnmute = () => {
const enabled = myVideoStream.getAudioTracks()[0].enabled;
if (enabled) {
myVideoStream.getAudioTracks()[0].enabled = false;
//setUnmuteButton();
} else {
//setMuteButton();
myVideoStream.getAudioTracks()[0].enabled = true;
}
}
const playStop = () => {
//console.log('object')
let enabled = myVideoStream.getVideoTracks()[0].enabled;
if (enabled) {
myVideoStream.getVideoTracks()[0].enabled = false;
//setPlayVideo()
} else {
//setStopVideo()
myVideoStream.getVideoTracks()[0].enabled = true;
}
}
useEffect(() => {
if(myVideoStream)
playStop()
}, [isVideoMute])
useEffect(() => {
if(myVideoStream)
muteUnmute()
}, [isAudioMute])
useEffect(() => {
if(socket== null)
return;
myPeer.on('open',id=>{
socket.emit('join-room',videoId,id);
})
const myVideo = document.createElement('video')
myVideo.muted = true
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(stream => {
// myVideoStream = stream;
window.localStream=stream;
setmyVideoStream(stream);
console.log(myVideoStream,"myvideostream");
addVideoStream(myVideo, stream)
myPeer.on('call', call => {
call.answer(stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream)
})
})
socket.on('user-connected',userId =>{
connectToNewUser(userId, stream)
})
socket.on('user-disconnected', userId => {
if (peers[userId]) peers[userId].close()
})
})
}, [socket,videoId])
function addVideoStream(video, stream) {
video.srcObject = stream
video.addEventListener('loadedmetadata', () => {
video.play()
})
videoGrid.append(video)
}
function connectToNewUser(userId, stream) {
const call = myPeer.call(userId, stream)
const video = document.createElement('video')
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream)
})
call.on('close', () => {
video.remove()
})
peers[userId] = call
}
return (
<div id="video-grid" className="videoStyleFromDiv">
{/* <Video srcObject={srcObject}/> */}
</div>
)
}
export default Videobox
Website Link
The TURN servers you are using have been out of commission for a couple of years in the case of the ones taken from https://www.html5rocks.com/en/tutorials/webrtc/infrastructure/
Copying credentials from random places is not how TURN works, you will need to run your own servers.
ERROR #11321 PLUGIN
"gatsby-node.js" threw an error while running the onCreateNode lifecycle:
Cannot read property 'replace' of undefined
25 | const { createNodeField } = actions;
26 | if (node.internal.type === 'MarkdownRemark') {
> 27 | const slug = createFilePath({ node, getNode, basePath: 'content' });
| ^
28 | createNodeField({
29 | node,
30 | name: 'slug',
File: gatsby-node.js:27:18
TypeError: Cannot read property 'replace' of undefined
- path.js:54 slash
[netcreative0]/[gatsby-core-utils]/dist/path.js:54:15
- create-file-path.js:41 module.exports
[netcreative0]/[gatsby-source-filesystem]/create-file-path.js:41:61
- gatsby-node.js:27 Object.exports.onCreateNode
C:/code/netcreative0/gatsby-node.js:27:18
- api-runner-node.js:247 runAPI
[netcreative0]/[gatsby]/dist/utils/api-runner-node.js:247:41
- api-runner-node.js:387 resolve
[netcreative0]/[gatsby]/dist/utils/api-runner-node.js:387:13
- new Promise
- api-runner-node.js:386 runPlugin
[netcreative0]/[gatsby]/dist/utils/api-runner-node.js:386:10
- api-runner-node.js:340 module.exports
[netcreative0]/[gatsby]/dist/utils/api-runner-node.js:340:24
- next_tick.js:68 process._tickCallback
internal/process/next_tick.js:68:7
Here's all the code in that file. I found this link https://github.com/datocms/gatsby-source-datocms/issues/52 but it didn't seem to help to remove getNode. in the path plugin, is this slash. I noticed that the path is undefined when I console.log it but I don't know what to do about it.
**function slash(path) {
const isExtendedLengthPath = /^\\\\\?\\/.test(path);
if (isExtendedLengthPath) {
return path;
}
return path.replace(/\\/g, `/`);
}**
const path = require('path');
const DirectoryNamedWebpackPlugin = require('directory-named-webpack-plugin');
const { createFilePath } = require('gatsby-source-filesystem');
exports.onCreateWebpackConfig = ({
stage,
getConfig,
rules,
loaders,
actions,
}) => {
actions.setWebpackConfig({
resolve: {
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
plugins: [
new DirectoryNamedWebpackPlugin({
exclude: /node_modules/,
}),
],
},
});
};
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions
if (node.internal.type === 'MarkdownRemark') {
const slug = createFilePath({ node, getNode, basePath: 'slugs' });
console.log(slug);
createNodeField({
node,
name: `slug`,
value: slug,
});
}
};
the second half of my code that looks like:
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions;
const result = await graphql(`
query {
allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}
`)
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
console.log(node)
createPage({
path: node.fields ? node.fields.slug : '',
component: path.resolve(`./src/template/project.js`),
context: {
// Data passed to context is available
// in page queries as GraphQL variables.
slug: node.fields ? node.fields.slug : '',
},
})
});
}
The last field is null and throws an error. Not sure why it's even there? I could easily put in a condition but what would the default be? Any suggestions? See below
{ fields: { slug: '/about/content/' } }
{ fields: { slug: '/home/intro/' } }
{ fields: { slug: '/slugs/goldparent/' } }
{ fields: { slug: '/slugs/ipadmaster/' } }
{ fields: null }
After removing the contentful plugin, I was able to see a more useful error message.
Some images were missing from the .md files when creating new pages so an error appeared on this line in my template page
data.frontmatter.featuredImage.childImageSharp.fluid <-
I added a ternary condition to the image tag and it built after that
<Img
style={{ width: '70%' }}
fluid={
data.frontmatter.featuredImage
? data.frontmatter.featuredImage.childImageSharp.fluid
: {}
}
alt="Large Image"
/>