TradingView Chart Library not working on production - reactjs

I've implemented the TradingView charting library on my react project following the documentation provided.
Copy charting_library folder from
https://github.com/tradingview/charting_library/ to /public and to
/src folders. Copy datafeeds folder from
https://github.com/tradingview/charting_library/ to /public.
exactly as mentioned in the documentation , when i run yarn start it's working and showing however , when I build and try to serve it using nginx .
I get an error saying .
TypeError: Cannot read properties of undefined (reading
'UDFCompatibleDatafeed').
import * as React from "react";
import "./index.css";
import {
widget,
ChartingLibraryWidgetOptions,
IChartingLibraryWidget
} from "../../../charting_library";
import { useMarket, USE_MARKETS } from "../../utils/markets";
import * as saveLoadAdapter from "./saveLoadAdapter";
import { flatten } from "../../utils/utils";
import { BONFIDA_DATA_FEED } from "../../utils/bonfidaConnector";
import {} from "../../../charting_library";
export interface ChartContainerProps {
symbol: ChartingLibraryWidgetOptions["symbol"];
interval: ChartingLibraryWidgetOptions["interval"];
auto_save_delay: ChartingLibraryWidgetOptions["auto_save_delay"];
// BEWARE: no trailing slash is expected in feed URL
// datafeed: any;
datafeedUrl: string;
libraryPath: ChartingLibraryWidgetOptions["library_path"];
chartsStorageUrl: ChartingLibraryWidgetOptions["charts_storage_url"];
chartsStorageApiVersion: ChartingLibraryWidgetOptions["charts_storage_api_version"];
clientId: ChartingLibraryWidgetOptions["client_id"];
userId: ChartingLibraryWidgetOptions["user_id"];
fullscreen: ChartingLibraryWidgetOptions["fullscreen"];
autosize: ChartingLibraryWidgetOptions["autosize"];
studiesOverrides: ChartingLibraryWidgetOptions["studies_overrides"];
containerId: ChartingLibraryWidgetOptions["container_id"];
theme: string;
}
export interface ChartContainerState {}
export const TVChartContainer = () => {
// let datafeed = useTvDataFeed();
const defaultProps: ChartContainerProps = {
symbol: "BTC/USDC",
// #ts-ignore
interval: "60",
auto_save_delay: 5,
theme: "Dark",
containerId: "tv_chart_container",
// datafeed: datafeed,
libraryPath: "/charting_library/",
chartsStorageApiVersion: "1.1",
clientId: "tradingview.com",
userId: "public_user_id",
fullscreen: false,
autosize: true,
datafeedUrl: BONFIDA_DATA_FEED,
studiesOverrides: {}
};
const tvWidgetRef = React.useRef<IChartingLibraryWidget | null>(null);
const { market } = useMarket();
const chartProperties = JSON.parse(
localStorage.getItem("chartproperties") || "{}"
);
React.useEffect(() => {
const savedProperties = flatten(chartProperties, {
restrictTo: ["scalesProperties", "paneProperties", "tradingProperties"]
});
let newWindow :any = window ;
console.log("defaultProps.datafeedUrl", newWindow.Datafeeds);
const widgetOptions: ChartingLibraryWidgetOptions = {
symbol:
USE_MARKETS.find(
(m) => m.address.toBase58() === market?.publicKey.toBase58()
)?.name || "SRM/USDC",
// BEWARE: no trailing slash is expected in feed URL
// tslint:disable-next-line:no-any
// #ts-ignore
// datafeed: datafeed,
// #ts-ignore
datafeed:new (window as any).Datafeeds.UDFCompatibleDatafeed(
defaultProps.datafeedUrl,
),
interval:
defaultProps.interval as ChartingLibraryWidgetOptions["interval"],
container_id:
defaultProps.containerId as ChartingLibraryWidgetOptions["container_id"],
library_path: defaultProps.libraryPath as string,
auto_save_delay: 5,
locale: "en",
disabled_features: ["use_localstorage_for_settings"],
enabled_features: ["study_templates"],
load_last_chart: true,
client_id: defaultProps.clientId,
user_id: defaultProps.userId,
fullscreen: defaultProps.fullscreen,
autosize: defaultProps.autosize,
studies_overrides: defaultProps.studiesOverrides,
theme: defaultProps.theme === "Dark" ? "Dark" : "Light",
overrides: {
...savedProperties,
"mainSeriesProperties.candleStyle.upColor": "#41C77A",
"mainSeriesProperties.candleStyle.downColor": "#F23B69",
"mainSeriesProperties.candleStyle.borderUpColor": "#41C77A",
"mainSeriesProperties.candleStyle.borderDownColor": "#F23B69",
"mainSeriesProperties.candleStyle.wickUpColor": "#41C77A",
"mainSeriesProperties.candleStyle.wickDownColor": "#F23B69",
"background": "#141424 ",
"backgroundColor" : "#141424 "
},
// #ts-ignore
save_load_adapter: saveLoadAdapter,
settings_adapter: {
initialSettings: {
"trading.orderPanelSettingsBroker": JSON.stringify({
showRelativePriceControl: false,
showCurrencyRiskInQty: false,
showPercentRiskInQty: false,
showBracketsInCurrency: false,
showBracketsInPercent: false
}),
// "proterty"
"trading.chart.proterty":
localStorage.getItem("trading.chart.proterty") ||
JSON.stringify({
hideFloatingPanel: 1
}),
"chart.favoriteDrawings":
localStorage.getItem("chart.favoriteDrawings") ||
JSON.stringify([]),
"chart.favoriteDrawingsPosition":
localStorage.getItem("chart.favoriteDrawingsPosition") ||
JSON.stringify({})
},
setValue: (key, value) => {
localStorage.setItem(key, value);
},
removeValue: (key) => {
localStorage.removeItem(key);
}
}
};
const tvWidget = new widget(widgetOptions);
tvWidget.onChartReady(() => {
tvWidgetRef.current = tvWidget;
tvWidget
// #ts-ignore
.subscribe("onAutoSaveNeeded", () => tvWidget.saveChartToServer());
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [market, tvWidgetRef.current]);
return <div id={defaultProps.containerId} className={"TVChartContainer"} />;
};
function useTvDataFeed() {
throw new Error("Function not implemented.");
}
ps: i've tried to implement this project : https://github.com/project-serum/serum-dex-ui

Related

How to relaunch an electron/react application on crash

I have an application built with react and electron, here is the issue that is occurring.
Sometimes when launching the application it will have an uncaught exception because of some IPC communication that failed.
I added a handler for this in my electron entry point file according to the documentation. However, when it relaunches it does not launch MY application. It simply displays some electron template window.
Here is the handler I'm using:
process.on("uncaughtException", function (err) {
//log the message and stack trace
log.warn("uncaught Exception: ", err);
//relaunch the app
app.relaunch({ args: [] });
app.exit(0);
handleLaunch(tray, window, store, __dirname);
});
The handleLaunch function is as such:
// Library Imports
const { app, BrowserWindow, dialog } = require("electron");
const { autoUpdater } = require("electron-updater");
const log = require("electron-log");
//Functions
const { createIpcBusBridge } = require("../ipc/createIpcBusBridge");
const { createWindow } = require("../window/createWindow");
const { createTray } = require("../tray/createTray");
const handleLaunch = (tray, window, store, directoryName) => {
const isDev = !app.isPackaged;
if (isDev === true) {
const reactDevToolsId = "fmkadmapgofadopljbjfkapdkoienihi";
const {
default: installExtension,
REDUX_DEVTOOLS,
} = require("electron-devtools-installer");
installExtension([REDUX_DEVTOOLS, reactDevToolsId])
.then((name) => console.log(`Added Extension: ${name}`))
.catch((err) => console.log("An error occurred: ", err));
}
log.info("CREATING WINDOW...........");
window = createWindow(directoryName, process, store, isDev);
if (tray !== undefined) {
tray.destroy();
}
tray = createTray(window, directoryName, process);
createIpcBusBridge();
app.on("activate", function () {
/*
On macOS it's common to re-create a window in the app when the
dock icon is clicked and there are no other windows open.
*/
if (BrowserWindow.getAllWindows().length === 0)
createWindow(window, tray, directoryName, process, store);
});
if (isDev === false) {
autoUpdater.on("update-available", (_event, releaseNotes, releaseName) => {
const dialogOpts = {
type: "info",
buttons: ["Ok"],
title: "Application Update",
message: process.platform === "win32" ? releaseNotes : releaseName,
detail: "A new version is being downloaded.",
};
dialog.showMessageBox(dialogOpts, (response) => {});
});
autoUpdater.on("update-downloaded", (_event, releaseNotes, releaseName) => {
const dialogOpts = {
type: "info",
buttons: ["Restart", "Later"],
title: "Application Update",
message: process.platform === "win32" ? releaseNotes : releaseName,
detail:
"A new version has been downloaded. Restart the application to apply the updates.",
};
dialog.showMessageBox(dialogOpts).then((returnValue) => {
if (returnValue.response === 0) autoUpdater.quitAndInstall();
});
});
}
};
module.exports = { handleLaunch };
Here is the createWindow function as requested by Kiran Maniya
// Library Imports
const { BrowserWindow, ipcMain } = require("electron");
const path = require("path");
const url = require("url");
const log = require("electron-log");
// Functions
const { handleResolutionPref } = require("./handleResolutionPref");
const { handlePositionPref } = require("./handlePositionPref");
const { maximizeWindow } = require("./maximizeWindow");
const { minimizeWindow } = require("./minimizeWindow");
const { closeWindow } = require("./closeWindow");
const createWindow = (directoryName, process, store, isDev) => {
try {
const [screenWidth, screenHeight] = handleResolutionPref(store);
const [screenXCoordinate, screenYCoordinate, isScreenPositionCustom] =
handlePositionPref(store);
let window = null;
const browserWindowOptions = {
width: screenWidth,
height: screenHeight,
frame: false,
fullscreenable: true,
resizable: true,
transparent: false,
webPreferences: {
preload: path.join(directoryName, "preload.bundle.js"),
contextIsolation: false,
nodeIntegration: true,
sandbox: false,
webSecurity: false,
},
icon: path.join(directoryName, "icon.ico"),
};
// Create the browser window.
if (isScreenPositionCustom === true) {
browserWindowOptions.x = screenXCoordinate;
browserWindowOptions.y = screenYCoordinate;
window = new BrowserWindow(browserWindowOptions);
} else {
window = new BrowserWindow(browserWindowOptions);
}
window.on("closed", () => (window = null));
if (isDev === true) {
window.loadURL("http://localhost:3000");
} else {
window.loadURL(
url.format({
pathname: path.join(directoryName, "index.html"),
protocol: "file:",
slashes: true,
})
);
}
// Handle window toggling for custom titlebar
ipcMain.on("windowMinimize", () => minimizeWindow(window));
ipcMain.on("windowMaximize", () => maximizeWindow(window));
ipcMain.on("windowClose", () => closeWindow(window));
// Open the DevTools.
// window.webContents.openDevTools()
return window;
} catch (error) {
log.info("CREATE WINDOW ERROR INSIDE FUNCTION: ", error);
}
};
module.exports = { createWindow };
Where am I going wrong here?

How can i make a button actvate my searchSpell function?

i am finishing my first react project. But I cant make this button work. I keep giving me the same error below
error console message: Uncaught TypeError_axios_api_js__WEBPACK_IMPORTED_MODULE_1__.default.request is not a function
code:
function Header(){
const { searchSpell } = Hooker();
const [whatSpell, setWhatSpell] = useState()
function pesquisar () {
if(!whatSpell){
alert("escreva alguma coisa antes de pesquisar")
return
} else{
return searchSpell(whatSpell)
}
}
another code:
import { SpellContext } from "../provider.js"
function Hooker (){
const { spellState, searchSpell } = useContext(SpellContext)
return { spellState, searchSpell }
}
export default Hooker
and the function one:
function BaseInfo({ children }){
const [spellState, setSpellState] = useState({
name: undefined,
desc: undefined,
higher_level: undefined,
range: undefined,
components: undefined,
material: undefined,
ritual: false,
duration: undefined,
concentration: false,
casting_time: undefined,
level: 0,
});
const searchSpell = (spellName) => {
api.request(spellName).then(function(response) {
setSpellState(prevState => ({
...prevState,
name: response.data.name,
desc: response.data.desc,
higher_level: response.data.higher_level,
range: response.data.range,
components: response.data.components,
material: response.data.material,
ritual: response.data.ritual,
duration: response.data.duration,
concentration: response.data.concentration,
casting_time: response.data.duration,
level: response.data.duration,
})
)
})
console.log(spellState.duration)
}
const contextValue = {
spellState,
searchSpell: useCallback((spellName) => searchSpell(spellName), []),
}
return(
<SpellContext.Provider value={contextValue}>
{children}
</SpellContext.Provider>
)
}
export default BaseInfo
I don't think it's the button's fault. The error message indicates you're calling searchSpell, but there is something wrong with the way you're writing the API request.
If you're using axios as the error suggests. Check the axios documentation for proper installation, importing and usage.
Example usage for your use case:
import axios from "axios"
// ... ...
axios.request(spellName).then(function() {
// ... ...

Error: `siteUrl` does not exist on `siteMetadata` in the data returned from the query. How to resolve?

When building my Gatsby website I get the below error.
I've tried to delete and reinstall npm, update the plugins, deleting (Gatsby) cache, playing around with the siteUrl and all kinds of settings in the Gatsby config. But I can't seem to get rid of the error. The development environment works fine.
github: https://github.com/bartfluitsma/gatsby-bart-fluitsma
**Error console log**
ERROR #11321 PLUGIN
"gatsby-plugin-sitemap" threw an error while running the onPostBuild lifecycle:
`siteUrl` does not exist on `siteMetadata` in the data returned from the query.
Add this to your `siteMetadata` object inside gatsby-config.js or add this to your custom query or provide a custom `resolveSiteUrl` function.
https://www.gatsbyjs.com/plugins/gatsby-plugin-sitemap/#api-reference
47 | errors = _yield$graphql.errors;
48 | _context.next = 9;
> 49 | return Promise.resolve(resolveSiteUrl(queryRecords)).catch(function (err) {
| ^
50 | return reporter.panic(_internals.REPORTER_PREFIX + " Error resolving Site URL", err);
51 | });
52 |
File: node_modules\gatsby-plugin-sitemap\gatsby-node.js:49:36
Error: `siteUrl` does not exist on `siteMetadata` in the data returned from the query.
Add this to your `siteMetadata` object inside gatsby-config.js or add this to your custom query or provide a custom `resolveSiteUrl` function.
https://www.gatsbyjs.com/plugins/gatsby-plugin-sitemap/#api-reference
- internals.js:62 resolveSiteUrl
[gatsby-bart-fluitsma]/[gatsby-plugin-sitemap]/internals.js:62:11
- gatsby-node.js:49 _callee$
[gatsby-bart-fluitsma]/[gatsby-plugin-sitemap]/gatsby-node.js:49:36
not finished onPostBuild - 0.480s
Gatsby-config.js
module.exports = {
siteMetadata: {
title: `Bart Fluitsma`,
description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
author: `#gatsbyjs`,
siteUrl: `http://bartfluitsma.com`,
},
plugins: [
`gatsby-plugin-react-helmet`,
`gatsby-plugin-image`,
'gatsby-plugin-postcss',
{
resolve: `gatsby-plugin-google-fonts-with-attributes`,
options: {
fonts: [
`montserrat\:300,400,400i,600,900`,
],
display: 'swap',
attributes: {
rel: "stylesheet preload prefetch",
},
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
}, {
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/src/locales`,
name: `locale`
}
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `Web development | Bart Fluitsma`,
short_name: `Bart develops`,
start_url: `/`,
background_color: `#663399`,
// This will impact how browsers show your PWA/website
// https://css-tricks.com/meta-theme-color-and-trickery/
// theme_color: `#663399`,
display: `minimal-ui`,
icon: `src/images/logo-bart-fluitsma-web-design.svg`, // This path is relative to the root of the site.
},
},
{
resolve: `gatsby-plugin-react-i18next`,
options: {
localeJsonSourceName: `locale`, // name given to `gatsby-source-filesystem` plugin.
languages: [`en`, `nl`],
defaultLanguage: `en`,
// if you are using Helmet, you must include siteUrl, and make sure you add http:https
siteUrl: `https://bartfluitsma.com`,
// you can pass any i18next options
i18nextOptions: {
interpolation: {
escapeValue: false // not needed for react as it escapes by default
},
keySeparator: false,
nsSeparator: false
},
pages: [
{
matchPath: '/:lang?/blog/:uid',
getLanguageFromPath: true
},
]
}
},
// this (optional) plugin enables Progressive Web App + Offline functionality
// To learn more, visit: https://gatsby.dev/offline
// `gatsby-plugin-offline`,
{
resolve: 'gatsby-plugin-sitemap',
options: {
excludes: ['/**/404', '/**/404.html'],
query: `
{
site {
siteMetadata {
siteUrl
}
}
allSitePage(filter: {context: {i18n: {routed: {eq: false}}}}) {
edges {
node {
context {
i18n {
defaultLanguage
languages
originalPath
}
}
path
}
}
}
}
`,
serialize: ({ site, allSitePage }) => {
return allSitePage.edges.map((edge) => {
const { languages, originalPath, defaultLanguage } = edge.node.context.i18n;
const { siteUrl } = site.siteMetadata;
const url = siteUrl + originalPath;
const links = [
{ lang: defaultLanguage, url },
{ lang: 'x-default', url }
];
languages.forEach((lang) => {
if (lang === defaultLanguage) return;
links.push({ lang, url: `${siteUrl}/${lang}${originalPath}` });
});
return {
url,
changefreq: 'daily',
priority: originalPath === '/' ? 1.0 : 0.7,
links
};
});
}
}
},
],
}
The error is thrown by gatsby-plugin-sitemap. Try adding the resolveSiteUrl method in your configuration like:
const siteUrl = process.env.URL || `https://fallback.net`
resolveSiteUrl: () => siteUrl,
Applied to your code:
const siteUrl = process.env.URL || `https://fallback.net`
module.exports = {
plugins: [
{
resolve: "gatsby-plugin-sitemap",
options: {
excludes: ["/**/404", "/**/404.html"],
query: `
{
site {
siteMetadata {
siteUrl
}
}
allSitePage(filter: {context: {i18n: {routed: {eq: false}}}}) {
edges {
node {
context {
i18n {
defaultLanguage
languages
originalPath
}
}
path
}
}
}
}
`,
resolveSiteUrl: () => siteUrl,
serialize: ({ site, allSitePage }) => {
return allSitePage.edges.map((edge) => {
const { languages, originalPath, defaultLanguage } =
edge.node.context.i18n;
const { siteUrl } = site.siteMetadata;
const url = siteUrl + originalPath;
const links = [
{ lang: defaultLanguage, url },
{ lang: "x-default", url },
];
languages.forEach((lang) => {
if (lang === defaultLanguage) return;
links.push({ lang, url: `${siteUrl}/${lang}${originalPath}` });
});
return {
url,
changefreq: "daily",
priority: originalPath === "/" ? 1.0 : 0.7,
links,
};
});
},
},
},
],
};
Change the siteUrl and the fallback URL accordingly if you are not setting it in your environment file
The answer by Ferran Buireu ultimately was not the solution for OP. I had experienced the same issue and this solution would have solved his issue hadn't he abandoned it. Check this GitHub thread.
Your siteUrl issue just masks that the query was invalid, as the context is not available in gatsby >= 4 anymore, as you found out after fixing the siteUrl.
You may have used this query from the gatsby-plugin-react-i18next docs to support a sitemap.
In order to make it work, I found you have to 1. create the context yourself, and 2. adjust the queries
Create your context through gatsby-node.js (credit wilsonvolker)
/**
* Workaround for missing sitePage.context:
* Used for generating sitemap with `gatsby-plugin-react-i18next` and `gatsby-plugin-sitemap` plugins
* https://www.gatsbyjs.com/docs/reference/release-notes/migrating-from-v3-to-v4/#field-sitepagecontext-is-no-longer-available-in-graphql-queries
*/
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions
createTypes(`
type SitePage implements Node {
context: SitePageContext
}
type SitePageContext {
i18n: i18nContext
}
type i18nContext {
language: String,
languages: [String],
defaultLanguage: String,
originalPath: String
routed: Boolean
}
`)
}
It looks like the serialize function proposed in the i18next doesn't work as-is anymore since it apparently receives a single node, not the full graphql response. So, a few changes in gatsby-config.js to make it work again (this assumes you have a global siteUrl variable available):
query: `
{
site {
siteMetadata {
siteUrl
}
}
allSitePage(filter: {context: {i18n: {routed: {eq: false}}}}) {
nodes {
context {
i18n {
defaultLanguage
languages
originalPath
}
}
path
}
}
}
`,
serialize: (node) => {
const { languages, originalPath, defaultLanguage } = node.context.i18n
const url = siteUrl + originalPath
const links = [
{ lang: defaultLanguage, url },
{ lang: 'x-default', url },
]
languages.forEach((lang) => {
if (lang === defaultLanguage) return
links.push({ lang, url: `${siteUrl}/${lang}${originalPath}` })
})
return {
url,
changefreq: 'daily',
priority: originalPath === '/' ? 1.0 : 0.7,
links,
}
},
This worked for me without the need to create new types:
{
resolve: "gatsby-plugin-sitemap",
options: {
excludes: ["/**/404", "/**/404.html"],
resolveSiteUrl: () => siteUrl,
query: `
{
allSitePage {
edges {
node {
pageContext
}
}
}
}
`,
resolvePages: ({ allSitePage: { edges } }) => {
return edges
.filter(
({ node }) => !["/404/", "/404.html"].includes(node.pageContext.i18n.originalPath)
)
.map(({ node: { pageContext } }) => {
const { languages, originalPath, path, defaultLanguage } = pageContext.i18n;
const baseUrl = siteUrl + originalPath;
const links = [{ lang: "x-default", url: baseUrl }];
languages.forEach((lang) => {
const isDefaultLang = lang === defaultLanguage;
const isDefaultPath = path === originalPath;
const isLangSubDir = path.includes(`${lang}/`);
if (isDefaultLang && isDefaultPath) return;
if (!isDefaultLang && isLangSubDir) return;
links.push({
lang,
url: isDefaultLang ? baseUrl : `${siteUrl}/${lang}${originalPath}`,
});
});
return {
path,
url: path === "/" ? siteUrl : `${siteUrl}/${path}`,
changefreq: "daily",
priority: originalPath === "/" ? 1.0 : 0.7,
links,
};
});
},
serialize: (page) => page,
},
}
Versions:
Node: 18.13.0
"gatsby": "^5.3.3",
"gatsby-plugin-react-i18next": "^3.0.1",
"gatsby-plugin-sitemap": "^6.5.0",

Electron/react application shows extension server error

I've been using an electron/react boilerplate for my application, yet I find myself facing a dreaded empty white screen as the console spits the following error message at me repeatedly:
[31308:0413/104846.234:ERROR:CONSOLE(1)] "Extension server error: Operation failed: Permission denied", source: devtools://devtools/bundled/models/extensions/extensions.js (1)
This error suddenly popped up without much warning as it was working fine earlier, though I suspect it might have something to do with changes I made to the ipcRenderer.
Along with this, the following errors pop up in the console: https://gyazo.com/1c3e3f22f65fd6f7db0fd9549969581b
Here's my preload.ts:
contextBridge.exposeInMainWorld('electron', {
ipcRenderer: {
myPing() {
ipcRenderer.send('ipc-example', 'ping');
},
on(channel: string, func: (...args: unknown[]) => void) {
const validChannels = ['ipc-example'];
if (validChannels.includes(channel)) {
const subscription = (_event: IpcRendererEvent, ...args: unknown[]) =>
func(...args);
// Deliberately strip event as it includes `sender`
ipcRenderer.on(channel, subscription);
return () => ipcRenderer.removeListener(channel, subscription);
}
return undefined;
},
once(channel: string, func: (...args: unknown[]) => void) {
const validChannels = ['ipc-example'];
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`
ipcRenderer.once(channel, (_event, ...args) => func(...args));
}
},
},
});
And here's my main.ts:
/**
* This module executes inside of electron's main process. You can start
* electron renderer process from here and communicate with the other processes
* through IPC.
*
* When running `npm run build` or `npm run build:main`, this file is compiled to
* `./src/main.js` using webpack. This gives us some performance wins.
*/
import path from 'path';
import { app, BrowserWindow, shell, ipcMain } from 'electron';
import { autoUpdater } from 'electron-updater';
import log from 'electron-log';
import MenuBuilder from './components/containers/menu';
import { resolveHtmlPath } from './main/util';
export default class AppUpdater {
constructor() {
log.transports.file.level = 'info';
autoUpdater.logger = log;
autoUpdater.checkForUpdatesAndNotify();
}
}
let mainWindow: BrowserWindow | null = null;
ipcMain.on('ipc-example', async (event, arg) => {
const msgTemplate = (pingPong: string) => `IPC test: ${pingPong}`;
console.log(msgTemplate(arg));
event.reply('ipc-example', msgTemplate('pong'));
});
if (process.env.NODE_ENV === 'production') {
const sourceMapSupport = require('source-map-support');
sourceMapSupport.install();
}
const isDevelopment =
process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true';
if (isDevelopment) {
require('electron-debug')();
}
const installExtensions = async () => {
const installer = require('electron-devtools-installer');
const forceDownload = !!process.env.UPGRADE_EXTENSIONS;
const extensions = ['REACT_DEVELOPER_TOOLS'];
return installer
.default(
extensions.map((name) => installer[name]),
forceDownload
)
.catch(console.log);
};
const createWindow = async () => {
if (isDevelopment) {
await installExtensions();
}
const RESOURCES_PATH = app.isPackaged
? path.join(process.resourcesPath, 'assets')
: path.join(__dirname, '../../assets');
const getAssetPath = (...paths: string[]): string => {
return path.join(RESOURCES_PATH, ...paths);
};
mainWindow = new BrowserWindow({
show: false,
width: 1024,
height: 728,
icon: getAssetPath('icon.png'),
webPreferences: {
contextIsolation: true,
preload: app.isPackaged
? path.join(__dirname, 'preload.js')
: path.join(__dirname, '../../.erb/dll/preload.js'),
},
});
mainWindow.loadURL(resolveHtmlPath('index.html'));
mainWindow.on('ready-to-show', () => {
if (!mainWindow) {
throw new Error('"mainWindow" is not defined');
}
if (process.env.START_MINIMIZED) {
mainWindow.minimize();
} else {
mainWindow.show();
}
});
mainWindow.on('closed', () => {
mainWindow = null;
});
const menuBuilder = new MenuBuilder(mainWindow);
menuBuilder.buildMenu();
// Open urls in the user's browser
mainWindow.webContents.setWindowOpenHandler((edata) => {
shell.openExternal(edata.url);
return { action: 'deny' };
});
// Remove this if your app does not use auto updates
// eslint-disable-next-line
new AppUpdater();
};
/**
* Add event listeners...
*/
app.on('window-all-closed', () => {
// Respect the OSX convention of having the application in memory even
// after all windows have been closed
if (process.platform !== 'darwin') {
app.quit();
}
});
app
.whenReady()
.then(() => {
createWindow();
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) createWindow();
});
})
.catch(console.log);
Does this error seem familiar to anyone? I've no clue how to go about solving this.

While trying to create pages in gatsby-node, I received this build error

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"
/>

Resources