@warren-bank/electron-portable-paths

Cross-platform helper functions to perform Electron boilerplate to configure 'special' directory paths relative to the executable

Usage no npm install needed!

<script type="module">
  import warrenBankElectronPortablePaths from 'https://cdn.skypack.dev/@warren-bank/electron-portable-paths';
</script>

README

electron-portable-paths

Cross-platform helper functions to perform Electron boilerplate to configure "special" directory paths relative to the executable

Resulting Directory Structure:

> tree . /F /A
C:\PortableApps\${productName}Portable
|   ${productName}.exe
|
\---${productName}
    +---data
    |   |   Cookies
    |   |   Cookies-journal
    |   |
    |   +---blob_storage
    |   |   \---aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
    |   +---Cache
    |   |       data_0
    |   |       data_1
    |   |       data_2
    |   |       data_3
    |   |       f_000001
    |   |       index
    |   |
    |   +---GPUCache
    |   |       data_0
    |   |       data_1
    |   |       data_2
    |   |       data_3
    |   |       index
    |   |
    |   +---temp
    |   \---webrtc_event_logs
    +---home
    |   +---desktop
    |   +---documents
    |   +---downloads
    |   +---music
    |   +---pictures
    |   \---videos
    \---logs

Installation:

npm install --save "@warren-bank/electron-portable-paths"

API:

  • success = makePortable(app)

    • input parameters:
      • required:
    • output value:
      • boolean
        • indicates whether a non-portable build has been configured in such a way that its paths can now be remapped by setPortablePaths
    • notes:
      • works across all platforms
      • has no effect when the Electron executable is a Windows portable target
  • success = setPortablePaths(app, make_dirs, rootPath, blacklist, allow_remapping_into_blacklisted_parent_directory)

    • input parameters:
      • required:
      • optional:
        • make_dirs: boolean
          • allow the creation of all remapped "special" directories that do not already exist
            • Electron will often choose to ignore a directory path when it cannot be found
          • default value: true
        • rootPath: string
          • path to custom root directory
          • default value: ./${app.getName()}
        • blacklist: Array of string
        • allow_remapping_into_blacklisted_parent_directory: boolean
    • output value:
      • boolean
        • indicates whether paths have been successfully remapped
    • notes:
      • only has effect when any of the following conditions are true:
        • the Electron executable is a Windows portable target
        • makePortable was previously called

Usage Example (basic):

  • file: ./src/main.js

      const {app} = require('electron')
      const {makePortable, setPortablePaths} = require('@warren-bank/electron-portable-paths')
    
      makePortable(app)
      setPortablePaths(app)
    

Usage Example (advanced):

  • file: ./src/main.js

      const {app} = require('electron')
      const {makePortable, setPortablePaths} = require('@warren-bank/electron-portable-paths')
    
      const parseArgv = require('yargs').parse
      const argv = parseArgv(process.argv.slice(1))
    
      if (argv['portable'])
        makePortable(app)
    
      if (!setPortablePaths(app, true, argv['data-dir'], ["documents","downloads"]) && argv['data-dir'])
        app.setPath('userData', path.resolve(argv['data-dir']))
    

Build Targets (tested and working):

  • linux
    • tar.gz
    • appimage
    • deb
    • rpm
  • win
    • zip
    • portable
    • squirrel
  • mac
    • zip
    • dmg

notes:

  • linux
    • deb
      • installation:
          app_name='myapp-desktop'
          app_productName='MyApp'
        
          sudo apt-get install ./${app_name}.deb
        
      • observations:
          which ${app_name}
          # /usr/local/bin/${app_name}
        
          ls -la `which ${app_name}`
          # /usr/local/bin/${app_name} -> /opt/${app_productName}/${app_name}
        
          ${app_name} --portable
        
          ls -d /opt/${app_productName}/${app_productName}
          # No such file or directory
        
          sudo ${app_name} --portable
        
          ls -d /opt/${app_productName}/${app_productName}
          # /opt/${app_productName}/${app_productName}
        
      • take-aways:
        • when the .deb package is installed by root
          • when the app is run by a regular user
            • need to make sure that rootPath:
              • exists, or can be created
              • is writable
      • workaround:
        • electron-builder.json:
            {
              "linux": {
                "target": ["deb"]
              },
              "deb": {
                "afterInstall": "build_resources/scripts/linux-package.after-install.sh",
                "afterRemove":  "build_resources/scripts/linux-package.after-remove.sh"
              }
            }
          
        • build_resources/scripts/linux-package.after-install.sh
            #!/bin/bash
          
            # Link to the binary
            ln -sf '/opt/${productFilename}/${executable}' '/usr/local/bin/${executable}'
          
            # Create default --portable directory
            mkdir --mode=777 '/opt/${productFilename}/${productFilename}'
          
        • build_resources/scripts/linux-package.after-remove.sh
            #!/bin/bash
          
            # Delete the link to the binary
            rm -f '/usr/local/bin/${executable}'
          
            # Delete default --portable directory
            rm -rf '/opt/${productFilename}/${productFilename}'
          
            # Cleanup
            rm -rf '/opt/${productFilename}'
          
      • scope of workaround:

Legal: