Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problems with graceful-fs/polyfills.js : process.version "undefined" #196

Open
raphael10-collab opened this issue Sep 5, 2020 · 21 comments

Comments

@raphael10-collab
Copy link

raphael10-collab commented Sep 5, 2020

I'm encountering this problem:

I discovered that once I activate this line:

const stateRecord: App = loadSettings()

in /src/store/modules/app.ts

I get this error: "Cannot read property 'match' of undefined"

image

This is /src/store/modules/app.ts :

import Vue from 'vue'
import { loadSettings, setSettings } from '@/services/electron-services/setting/setting'

const TOGGLE_THEME = 'TOGGLE_THEME'
const TOGGLE_LANG = 'TOGGLE_LANG'

const stateRecord: App = loadSettings()

const app = {
  state: {
    currentTheme: stateRecord.currentTheme || 'light',
  },
  mutations: {
    [TOGGLE_THEME](state: App, currentTheme: Theme) {
      state.currentTheme = currentTheme
    },
  },
  actions: {
    TOGGLE_THEME({ commit }: any, payload: App) {
      setSettings('settings.currentTheme', payload.currentTheme)
      commit(TOGGLE_THEME, payload.currentTheme)
    },
  },
}

export default app

this is src/services/electron-services/setting/setting :

import db from '../database/index'

export const loadSettings = (): App => {
  return db.get<App>('settings')
}

export const setSettings = (key: string, value: string | boolean | number): string | boolean 
| number => {
  return db.set<string | boolean | number>(key, value)
}

export default {}

and this is electron-services/database/index.ts :

import Lowdb from 'lowdb'
import FileSync from 'lowdb/adapters/FileSync'
import path from 'path'
import fs from 'fs-extra'
import LodashID from 'lodash-id'
import { app, remote } from 'electron'

interface Schema {
  windowSize: {
    height: number
    width: number
  }
  settings: {
    currentLang: string
    currentTheme: string
  }
}

const isRenderer: boolean = process.type === 'renderer'
// Render process use remote app
const APP: Electron.App = isRenderer ? remote.app : app

const STORE_PATH: string = APP.getPath('userData')

// In production mode, during the first open application
// APP.getPath('userData') gets the path nested and the datastore.js is loaded.
// if it doesn't exist, create it.
if (!isRenderer) {
  if (!fs.pathExistsSync(STORE_PATH)) {
    fs.mkdirpSync(STORE_PATH)
  }
}

class DB {
  private db: Lowdb.LowdbSync<Schema>
  public constructor() {
    const adapter: Lowdb.AdapterSync<Schema> = new FileSync<Schema>(path.join(STORE_PATH, 
'/db.json'))
    this.db = Lowdb(adapter)
    // Use lodash-id must use insert methods
    this.db._.mixin(LodashID)
    if (!this.db.has('windowSize').value()) {
      this.db
        .set('windowSize', {
          width: 1025,
          height: 749,
        })
        .write()
    }
    if (!this.db.has('settings').value()) {
      this.db
        .set('settings', {
          currentLang: 'en',
          currentTheme: 'light',
        })
        .write()
    }
    // Purple to Night
    if (this.db.get('settings.currentTheme').value() === 'purple') {
      this.db.set('settings.currentTheme', 'night').write()
    }
    if (!this.db.has('settings.currentLang')) {
      this.db.set('settings.currentLang', 'en').write()
    }
  }
  // read() is to keep the data of the main process and the rendering process up to date.
  public read() {
    return this.db.read()
  }
  public get<T>(key: string): T {
    return this.read().get(key).value()
    //return this.db.get(key).value()
  }
  public find<T>(key: string, id: string): T {
    const data: $TSFixed = this.read().get(key)
    return data.find({ id }).value()
  }
  public set<T>(key: string, value: T): T {
    //return this.read().set(key, value).write()
    return this.db.set(key, value).write()
  }
  public insert<T>(key: string, value: T): T {
    const data: $TSFixed = this.read().get(key)
    return data.insert(value).write()
  }
  public update<T>(key: string, id: string, value: T): T {
    const data: $TSFixed = this.read().get(key)
    return data.find({ id }).assign(value).write()
  }
  public remove<T>(key: string, id: string): T {
    const data: $TSFixed = this.read().get(key)
    return data.removeById(id).write()
  }
  public filter<T, K>(key: string, query: K): T {
    const data: $TSFixed = this.read().get(key)
    return data.filter(query).value()
  }
  public has(key: string): boolean {
    return this.read().has(key).value()
  }
}

