Browse Source

initial commit

master
jeffvli 3 years ago
commit
4c1a86eed7
  1. 12
      .editorconfig
  2. 7
      .erb/configs/.eslintrc
  3. 46
      .erb/configs/webpack.config.base.js
  4. 4
      .erb/configs/webpack.config.eslint.js
  5. 75
      .erb/configs/webpack.config.main.prod.babel.js
  6. 335
      .erb/configs/webpack.config.renderer.dev.babel.js
  7. 72
      .erb/configs/webpack.config.renderer.dev.dll.babel.js
  8. 165
      .erb/configs/webpack.config.renderer.prod.babel.js
  9. BIN
      .erb/img/erb-banner.png
  10. BIN
      .erb/img/erb-logo.png
  11. BIN
      .erb/img/eslint-padded-90.png
  12. BIN
      .erb/img/eslint-padded.png
  13. BIN
      .erb/img/eslint.png
  14. BIN
      .erb/img/jest-padded-90.png
  15. BIN
      .erb/img/jest-padded.png
  16. BIN
      .erb/img/jest.png
  17. BIN
      .erb/img/js-padded.png
  18. BIN
      .erb/img/js.png
  19. BIN
      .erb/img/npm.png
  20. BIN
      .erb/img/react-padded-90.png
  21. BIN
      .erb/img/react-padded.png
  22. BIN
      .erb/img/react-router-padded-90.png
  23. BIN
      .erb/img/react-router-padded.png
  24. BIN
      .erb/img/react-router.png
  25. BIN
      .erb/img/react.png
  26. BIN
      .erb/img/webpack-padded-90.png
  27. BIN
      .erb/img/webpack-padded.png
  28. BIN
      .erb/img/webpack.png
  29. BIN
      .erb/img/yarn-padded-90.png
  30. BIN
      .erb/img/yarn-padded.png
  31. BIN
      .erb/img/yarn.png
  32. 1
      .erb/mocks/fileMock.js
  33. 8
      .erb/scripts/.eslintrc
  34. 6
      .erb/scripts/BabelRegister.js
  35. 25
      .erb/scripts/CheckBuildsExist.js
  36. 52
      .erb/scripts/CheckNativeDep.js
  37. 16
      .erb/scripts/CheckNodeEnv.js
  38. 16
      .erb/scripts/CheckPortInUse.js
  39. 7
      .erb/scripts/DeleteSourceMaps.js
  40. 22
      .erb/scripts/ElectronRebuild.js
  41. 28
      .erb/scripts/Notarize.js
  42. 56
      .eslintignore
  43. 32
      .eslintrc.js
  44. 12
      .gitattributes
  45. 5
      .github/FUNDING.yml
  46. 67
      .github/ISSUE_TEMPLATE/1-Bug_report.md
  47. 19
      .github/ISSUE_TEMPLATE/2-Question.md
  48. 15
      .github/ISSUE_TEMPLATE/3-Feature_request.md
  49. 6
      .github/config.yml
  50. 17
      .github/stale.yml
  51. 55
      .github/workflows/publish.yml
  52. 33
      .github/workflows/test.yml
  53. 50
      .gitignore
  54. 6
      .prettierrc
  55. 7
      .vscode/extensions.json
  56. 28
      .vscode/launch.json
  57. 28
      .vscode/settings.json
  58. 25
      .vscode/tasks.json
  59. 533
      CHANGELOG.md
  60. 76
      CODE_OF_CONDUCT.md
  61. 21
      LICENSE
  62. 157
      README.md
  63. 14
      assets/assets.d.ts
  64. 10
      assets/entitlements.mac.plist
  65. BIN
      assets/icon.icns
  66. BIN
      assets/icon.ico
  67. BIN
      assets/icon.png
  68. 23
      assets/icon.svg
  69. BIN
      assets/icons/1024x1024.png
  70. BIN
      assets/icons/128x128.png
  71. BIN
      assets/icons/16x16.png
  72. BIN
      assets/icons/24x24.png
  73. BIN
      assets/icons/256x256.png
  74. BIN
      assets/icons/32x32.png
  75. BIN
      assets/icons/48x48.png
  76. BIN
      assets/icons/512x512.png
  77. BIN
      assets/icons/64x64.png
  78. BIN
      assets/icons/96x96.png
  79. 62
      babel.config.js
  80. 320
      package.json
  81. 36
      src/App.tsx
  82. 10
      src/__tests__/App.test.tsx
  83. 98
      src/api/api.ts
  84. 12
      src/api/auth.ts
  85. 96
      src/auth/service.ts
  86. 66
      src/components/Playlists.tsx
  87. 15
      src/components/layout/GenericPage.tsx
  88. 77
      src/components/layout/Layout.tsx
  89. 42
      src/components/layout/NavToggle.tsx
  90. 159
      src/components/layout/Sidebar.tsx
  91. 13
      src/components/loader/Loader.tsx
  92. 7
      src/components/player/NowPlayingList.tsx
  93. 36
      src/components/player/Player.tsx
  94. 7
      src/components/playlist/Playlist.tsx
  95. 86
      src/components/playlist/PlaylistList.tsx
  96. 103
      src/components/playlist/PlaylistView.tsx
  97. 19
      src/components/playlist/PlaylistViewHeader.tsx
  98. 140
      src/components/settings/Settings.tsx
  99. 7
      src/components/views/GridView.tsx
  100. 34
      src/components/views/ListView.tsx

12
.editorconfig

@ -0,0 +1,12 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

7
.erb/configs/.eslintrc

@ -0,0 +1,7 @@
{
"rules": {
"no-console": "off",
"global-require": "off",
"import/no-dynamic-require": "off"
}
}

46
.erb/configs/webpack.config.base.js

@ -0,0 +1,46 @@
/**
* Base webpack config used across other specific configs
*/
import path from 'path';
import webpack from 'webpack';
import { dependencies as externals } from '../../src/package.json';
export default {
externals: [...Object.keys(externals || {})],
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
},
},
},
],
},
output: {
path: path.join(__dirname, '../../src'),
// https://github.com/webpack/webpack/issues/1114
libraryTarget: 'commonjs2',
},
/**
* Determine the array of extensions that should be used to resolve modules.
*/
resolve: {
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
modules: [path.join(__dirname, '../../src'), 'node_modules'],
},
plugins: [
new webpack.EnvironmentPlugin({
NODE_ENV: 'production',
}),
],
};

4
.erb/configs/webpack.config.eslint.js

@ -0,0 +1,4 @@
/* eslint import/no-unresolved: off, import/no-self-import: off */
require('@babel/register');
module.exports = require('./webpack.config.renderer.dev.babel').default;

75
.erb/configs/webpack.config.main.prod.babel.js

@ -0,0 +1,75 @@
/**
* Webpack config for production electron main process
*/
import path from 'path';
import webpack from 'webpack';
import { merge } from 'webpack-merge';
import TerserPlugin from 'terser-webpack-plugin';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import baseConfig from './webpack.config.base';
import CheckNodeEnv from '../scripts/CheckNodeEnv';
import DeleteSourceMaps from '../scripts/DeleteSourceMaps';
CheckNodeEnv('production');
DeleteSourceMaps();
const devtoolsConfig = process.env.DEBUG_PROD === 'true' ? {
devtool: 'source-map'
} : {};
export default merge(baseConfig, {
...devtoolsConfig,
mode: 'production',
target: 'electron-main',
entry: './src/main.dev.ts',
output: {
path: path.join(__dirname, '../../'),
filename: './src/main.prod.js',
},
optimization: {
minimizer: [
new TerserPlugin({
parallel: true,
}),
]
},
plugins: [
new BundleAnalyzerPlugin({
analyzerMode:
process.env.OPEN_ANALYZER === 'true' ? 'server' : 'disabled',
openAnalyzer: process.env.OPEN_ANALYZER === 'true',
}),
/**
* Create global constants which can be configured at compile time.
*
* Useful for allowing different behaviour between development builds and
* release builds
*
* NODE_ENV should be production so that modules do not perform certain
* development checks
*/
new webpack.EnvironmentPlugin({
NODE_ENV: 'production',
DEBUG_PROD: false,
START_MINIMIZED: false,
}),
],
/**
* Disables webpack processing of __dirname and __filename.
* If you run the bundle in node.js it falls back to these values of node.js.
* https://github.com/webpack/webpack/issues/2010
*/
node: {
__dirname: false,
__filename: false,
},
});

335
.erb/configs/webpack.config.renderer.dev.babel.js

@ -0,0 +1,335 @@
import path from 'path';
import fs from 'fs';
import webpack from 'webpack';
import chalk from 'chalk';
import { merge } from 'webpack-merge';
import { spawn, execSync } from 'child_process';
import baseConfig from './webpack.config.base';
import CheckNodeEnv from '../scripts/CheckNodeEnv';
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
// When an ESLint server is running, we can't set the NODE_ENV so we'll check if it's
// at the dev webpack config is not accidentally run in a production environment
if (process.env.NODE_ENV === 'production') {
CheckNodeEnv('development');
}
const port = process.env.PORT || 4343;
const publicPath = `http://localhost:${port}/dist`;
const dllDir = path.join(__dirname, '../dll');
const manifest = path.resolve(dllDir, 'renderer.json');
const requiredByDLLConfig = module.parent.filename.includes(
'webpack.config.renderer.dev.dll'
);
/**
* Warn if the DLL is not built
*/
if (
!requiredByDLLConfig &&
!(fs.existsSync(dllDir) && fs.existsSync(manifest))
) {
console.log(
chalk.black.bgYellow.bold(
'The DLL files are missing. Sit back while we build them for you with "yarn build-dll"'
)
);
execSync('yarn postinstall');
}
export default merge(baseConfig, {
devtool: 'inline-source-map',
mode: 'development',
target: 'electron-renderer',
entry: [
'core-js',
'regenerator-runtime/runtime',
require.resolve('../../src/index.tsx'),
],
output: {
publicPath: `http://localhost:${port}/dist/`,
filename: 'renderer.dev.js',
},
module: {
rules: [
{
test: /\.[jt]sx?$/,
exclude: /node_modules/,
use: [
{
loader: require.resolve('babel-loader'),
options: {
plugins: [require.resolve('react-refresh/babel')].filter(Boolean),
},
},
],
},
{
test: /\.global\.css$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'less-loader',
options: {
lessOptions: {
javascriptEnabled: true,
},
},
},
],
},
{
test: /^((?!\.global).)*\.css$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[name]__[local]__[hash:base64:5]',
},
sourceMap: true,
importLoaders: 1,
},
},
{
loader: 'less-loader',
options: {
lessOptions: {
javascriptEnabled: true,
},
},
},
],
},
// SASS support - compile all .global.scss files and pipe it to style.css
{
test: /\.global\.(scss|sass)$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'sass-loader',
},
{
loader: 'less-loader',
options: {
lessOptions: {
javascriptEnabled: true,
},
},
},
],
},
// SASS support - compile all other .scss files and pipe it to style.css
{
test: /^((?!\.global).)*\.(scss|sass)$/,
use: [
{
loader: 'style-loader',
},
{
loader: '@teamsupercell/typings-for-css-modules-loader',
},
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[name]__[local]__[hash:base64:5]',
},
sourceMap: true,
importLoaders: 1,
},
},
{
loader: 'sass-loader',
},
{
loader: 'less-loader',
options: {
lessOptions: {
javascriptEnabled: true,
},
},
},
],
},
{
test: /\.less$/i,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'less-loader',
options: {
lessOptions: {
javascriptEnabled: true,
},
},
},
],
},
// WOFF Font
{
test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-woff',
},
},
},
// WOFF2 Font
{
test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-woff',
},
},
},
// OTF Font
{
test: /\.otf(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'font/otf',
},
},
},
// TTF Font
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/octet-stream',
},
},
},
// EOT Font
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
use: 'file-loader',
},
// SVG Font
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'image/svg+xml',
},
},
},
// Common Image Formats
{
test: /\.(?:ico|gif|png|jpg|jpeg|webp)$/,
use: 'url-loader',
},
],
},
plugins: [
requiredByDLLConfig
? null
: new webpack.DllReferencePlugin({
context: path.join(__dirname, '../dll'),
manifest: require(manifest),
sourceType: 'var',
}),
new webpack.NoEmitOnErrorsPlugin(),
/**
* Create global constants which can be configured at compile time.
*
* Useful for allowing different behaviour between development builds and
* release builds
*
* NODE_ENV should be production so that modules do not perform certain
* development checks
*
* By default, use 'development' as NODE_ENV. This can be overriden with
* 'staging', for example, by changing the ENV variables in the npm scripts
*/
new webpack.EnvironmentPlugin({
NODE_ENV: 'development',
}),
new webpack.LoaderOptionsPlugin({
debug: true,
}),
new ReactRefreshWebpackPlugin(),
],
node: {
__dirname: false,
__filename: false,
},
devServer: {
port,
publicPath,
compress: true,
noInfo: false,
stats: 'errors-only',
inline: true,
lazy: false,
hot: true,
headers: { 'Access-Control-Allow-Origin': '*' },
contentBase: path.join(__dirname, 'dist'),
watchOptions: {
aggregateTimeout: 300,
ignored: /node_modules/,
poll: 100,
},
historyApiFallback: {
verbose: true,
disableDotRule: false,
},
before() {
console.log('Starting Main Process...');
spawn('npm', ['run', 'start:main'], {
shell: true,
env: process.env,
stdio: 'inherit',
})
.on('close', (code) => process.exit(code))
.on('error', (spawnError) => console.error(spawnError));
},
},
});

72
.erb/configs/webpack.config.renderer.dev.dll.babel.js

@ -0,0 +1,72 @@
/**
* Builds the DLL for development electron renderer process
*/
import webpack from 'webpack';
import path from 'path';
import { merge } from 'webpack-merge';
import baseConfig from './webpack.config.base';
import { dependencies } from '../../package.json';
import CheckNodeEnv from '../scripts/CheckNodeEnv';
CheckNodeEnv('development');
const dist = path.join(__dirname, '../dll');
export default merge(baseConfig, {
context: path.join(__dirname, '../..'),
devtool: 'eval',
mode: 'development',
target: 'electron-renderer',
externals: ['fsevents', 'crypto-browserify'],
/**
* Use `module` from `webpack.config.renderer.dev.js`
*/
module: require('./webpack.config.renderer.dev.babel').default.module,
entry: {
renderer: Object.keys(dependencies || {}),
},
output: {
library: 'renderer',
path: dist,
filename: '[name].dev.dll.js',
libraryTarget: 'var',
},
plugins: [
new webpack.DllPlugin({
path: path.join(dist, '[name].json'),
name: '[name]',
}),
/**
* Create global constants which can be configured at compile time.
*
* Useful for allowing different behaviour between development builds and
* release builds
*
* NODE_ENV should be production so that modules do not perform certain
* development checks
*/
new webpack.EnvironmentPlugin({
NODE_ENV: 'development',
}),
new webpack.LoaderOptionsPlugin({
debug: true,
options: {
context: path.join(__dirname, '../../src'),
output: {
path: path.join(__dirname, '../dll'),
},
},
}),
],
});

165
.erb/configs/webpack.config.renderer.prod.babel.js

@ -0,0 +1,165 @@
/**
* Build config for electron renderer process
*/
import path from 'path';
import webpack from 'webpack';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
import { merge } from 'webpack-merge';
import TerserPlugin from 'terser-webpack-plugin';
import baseConfig from './webpack.config.base';
import CheckNodeEnv from '../scripts/CheckNodeEnv';
import DeleteSourceMaps from '../scripts/DeleteSourceMaps';
CheckNodeEnv('production');
DeleteSourceMaps();
const devtoolsConfig =
process.env.DEBUG_PROD === 'true'
? {
devtool: 'source-map',
}
: {};
export default merge(baseConfig, {
...devtoolsConfig,
mode: 'production',
target: 'electron-renderer',
entry: [
'core-js',
'regenerator-runtime/runtime',
path.join(__dirname, '../../src/index.tsx'),
],
output: {
path: path.join(__dirname, '../../src/dist'),
publicPath: './dist/',
filename: 'renderer.prod.js',
},
module: {
rules: [
{
test: /.s?l?c?e?ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
// `./dist` can't be inerhited for publicPath for styles. Otherwise generated paths will be ./dist/dist
publicPath: './',
},
},
'css-loader',
'less-loader',
'sass-loader',
],
},
// WOFF Font
{
test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-woff',
},
},
},
// WOFF2 Font
{
test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-woff',
},
},
},
// OTF Font
{
test: /\.otf(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'font/otf',
},
},
},
// TTF Font
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/octet-stream',
},
},
},
// EOT Font
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
use: 'file-loader',
},
// SVG Font
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'image/svg+xml',
},
},
},
// Common Image Formats
{
test: /\.(?:ico|gif|png|jpg|jpeg|webp)$/,
use: 'url-loader',
},
],
},
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
}),
new CssMinimizerPlugin(),
],
},
plugins: [
/**
* Create global constants which can be configured at compile time.
*
* Useful for allowing different behaviour between development builds and
* release builds
*
* NODE_ENV should be production so that modules do not perform certain
* development checks
*/
new webpack.EnvironmentPlugin({
NODE_ENV: 'production',
DEBUG_PROD: false,
}),
new MiniCssExtractPlugin({
filename: 'style.css',
}),
new BundleAnalyzerPlugin({
analyzerMode:
process.env.OPEN_ANALYZER === 'true' ? 'server' : 'disabled',
openAnalyzer: process.env.OPEN_ANALYZER === 'true',
}),
],
});

BIN
.erb/img/erb-banner.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

BIN
.erb/img/erb-logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
.erb/img/eslint-padded-90.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
.erb/img/eslint-padded.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
.erb/img/eslint.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

BIN
.erb/img/jest-padded-90.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
.erb/img/jest-padded.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
.erb/img/jest.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
.erb/img/js-padded.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
.erb/img/js.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
.erb/img/npm.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
.erb/img/react-padded-90.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
.erb/img/react-padded.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
.erb/img/react-router-padded-90.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
.erb/img/react-router-padded.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
.erb/img/react-router.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
.erb/img/react.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
.erb/img/webpack-padded-90.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
.erb/img/webpack-padded.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
.erb/img/webpack.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
.erb/img/yarn-padded-90.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
.erb/img/yarn-padded.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
.erb/img/yarn.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

1
.erb/mocks/fileMock.js

@ -0,0 +1 @@
export default 'test-file-stub';

8
.erb/scripts/.eslintrc

@ -0,0 +1,8 @@
{
"rules": {
"no-console": "off",
"global-require": "off",
"import/no-dynamic-require": "off",
"import/no-extraneous-dependencies": "off"
}
}

6
.erb/scripts/BabelRegister.js

@ -0,0 +1,6 @@
const path = require('path');
require('@babel/register')({
extensions: ['.es6', '.es', '.jsx', '.js', '.mjs', '.ts', '.tsx'],
cwd: path.join(__dirname, '../..'),
});

25
.erb/scripts/CheckBuildsExist.js

@ -0,0 +1,25 @@
// Check if the renderer and main bundles are built
import path from 'path';
import chalk from 'chalk';
import fs from 'fs';
const mainPath = path.join(__dirname, '../../src/main.prod.js');
const rendererPath = path.join(
__dirname, '../../src/dist/renderer.prod.js'
);
if (!fs.existsSync(mainPath)) {
throw new Error(
chalk.whiteBright.bgRed.bold(
'The main process is not built yet. Build it by running "yarn build:main"'
)
);
}
if (!fs.existsSync(rendererPath)) {
throw new Error(
chalk.whiteBright.bgRed.bold(
'The renderer process is not built yet. Build it by running "yarn build:renderer"'
)
);
}

52
.erb/scripts/CheckNativeDep.js

@ -0,0 +1,52 @@
import fs from 'fs';
import chalk from 'chalk';
import { execSync } from 'child_process';
import { dependencies } from '../../package.json';
if (dependencies) {
const dependenciesKeys = Object.keys(dependencies);
const nativeDeps = fs
.readdirSync('node_modules')
.filter((folder) => fs.existsSync(`node_modules/${folder}/binding.gyp`));
if (nativeDeps.length === 0) {
process.exit(0);
}
try {
// Find the reason for why the dependency is installed. If it is installed
// because of a devDependency then that is okay. Warn when it is installed
// because of a dependency
const { dependencies: dependenciesObject } = JSON.parse(
execSync(`npm ls ${nativeDeps.join(' ')} --json`).toString()
);
const rootDependencies = Object.keys(dependenciesObject);
const filteredRootDependencies = rootDependencies.filter((rootDependency) =>
dependenciesKeys.includes(rootDependency)
);
if (filteredRootDependencies.length > 0) {
const plural = filteredRootDependencies.length > 1;
console.log(`
${chalk.whiteBright.bgYellow.bold(
'Webpack does not work with native dependencies.'
)}
${chalk.bold(filteredRootDependencies.join(', '))} ${
plural ? 'are native dependencies' : 'is a native dependency'
} and should be installed inside of the "./src" folder.
First, uninstall the packages from "./package.json":
${chalk.whiteBright.bgGreen.bold('yarn remove your-package')}
${chalk.bold(
'Then, instead of installing the package to the root "./package.json":'
)}
${chalk.whiteBright.bgRed.bold('yarn add your-package')}
${chalk.bold('Install the package to "./src/package.json"')}
${chalk.whiteBright.bgGreen.bold('cd ./src && yarn add your-package')}
Read more about native dependencies at:
${chalk.bold(
'https://electron-react-boilerplate.js.org/docs/adding-dependencies/#module-structure'
)}
`);
process.exit(1);
}
} catch (e) {
console.log('Native dependencies could not be checked');
}
}

16
.erb/scripts/CheckNodeEnv.js

@ -0,0 +1,16 @@
import chalk from 'chalk';
export default function CheckNodeEnv(expectedEnv) {
if (!expectedEnv) {
throw new Error('"expectedEnv" not set');
}
if (process.env.NODE_ENV !== expectedEnv) {
console.log(
chalk.whiteBright.bgRed.bold(
`"process.env.NODE_ENV" must be "${expectedEnv}" to use this webpack config`
)
);
process.exit(2);
}
}

16
.erb/scripts/CheckPortInUse.js

@ -0,0 +1,16 @@
import chalk from 'chalk';
import detectPort from 'detect-port';
const port = process.env.PORT || '4343';
detectPort(port, (err, availablePort) => {
if (port !== String(availablePort)) {
throw new Error(
chalk.whiteBright.bgRed.bold(
`Port "${port}" on "localhost" is already in use. Please use another port. ex: PORT=4343 yarn start`
)
);
} else {
process.exit(0);
}
});

7
.erb/scripts/DeleteSourceMaps.js

@ -0,0 +1,7 @@
import path from 'path';
import rimraf from 'rimraf';
export default function deleteSourceMaps() {
rimraf.sync(path.join(__dirname, '../../src/dist/*.js.map'));
rimraf.sync(path.join(__dirname, '../../src/*.js.map'));
}

22
.erb/scripts/ElectronRebuild.js

@ -0,0 +1,22 @@
import path from 'path';
import { execSync } from 'child_process';
import fs from 'fs';
import { dependencies } from '../../src/package.json';
const nodeModulesPath = path.join(__dirname, '../../src/node_modules');
if (
Object.keys(dependencies || {}).length > 0 &&
fs.existsSync(nodeModulesPath)
) {
const electronRebuildCmd =
'../node_modules/.bin/electron-rebuild --parallel --force --types prod,dev,optional --module-dir .';
const cmd =
process.platform === 'win32'
? electronRebuildCmd.replace(/\//g, '\\')
: electronRebuildCmd;
execSync(cmd, {
cwd: path.join(__dirname, '../../src'),
stdio: 'inherit',
});
}

28
.erb/scripts/Notarize.js

@ -0,0 +1,28 @@
const { notarize } = require('electron-notarize');
const { build } = require('../../package.json');
exports.default = async function notarizeMacos(context) {
const { electronPlatformName, appOutDir } = context;
if (electronPlatformName !== 'darwin') {
return;
}
if (!process.env.CI) {
console.warn('Skipping notarizing step. Packaging is not running in CI');
return;
}
if (!('APPLE_ID' in process.env && 'APPLE_ID_PASS' in process.env)) {
console.warn('Skipping notarizing step. APPLE_ID and APPLE_ID_PASS env variables must be set');
return;
}
const appName = context.packager.appInfo.productFilename;
await notarize({
appBundleId: build.appId,
appPath: `${appOutDir}/${appName}.app`,
appleId: process.env.APPLE_ID,
appleIdPassword: process.env.APPLE_ID_PASS,
});
};

56
.eslintignore

@ -0,0 +1,56 @@
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
.eslintcache
# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules
# OSX
.DS_Store
# App packaged
release
src/*.main.prod.js
src/main.prod.js
src/main.prod.js.map
src/renderer.prod.js
src/renderer.prod.js.map
src/style.css
src/style.css.map
dist
dll
main.js
main.js.map
.idea
npm-debug.log.*
__snapshots__
# Package.json
package.json
.travis.yml
*.css.d.ts
*.sass.d.ts
*.scss.d.ts

32
.eslintrc.js

@ -0,0 +1,32 @@
module.exports = {
extends: 'erb',
rules: {
// A temporary hack related to IDE not resolving correct package.json
'import/no-extraneous-dependencies': 'off',
'import/prefer-default-export': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'no-underscore-dangle': 'off',
'no-console': 'off',
'jsx-quotes': ['error', 'prefer-double'],
'react/jsx-props-no-spreading': 'off',
},
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
project: './tsconfig.json',
tsconfigRootDir: __dirname,
createDefaultProgram: true,
},
settings: {
'import/resolver': {
// See https://github.com/benmosher/eslint-plugin-import/issues/1396#issuecomment-575727774 for line below
node: {},
webpack: {
config: require.resolve('./.erb/configs/webpack.config.eslint.js'),
},
},
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
},
};

12
.gitattributes

@ -0,0 +1,12 @@
* text eol=lf
*.exe binary
*.png binary
*.jpg binary
*.jpeg binary
*.ico binary
*.icns binary
*.eot binary
*.otf binary
*.ttf binary
*.woff binary
*.woff2 binary

5
.github/FUNDING.yml

@ -0,0 +1,5 @@
# These are supported funding model platforms
github: [electron-react-boilerplate, amilajack]
patreon: amilajack
open_collective: electron-react-boilerplate-594

67
.github/ISSUE_TEMPLATE/1-Bug_report.md

@ -0,0 +1,67 @@
---
name: Bug report
about: You're having technical issues. ๐Ÿž
labels: 'bug'
---
<!-- Please use the following issue template or your issue will be closed -->
## Prerequisites
<!-- If the following boxes are not ALL checked, your issue is likely to be closed -->
- [ ] Using yarn
- [ ] Using an up-to-date [`master` branch](https://github.com/electron-react-boilerplate/electron-react-boilerplate/tree/master)
- [ ] Using latest version of devtools. [Check the docs for how to update](https://electron-react-boilerplate.js.org/docs/dev-tools/)
- [ ] Tried solutions mentioned in [#400](https://github.com/electron-react-boilerplate/electron-react-boilerplate/issues/400)
- [ ] For issue in production release, add devtools output of `DEBUG_PROD=true yarn build && yarn start`
## Expected Behavior
<!--- What should have happened? -->
## Current Behavior
<!--- What went wrong? -->
## Steps to Reproduce
<!-- Add relevant code and/or a live example -->
<!-- Add stack traces -->
1.
2.
3.
4.
## Possible Solution (Not obligatory)
<!--- Suggest a reason for the bug or how to fix it. -->
## Context
<!--- How has this issue affected you? What are you trying to accomplish? -->
<!--- Did you make any changes to the boilerplate after cloning it? -->
<!--- Providing context helps us come up with a solution that is most useful in the real world -->
## Your Environment
<!--- Include as many relevant details about the environment you experienced the bug in -->
- Node version :
- electron-react-boilerplate version or branch :
- Operating System and version :
- Link to your project :
<!---
โ—๏ธโ—๏ธ Also, please consider donating (https://opencollective.com/electron-react-boilerplate-594) โ—๏ธโ—๏ธ
Donations will ensure the following:
๐Ÿ”จ Long term maintenance of the project
๐Ÿ›ฃ Progress on the roadmap
๐Ÿ› Quick responses to bug reports and help requests
-->

19
.github/ISSUE_TEMPLATE/2-Question.md

@ -0,0 +1,19 @@
---
name: Question
about: Ask a question.โ“
labels: 'question'
---
## Summary
<!-- What do you need help with? -->
<!---
โ—๏ธโ—๏ธ Also, please consider donating (https://opencollective.com/electron-react-boilerplate-594) โ—๏ธโ—๏ธ
Donations will ensure the following:
๐Ÿ”จ Long term maintenance of the project
๐Ÿ›ฃ Progress on the roadmap
๐Ÿ› Quick responses to bug reports and help requests
-->

15
.github/ISSUE_TEMPLATE/3-Feature_request.md

@ -0,0 +1,15 @@
---
name: Feature request
about: You want something added to the boilerplate. ๐ŸŽ‰
labels: 'enhancement'
---
<!---
โ—๏ธโ—๏ธ Also, please consider donating (https://opencollective.com/electron-react-boilerplate-594) โ—๏ธโ—๏ธ
Donations will ensure the following:
๐Ÿ”จ Long term maintenance of the project
๐Ÿ›ฃ Progress on the roadmap
๐Ÿ› Quick responses to bug reports and help requests
-->

6
.github/config.yml

@ -0,0 +1,6 @@
requiredHeaders:
- Prerequisites
- Expected Behavior
- Current Behavior
- Possible Solution
- Your Environment

17
.github/stale.yml

@ -0,0 +1,17 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 40
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pr
- discussion
- e2e
- enhancement
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

55
.github/workflows/publish.yml

@ -0,0 +1,55 @@
name: Publish
on:
push:
branches:
- master
jobs:
publish:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ macos-latest ]
steps:
- name: Checkout git repo
uses: actions/checkout@v1
- name: Install Node, NPM and Yarn
uses: actions/setup-node@v1
with:
node-version: 15
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v1
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install dependencies
run: |
yarn install --prefer-offline
- name: Install dependencies
run: |
yarn install
- name: Publish releases
env:
# These values are used for auto updates signing
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_ID_PASS: ${{ secrets.APPLE_ID_PASS }}
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
# This is used for uploading release assets to github
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
yarn postinstall && yarn build && yarn electron-builder --publish always --win --mac --linux

33
.github/workflows/test.yml

@ -0,0 +1,33 @@
name: Test
on: [push, pull_request]
jobs:
release:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- name: Check out Git repository
uses: actions/checkout@v1
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v1
with:
node-version: 15
- name: yarn install
run: |
yarn install --frozen-lockfile --network-timeout 300000
- name: yarn test
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
yarn package
yarn lint
yarn tsc
yarn test

50
.gitignore

@ -0,0 +1,50 @@
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
.eslintcache
# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules
# OSX
.DS_Store
# App packaged
release
src/main.prod.js
src/main.prod.js.map
src/renderer.prod.js
src/renderer.prod.js.map
src/style.css
src/style.css.map
dist
dll
main.js
main.js.map
.idea
npm-debug.log.*
*.css.d.ts
*.sass.d.ts
*.scss.d.ts

6
.prettierrc

@ -0,0 +1,6 @@
{
"trailingComma": "es5",
"tabWidth": 2,
"semi": true,
"singleQuote": false
}

7
.vscode/extensions.json

@ -0,0 +1,7 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"EditorConfig.EditorConfig",
"msjsdiag.debugger-for-chrome"
]
}

28
.vscode/launch.json

@ -0,0 +1,28 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Electron: Main",
"type": "node",
"request": "launch",
"protocol": "inspector",
"runtimeExecutable": "yarn",
"runtimeArgs": ["start:main --inspect=5858 --remote-debugging-port=9223"],
"preLaunchTask": "Start Webpack Dev"
},
{
"name": "Electron: Renderer",
"type": "chrome",
"request": "attach",
"port": 9223,
"webRoot": "${workspaceFolder}",
"timeout": 15000
}
],
"compounds": [
{
"name": "Electron: All",
"configurations": ["Electron: Main", "Electron: Renderer"]
}
]
}

28
.vscode/settings.json

@ -0,0 +1,28 @@
{
"files.associations": {
".babelrc": "jsonc",
".eslintrc": "jsonc",
".prettierrc": "jsonc",
".eslintignore": "ignore"
},
"javascript.validate.enable": false,
"javascript.format.enable": false,
"typescript.format.enable": false,
"search.exclude": {
".git": true,
".eslintcache": true,
"src/dist": true,
"src/main.prod.js": true,
"src/main.prod.js.map": true,
"bower_components": true,
"dll": true,
"release": true,
"node_modules": true,
"npm-debug.log.*": true,
"test/**/__snapshots__": true,
"yarn.lock": true,
"*.{css,sass,scss}.d.ts": true
}
}

25
.vscode/tasks.json

@ -0,0 +1,25 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"label": "Start Webpack Dev",
"script": "start:renderer",
"options": {
"cwd": "${workspaceFolder}"
},
"isBackground": true,
"problemMatcher": {
"owner": "custom",
"pattern": {
"regexp": "____________"
},
"background": {
"activeOnStart": true,
"beginsPattern": "Compiling\\.\\.\\.$",
"endsPattern": "(Compiled successfully|Failed to compile)\\.$"
}
}
}
]
}

533
CHANGELOG.md

@ -0,0 +1,533 @@
# 2.1.0
- Migrate to `css-minifier-webpack-plugin`
# 2.0.1
## Fixes
- Fix broken css linking in production build
# 2.0.0
## Breaking Changes
- drop redux
- remove counter example app
- simplify directory structure
- move `dll` dir to `.erb` dir
- fix icon/font import paths
- migrate to `react-refresh` from `react-hot-loader`
- migrate to webpack@5
- migrate to electron@11
- remove e2e tests and testcafe integration
- rename `app` dir to more conventional `src` dir
- rename `resources` dir to `assets`
- simplify npm scripts
- drop stylelint
- simplify styling of boilerplate app
- remove `START_HOT` env variable
- notarize support
- landing page boilerplate
- docs updates
- restore removed debugging support
# 1.4.0
- Migrate to `eslint-config-erb@2`
- Rename `dev` npm script to `start`
- GitHub Actions: only publish GitHub releases when on master branch
# 1.3.1
- Fix sass building bug ([#2540](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2540))
- Fix CI bug related to E2E tests and network timeouts
- Move automated dependency PRs to `next` ([#2554](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2554))
- Bump dependencies to patch semver
# 1.3.0
- Fixes E2E tests ([#2516](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2516))
- Fixes preload entrypoint ([#2503](https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2503))
- Downgrade to `electron@8`
- Bump dependencies to latest semver
# 1.2.0
- Migrate to redux toolkit
- Lazy load routes with react suspense
- Drop support for azure-pipelines and use only github actions
- Bump all deps to latest semver
- Remove `test-e2e` script from tests (blocked on release of https://github.com/DevExpress/testcafe-browser-provider-electron/pull/65)
- Swap `typed-css-modules-webpack-plugin` for `typings-for-css-modules-loader`
- Use latest version of `eslint-config-erb`
- Remove unnecessary file extensions from ts exclude
- Add experimental support for vscode debugging
- Revert https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2365 as default for users, provide as opt in option
# 1.1.0
- Fix #2402
- Simplify configs (https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2406)
# 1.0.0
- Migrate to TypeScript from Flow ([#2363]