The operation setSettings has the same problem:
once I only activate setSettings in src/store/modules/app.ts I get the same error:

import Vue from 'vue'
//import { loadSettings, setSettings } from '@/services/electron-services/setting/setting'
import { setSettings } from '@/services/electron-services/setting/setting'

const TOGGLE_THEME = 'TOGGLE_THEME'
const TOGGLE_LANG = 'TOGGLE_LANG'

//const stateRecord: App = loadSettings()

const app = {
  state: {
    //currentTheme: stateRecord.currentTheme || 'dark',
    //currentLang: stateRecord.currentLang || 'en',
    //currentTheme: 'light',
  },
  mutations: {
    //[TOGGLE_THEME](state: App, currentTheme: Theme) {
    //  state.currentTheme = currentTheme
    //},
    //[TOGGLE_LANG](state: App, currentLang: Language) {
    //  state.currentLang = currentLang
    //},
  },
  actions: {
    TOGGLE_THEME({ commit }: any, payload: App) {
      setSettings('settings.currentTheme', payload.currentTheme)
      commit(TOGGLE_THEME, payload.currentTheme)
    },
    //TOGGLE_LANG({ commit }: any, payload: App) {
    //  setSettings('settings.currentLang', payload.currentLang)
    //  commit(TOGGLE_LANG, payload.currentLang)
    //},
  },
}

export default app

src/services/electron-services/setting/setting.ts :

import db from '../database/index'

//export const loadSettings = (): App => {
//  return db.get<App>('settings')
//}

export const setSettings = (key: string, value: string | boolean | number): string | boolean | number => {
  return db.set<string | boolean | number>(key, value)
}

export default {}

image

Also modifying

public constructor() {
    // const adapter: Lowdb.AdapterSync<Schema> = new FileSync<Schema>(path.join(STORE_PATH, '/db.json'))
    const adapter= new FileSync('db.json')

still get this error

image

This is the line in fileSync.js which seems to be involved:

image

It seems that the line involved in node_modules/graceful-fs/polyfills.js is the following:

 process.version.match(/^v0\.6\.[0-2]|^v0\.5\./))

in this function:

function patch (fs) {
  // (re-)implement some things that are known busted or missing.

  // lchmod, broken prior to 0.6.2
  // back-port the fix here.
  if (constants.hasOwnProperty('O_SYMLINK') &&
    process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {   // <------------------------------------------------------------------------------------
    patchLchmod(fs)
  }

vue info:

Environment Info:

  System:
    OS: Linux 5.4 Ubuntu 18.04.5 LTS (Bionic Beaver)
    CPU: (8) x64 Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz
  Binaries:
    Node: 14.5.0 - ~/.nvm/versions/node/v14.5.0/bin/node
    Yarn: 1.22.5 - /usr/bin/yarn
    npm: 6.14.5 - ~/.nvm/versions/node/v14.5.0/bin/npm
  Browsers:
    Chrome: 85.0.4183.83
    Firefox: 80.0
  npmPackages:
    @vue/babel-helper-vue-jsx-merge-props:  1.0.0 
    @vue/babel-plugin-transform-vue-jsx:  1.1.2 
    @vue/babel-preset-app:  4.4.6 
    @vue/babel-preset-jsx:  1.1.2 
    @vue/babel-sugar-functional-vue:  1.1.2 
    @vue/babel-sugar-inject-h:  1.1.2 
    @vue/babel-sugar-v-model:  1.1.2 
    @vue/babel-sugar-v-on:  1.1.2 
    @vue/cli-overlay:  4.4.6 
    @vue/cli-plugin-babel: ~4.4.0 => 4.4.6 
    @vue/cli-plugin-e2e-cypress: ~4.4.0 => 4.4.6 
    @vue/cli-plugin-router: ~4.4.0 => 4.4.6 
    @vue/cli-plugin-typescript: ~4.4.0 => 4.4.6 
    @vue/cli-plugin-unit-mocha: ~4.4.0 => 4.4.6 
    @vue/cli-plugin-vuex: ~4.4.0 => 4.4.6 
    @vue/cli-service: ~4.4.0 => 4.4.6 
    @vue/cli-shared-utils:  4.4.6 
    @vue/component-compiler-utils:  3.2.0 
    @vue/preload-webpack-plugin:  1.1.2 
    @vue/test-utils: ^1.0.3 => 1.0.3 
    @vue/web-component-wrapper:  1.2.0 
    babel-helper-vue-jsx-merge-props:  2.0.3 
    typescript: ^3.9.7 => 3.9.7 
    vue: ^2.6.11 => 2.6.11 
    vue-class-component: ^7.2.5 => 7.2.5 
    vue-cli-plugin-electron-builder: ~2.0.0-rc.4 => 2.0.0-rc.4 
    vue-hot-reload-api:  2.3.4 
    vue-i18n: ^8.20.0 => 8.20.0 
    vue-loader:  15.9.3 
    vue-property-decorator: ^9.0.0 => 9.0.0 
    vue-router: ^3.2.0 => 3.3.4 
    vue-style-loader:  4.1.2 
    vue-template-compiler: ^2.6.11 => 2.6.11 
    vue-template-es2015-compiler:  1.9.1 
    vuex: ^3.5.1 => 3.5.1 
    vuex-class: ^0.3.2 => 0.3.2 
  npmGlobalPackages:
    @vue/cli: 4.4.6

  electron version: 10.0.0

This is vue.config.js :

const WorkerPlugin = require('worker-plugin')

module.exports = {
  // options...
  publicPath: '',
  pluginOptions: {
    electronBuilder: {
      // Prevent bundling of certain imported packages and instead retrieve these external 
dependencies at runtime.
      // In order to connect to websocket.
      // https://github.com/nklayman/vue-cli-plugin-electron-builder/issues
/652#issuecomment-583764345
      externals: ['ggc', 'tesseract.js'],
      builderOptions: {
        productName: 'GGC',
        win: {
          icon: './public/app.ico'
        },
        mac: {
          icon: './public/icons/Icon.icns',
          target: [
            'pkg',
            'dmg',
            'zip',
          ],
        },
        linux: {
          icon: './public/app.png'
        }
      },
      // https://nklayman.github.io/vue-cli-plugin-electron-builder/guide
/configuration.html#webpack-configuration
      chainWebpackRendererProcess: (config) => {
        // Chain webpack config for electron renderer process only
        // The following example will set IS_ELECTRON to true in your app
        config.plugin('define').tap((args) => {
          args[0]['IS_ELECTRON'] = true
          return args
        })
      },
      mainProcessFile: 'src/background.ts',
      // https://nklayman.github.io/vue-cli-plugin-electron-builder/guide
/configuration.html#typescript-options
      disableMainProcessTypescript: false, // Manually disable typescript plugin for main 
process. Enable if you want to use regular js for the main process (src/background.js by 
default)
      mainProcessTypeChecking: false, // Manually enable type checking during webpck 
bundling for background file.
      // https://nklayman.github.io/vue-cli-plugin-electron-builder/guide
/guide.html#preload-files
      preload: 'src/preload.js',
      // https://nklayman.github.io/vue-cli-plugin-electron-builder/guide
/security.html#node-integration
      nodeIntegration: false
    },
    // https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/guide.html#web-
workers
    configureWebpack: {
      plugins: [new WorkerPlugin()]
    }
  }
}

And this is webpack.config.js :

module.exports = {
  entry: './src/background.ts',
  target: 'node',
  output: {
    path: path.join(__dirname, 'build'),
    filename: 'background.js'
  },
  // https://github.com/GoogleChromeLabs/worker-plugin
  plugins: [
    new WorkerPlugin()
  ],
  // https://webpack.js.org/plugins/define-plugin/
  new webpack.DefinePlugin({
    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
  }),
  //https://vuetifyjs.com/en/getting-started/quick-start/#webpack-install
  rules: [
    {
      test: /\.s(c|a)ss$/,
      use: [
        'vue-style-loader',
        'css-loader',
        {
          loader: 'sass-loader',
          // Requires sass-loader@^7.0.0
          options: {
            implementation: require('sass'),
            fiber: require('fibers'),
            indentedSyntax: true // optional
          },
          // Requires sass-loader@^8.0.0
          options: {
            implementation: require('sass'),
            sassOptions: {
              fiber: require('fibers'),
              indentedSyntax: true // optional
            },
          },
        },
      ],
    },
  ],
}

This is vue.config.js :

const WorkerPlugin = require('worker-plugin')

module.exports = {
  // options...
  publicPath: '',
  pluginOptions: {
    electronBuilder: {
      // Prevent bundling of certain imported packages and instead retrieve these external 
dependencies at runtime.
      // In order to connect to websocket.
      // https://github.com/nklayman/vue-cli-plugin-electron-builder/issues
/652#issuecomment-583764345
      externals: ['ggc', 'tesseract.js'],
      builderOptions: {
        productName: 'GGC',
        win: {
          icon: './public/app.ico'
        },
        mac: {
          icon: './public/icons/Icon.icns',
          target: [
            'pkg',
            'dmg',
            'zip',
          ],
        },
        linux: {
          icon: './public/app.png'
        }
      },
      // https://nklayman.github.io/vue-cli-plugin-electron-builder/guide
/configuration.html#webpack-configuration
      chainWebpackRendererProcess: (config) => {
        // Chain webpack config for electron renderer process only
        // The following example will set IS_ELECTRON to true in your app
        config.plugin('define').tap((args) => {
          args[0]['IS_ELECTRON'] = true
          return args
        })
      },
      mainProcessFile: 'src/background.ts',
      // https://nklayman.github.io/vue-cli-plugin-electron-builder/guide
/configuration.html#typescript-options
      disableMainProcessTypescript: false, // Manually disable typescript plugin for main 
process. Enable if you want to use regular js for the main process (src/background.js by 
default)
      mainProcessTypeChecking: false, // Manually enable type checking during webpck 
bundling for background file.
      // https://nklayman.github.io/vue-cli-plugin-electron-builder/guide
/guide.html#preload-files
      preload: 'src/preload.js',
      // https://nklayman.github.io/vue-cli-plugin-electron-builder/guide
/security.html#node-integration
      nodeIntegration: false
    },
    // https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/guide.html#web-
workers
    configureWebpack: {
      plugins: [new WorkerPlugin()]
    }
  }
}

I've put in node_modules/graceful-fs/polyfill.js
console.log("process.version: ", process.version) :

function patch (fs) {
  // (re-)implement some things that are known busted or missing.

  // lchmod, broken prior to 0.6.2
  // back-port the fix here.

  console.log("process.version: ", process.version)

  if (constants.hasOwnProperty('O_SYMLINK') &&
      process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
    patchLchmod(fs)
  }

And this is the output:

process.version: undefined

image

node is working fine:

(base) marco@pc01:~/webMatters/electronMatters/ElectronVueTypeScriptScaffolding$ node -v
v14.5.0


(base) marco@pc01:~/webMatters/electronMatters/ElectronVueTypeScriptScaffolding$ node
Welcome to Node.js v14.5.0.
Type ".help" for more information.


> console.log(process.versions)
{
  node: '14.5.0',
  v8: '8.3.110.9-node.23',
  uv: '1.38.0',
  zlib: '1.2.11',
  brotli: '1.0.7',
  ares: '1.16.0',
  modules: '83',
  nghttp2: '1.41.0',
  napi: '6',
  llhttp: '2.0.4',
  openssl: '1.1.1g',
  cldr: '37.0',
  icu: '67.1',
  tz: '2020a',
  unicode: '13.0'
}

> console.log(process.version)
v14.5.0

May be this version "undefined" is due to the fact that I set, to keep the app as safe as possible, nodeIntegration: false in

webPreferences: {
      nodeIntegration: false,
      contextIsolation: true, // protects against prototype pollution
      preload: path.join(__dirname, "../dist_electron/preload.js"),
    },

?
But this nodeIntegration: false shouldn't affect the node functioning and in particular the node's process version

I searched in graceful-fs folder for all the occurences of process.version :

(base) marco@pc01:~/webMatters/electronMatters/ElectronVueTypeScriptScaffolding/node_modules/graceful-fs$ grep   
--recursive "process.version" *
graceful-fs.js:  if (process.version.substr(0, 4) === 'v0.8') {
polyfills.js:      process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {

Why process.version is "undefined" in node_modules/graceful-fs/polyfills.js ?
And why process.version is defined, thus not undefined in node_modules/graceful-fs/graceful-fs.js ?

If I put console.log in:

  if (process.version.substr(0, 4) === 'v0.8') {
     console.log("graceful-fs-process.version: ", process.version)
    var legStreams = legacy(fs)
    ReadStream = legStreams.ReadStream
    WriteStream = legStreams.WriteStream
  }

in node_modules/graceful-fs/graceful-fs.js

I do not get any output...

Putting console.log(process) in node_modules/graceful-js/polyfill.js :

function patch (fs) {
  // (re-)implement some things that are known busted or missing.

  // lchmod, broken prior to 0.6.2
  // back-port the fix here.

   console.log("process: ", process)

  console.log("process.version: ", process.version)

I get :

 INFO  Launching Electron...
process:  process {
  version: 'v12.16.3',
  versions: {
    node: '12.16.3',
    v8: '8.5.210.20-electron.0',
    uv: '1.34.2',
    zlib: '1.2.11',
    brotli: '1.0.7',
    ares: '1.16.0',
    modules: '82',
    nghttp2: '1.41.0',
    napi: '5',
    llhttp: '2.0.4',
    http_parser: '2.9.3',
    openssl: '1.1.0',
    icu: '67.1',
    unicode: '13.0',
    electron: '10.0.0',
    chrome: '85.0.4183.84'
  },
  arch: 'x64',
  platform: 'linux',
  release: {
    name: 'node',
    lts: 'Erbium',
    sourceUrl: 'https://nodejs.org/download/release/v12.16.3/node-v12.16.3.tar.gz',
    headersUrl: 'https://nodejs.org/download/release/v12.16.3/node-v12.16.3-headers.tar.gz'
  },
  _rawDebug: [Function: _rawDebug],

plenty of other output at the end of which :

process.version:  v12.16.3
(node:9831) ExtensionLoadWarning: Warnings loading extension at /home/marco/.config/base/extensions 
/nhdogjmejiglipccpnnnanhbledajbpd: Unrecognized manifest key 'browser_action'. Unrecognized manifest key 'update_url'.    
Permission 'contextMenus' is unknown or URL pattern is malformed. Cannot load extension with file or directory name    
_metadata. Filenames starting with "_" are reserved for use by the system. 
No type errors found
Version: typescript 3.9.7
Time: 4215ms

So, it seems that process.version used by node_modules/graceful-fs/polyfill.js is: v12.16.3

Why the print of console.log("process.version: ", process.version) gives "undefined" and not v12.16.3 ?

I've put nodeIntegration: true in src/background.ts :

    webPreferences: {
      // Use pluginOptions.nodeIntegration, leave this alone
      // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
      //nodeIntegration: (process.env
      //    .ELECTRON_NODE_INTEGRATION as unknown) as boolean,
      nodeIntegration: true,
      //nodeIntegration: false,
      //contextIsolation: true, // protects against prototype pollution
      //preload: path.join(__dirname, "../dist_electron/preload.js"),
    },

but still get the same error: "Uncaught TypeError: Cannot read property 'match' of undefined"

image

Anyway, as far as I understand, to keep electron.js app safer nodeIntegration: false in conjunction with the use of preload file should be preferred: https://www.electronjs.org/docs/tutorial/security#electron-security-warnings

I do not understand why process.version is "undefined" in node_modules/graceful-fs/polyfill.js but when printed outside of polyfill.js is v12.16.3

You can find the GitHub repo here: https://github.com/raphael10-collab/ElectronVueTypeScriptScaffolding

Looking forward to your kind help

@raphael10-collab raphael10-collab changed the title Problems with graceful-fs/polyfills.js Problems with graceful-fs/polyfills.js : process.version "undefined" Sep 5, 2020
@AimForNaN
Copy link

AimForNaN commented Sep 14, 2020

Here is a workaround I came across:

const { remote } = window.require('electron');
const fs = remote.require('fs-extra');

Just replace const fs = remote.require('fs-extra'); with whatever you're trying to import.

@raphael10-collab
Copy link
Author

Hi @truefusion
thanks for answering.

I do not understand what I should do.

In src/services/electron-services/database/index.ts I tried to substitute

//import fs from 'fs-extra'

with

import pathExistsSync from 'fs-extra/pathExistsSync'
import mkdirpSync from 'fs-extra/mkdirpSync'

if (!isRenderer) {
  //if (!fs.pathExistsSync(STORE_PATH)) {
    //fs.mkdirpSync(STORE_PATH)
  if (!pathExistsSync(STORE_PATH)) {
    mkdirpSync(STORE_PATH)
  }
}

but got "Cannot find module 'fs-extra/pathExistsSync' or its corresponding type declarations"
and "Cannot find module 'fs-extra/mkdirpSync' or its corresponding type declarations."

@AimForNaN
Copy link

AimForNaN commented Sep 15, 2020

I couldn't provide you with relevant code because I didn't know what exactly you were trying to do. But if you were trying to use the fs-extra module in an electron environment, then the code I provided should be enough. The code you responded with did not make use of the code I provided. I will assume you know how to program in JavaScript and about the many different ways to import or require modules, so I won't go into details for that. But if you are trying to use fs-extra in an electron environment, then you must use the code I provided in exactly the way I provided it.

In other words, this code

import fs from 'fs-extra'

Becomes this code

const { remote } = window.require('electron');
const fs = remote.require('fs-extra');

Then you can start using fs anywhere. For example,

const { remote } = window.require('electron');
const fs = remote.require('fs-extra');

if (!isRenderer) {
  if (!fs.pathExistsSync(STORE_PATH)) {
    fs.mkdirpSync(STORE_PATH)
  }
}

I don't know where isRenderer or STORE_PATH came from, but I don't need to know.

@raphael10-collab
Copy link
Author

@truefusion where does window come from?

@AimForNaN
Copy link

window is a pre-defined, global variable. Therefore it comes from the environment, in this case it would be from electron's environment. If you were running your script in a node environment, I would not expect window to be defined.

@raphael10-collab
Copy link
Author

@truefusion
I tried to put

//import fs from 'fs-extra'

const { BrowserWindow } = require('electron').remote
let window = new BrowserWindow()
const { remote } = window.require('electron');
const fs = remote.require('fs-extra');
import LodashID from 'lodash-id'
//import { app, remote } from 'electron'
import { app } from 'electron'

But I got this error:

A JavaScript error occurred in the main process
Uncaught Exception:
TypeError: Cannot destructure property 'BrowserWindow' of '__webpack_require__(...).remote' as it is undefined.
    at eval (webpack:///./src/services/electron-services/database/index.ts?:16:9)
    at Module../src/services/electron-services/database/index.ts (/home/marco/webMatters/electronMatters/GGC-Electron
/dist_electron/index.js:1984:1)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/GGC-Electron/dist_electron/index.js:20:30)
    at eval (webpack:///./src/background.ts?:7:100)
    at Module../src/background.ts (/home/marco/webMatters/electronMatters/GGC-Electron/dist_electron/index.js:1960:1)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/GGC-Electron/dist_electron/index.js:20:30)
    at eval (webpack:///multi_./src/background.ts?:1:18)
    at Object.0 (/home/marco/webMatters/electronMatters/GGC-Electron/dist_electron/index.js:2007:1)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/GGC-Electron/dist_electron/index.js:20:30)
    at /home/marco/webMatters/electronMatters/GGC-Electron/dist_electron/index.js:84:18

actually window, aka win, is already defined in src/background.ts :

import { app, protocol, BrowserWindow, ipcMain, shell, Menu } from 'electron'

async function createWindow() {
  win = new BrowserWindow({

But window has to be defined in src/services/electron-services/database/index.ts as well in order to be able to do
const { remote } = window.require('electron')

@AimForNaN
Copy link

AimForNaN commented Sep 16, 2020

The moment you redefine window is when you break its original value. I'm not sure what your programming background is, but there is a bigger underlying issue here. It is best if you take this time to come to a deeper understanding of JavaScript and its environments before continuing any further on your project.

Here may be a good place to start: https://developer.mozilla.org/en-US/docs/Web/JavaScript

@raphael10-collab
Copy link
Author

@truefusion thank for your kind suggestion.
I would be grateful if you would have a look at the file where you suggest to modify how to import fs-extra : https://github.com/raphael10-collab/ElectronVueTypeScriptScaffolding/blob/master/src/services/electron-services/database/index.ts and tell me how to use window, which cannot be redefined, otherwise its original value will be broken, there

@raphael10-collab
Copy link
Author

@truefusion thank you for your pull request
Doing :

const { app, remote } = window.require('electron')
import Lowdb from 'lowdb'
import FileSync from 'lowdb/adapters/FileSync'
import path from 'path'
const fs = remote.require('fs-extra')

I get : "ReferenceError: window is not defined".
So I have to understand how to define window in src/services/electron-services/database/index.ts

@AimForNaN
Copy link

How are you compiling your code? And how are you running your app?

@raphael10-collab
Copy link
Author

This is the complete output:

(base) marco@pc01:~/webMatters/electronMatters/ElectronVueTypeScriptScaffolding$ yarn electron:serve
yarn run v1.22.5
warning ../package.json: No license field
$ vue-cli-service electron:serve
 INFO  Starting development server...
Starting type checking service...
Using 1 worker with 2048MB memory limit
98% after emitting CopyPlugin

 DONE  Compiled successfully in 1725ms                                                                                                                                         
10:26:28 PM

Type checking in progress...

  App running at:
  - Local:   http://localhost:8080 
  - Network: http://192.168.1.7:8080

  Note that the development build is not optimized.
  To create a production build, run yarn build.

⠏  Bundling main process...

 DONE  Compiled successfully in 855ms                                                                                                                                       
10:26:29 PM

  File                      Size                                                                       Gzipped

  dist_electron/index.js    1366.33 KiB                                                                274.09 KiB

 Images and other types of assets omitted.



  DONE  Compiled successfully in 11ms       
 10:26:29 PM


  File                        Size                                                                      Gzipped

  dist_electron/preload.js    76.96 KiB                                                                 5.19 KiB

  Images and other types of assets omitted.

 INFO  Launching Electron...
App threw an error during load
ReferenceError: window is not defined
    at eval (webpack:///./src/services/electron-services/database/index.ts?:8:25)
    at Module../src/services/electron-services/database/index.ts (/home/marco/webMatters/electronMatters
/ElectronVueTypeScriptScaffolding/dist_electron/index.js:1894:1)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/ElectronVueTypeScriptScaffolding/dist_electron
/index.js:20:30)
    at eval (webpack:///./src/background.ts?:7:100)
    at Module../src/background.ts (/home/marco/webMatters/electronMatters/ElectronVueTypeScriptScaffolding/dist_electron
/index.js:1870:1)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/ElectronVueTypeScriptScaffolding/dist_electron
/index.js:20:30)
    at eval (webpack:///multi_./src/background.ts?:1:18)
    at Object.0 (/home/marco/webMatters/electronMatters/ElectronVueTypeScriptScaffolding/dist_electron/index.js:1917:1)
at __webpack_require__ (/home/marco/webMatters/electronMatters/ElectronVueTypeScriptScaffolding/dist_electron
/index.js:20:30)
    at /home/marco/webMatters/electronMatters/ElectronVueTypeScriptScaffolding/dist_electron/index.js:84:18
A JavaScript error occurred in the main process
Uncaught Exception:
ReferenceError: window is not defined
    at eval (webpack:///./src/services/electron-services/database/index.ts?:8:25)
    at Module../src/services/electron-services/database/index.ts (/home/marco/webMatters/electronMatters
/ElectronVueTypeScriptScaffolding/dist_electron/index.js:1894:1)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/ElectronVueTypeScriptScaffolding/dist_electron
/index.js:20:30)
    at eval (webpack:///./src/background.ts?:7:100)
    at Module../src/background.ts (/home/marco/webMatters/electronMatters/ElectronVueTypeScriptScaffolding/dist_electron
/index.js:1870:1)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/ElectronVueTypeScriptScaffolding/dist_electron
/index.js:20:30)
    at eval (webpack:///multi_./src/background.ts?:1:18)
    at Object.0 (/home/marco/webMatters/electronMatters/ElectronVueTypeScriptScaffolding/dist_electron/index.js:1917:1)
    at __webpack_require__ (/home/marco/webMatters/electronMatters/ElectronVueTypeScriptScaffolding/dist_electron
/index.js:20:30)
    at /home/marco/webMatters/electronMatters/ElectronVueTypeScriptScaffolding/dist_electron/index.js:84:18
No type errors found
Version: typescript 3.9.7
Time: 3989ms

@AimForNaN
Copy link

Your dist_electron/preload.js script is not designed to properly launch electron.

@raphael10-collab
Copy link
Author

raphael10-collab commented Sep 17, 2020

@truefusion

This is the preload.js I'm using, based on the suggestions here: electron/electron#9920 (comment)

const {
    contextBridge,
    ipcRenderer
} = require("electron");

// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
    "api", {
        send: (channel, data) => {
            // whitelist channels
            let validChannels = ["toMain"];
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel, data);
            }
        },
        receive: (channel, func) => {
            let validChannels = ["fromMain"];
            if (validChannels.includes(channel)) {
                // Deliberately strip event as it includes `sender` 
                ipcRenderer.on(channel, (event, ...args) => func(...args));
            }
        }
    }
);

How should I modify preload.js in order to properly launch electron?

I tried also with nodeIntegration:true in src/background.ts, thus commenting the preload.js path :

  webPreferences: {
    nodeIntegration: true,
    //nodeIntegration: false,
    //contextIsolation: true, // protects against prototype pollution
    //preload: path.join(__dirname, "../dist_electron/preload.js"),
  },

but still get error: "ReferenceError: window is not defined"

@AimForNaN
Copy link

This is as far as I will help you on the matter. https://www.electronjs.org/docs/tutorial/quick-start

For anything else, you'll have to become more acquainted with web technologies.

@raphael10-collab
Copy link
Author

raphael10-collab commented Sep 17, 2020 via email

@nmschorr
Copy link

nmschorr commented Sep 29, 2020

I have the same problem:

Uncaught TypeError: can't access property "match", e.version is undefined
c polyfills.js:30
v graceful-fs.js:104
0da7 graceful-fs.js:96
0da7 chunk-vendors.331b15a4.js:1
Webpack 14
polyfills.js:30:16
c polyfills.js:30
v graceful-fs.js:104
0da7 graceful-fs.js:96
0da7 chunk-vendors.331b15a4.js:1
Webpack 14

I've tried everything under the sun, and don't think it's my npm installation.

Let me know if you would like more info. Meanwhile I'm going to try commenting out:

if (constants.hasOwnProperty('O_SYMLINK') &&
process.version.match(/^v0.6.[0-2]|^v0.5./)) {
patchLchmod(fs)
}

which seems to be the problem area so far.

Edit: Ok, I tried editing out the above, and it worked for that problem, but then something similar, same file - shows up. Which makes me think it's not this file at all, but something else.

I had just added this package to read ssl cert/key with. Before that the project was fine running under http.

@schoudhary21
Copy link

i faced the same issue and fixed it by downgrading to graceful-fs "4.2.4" version; force it using 'npm install graceful-fs@4.2.4'
the recent versions breaking for me

@Clockwerk300
Copy link

Clockwerk300 commented Feb 17, 2021

Edit:

Ok I my miss take if you remove the line "implementation: require('sass'),". Then sass-dart will be loaded and it will work.

If sass is used, it failed already in require('sass') because someone require('fs') is used which return an empty object.

This happend only in the browser.

@1c7
Copy link

1c7 commented Feb 21, 2021

webpack config, try this, may works

I am using webpack & electron.js

plugins: [
  // https://webpack.js.org/plugins/environment-plugin/
  new webpack.DefinePlugin({
    'process.version': process.version,
  }), 
],

Above solution cause some other problem

(A lot of Uncaught SyntaxError: Unexpected number)

but this one works:

module.exports = {
  configureWebpack: {
    target: 'electron-renderer'

@eumenhofer
Copy link

eumenhofer commented Apr 26, 2021

Running into this as well with react on the latest version. Workarounds aren't really an option for my project.
Using react and it's failing here.

module.exports = patch(clone(fs)) <---------
if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs.__patched) {
    module.exports = patch(fs)
    fs.__patched = true;
}

for me the TEST_GRACEFUL_FS_GLOBAL_PATCH and __patched are undefined throwing the error.

@QIANJI777
Copy link

This problem is most likely caused by Webpack5. Webpack5 no longer automatically populates the nodejs core module.
https://webpack.js.org/configuration/resolve/#resolvefallback
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants