Repository: saltyshiomix/nuxtron
Branch: master
Commit: cef83b72c5b3
Files: 47
Total size: 38.2 KB
Directory structure:
gitextract_qgi3zrsw/
├── .babelrc
├── .gitignore
├── LICENSE
├── README.md
├── dev.js
├── examples/
│ ├── _template/
│ │ ├── gitignore.txt
│ │ ├── js/
│ │ │ ├── main/
│ │ │ │ ├── background.js
│ │ │ │ └── helpers/
│ │ │ │ ├── create-window.js
│ │ │ │ ├── exit-on-change.js
│ │ │ │ └── index.js
│ │ │ └── resources/
│ │ │ └── icon.icns
│ │ └── ts/
│ │ ├── main/
│ │ │ ├── background.ts
│ │ │ └── helpers/
│ │ │ ├── create-window.ts
│ │ │ ├── exit-on-change.ts
│ │ │ └── index.ts
│ │ └── resources/
│ │ └── icon.icns
│ ├── custom-build-options/
│ │ ├── README.md
│ │ ├── electron-builder.yml
│ │ ├── package.json
│ │ └── renderer/
│ │ ├── nuxt.config.js
│ │ └── pages/
│ │ ├── about.vue
│ │ └── home.vue
│ ├── with-javascript/
│ │ ├── README.md
│ │ ├── electron-builder.yml
│ │ ├── package.json
│ │ └── renderer/
│ │ ├── nuxt.config.js
│ │ └── pages/
│ │ ├── about.vue
│ │ └── home.vue
│ └── with-typescript/
│ ├── README.md
│ ├── electron-builder.yml
│ ├── package.json
│ ├── renderer/
│ │ ├── nuxt.config.js
│ │ └── pages/
│ │ ├── about.vue
│ │ └── home.vue
│ └── tsconfig.json
├── lib/
│ ├── logger.ts
│ ├── nuxtron-build.ts
│ ├── nuxtron-dev.ts
│ ├── nuxtron-init.ts
│ ├── nuxtron-list.ts
│ ├── nuxtron.ts
│ └── webpack/
│ ├── build.production.ts
│ ├── helpers.ts
│ └── webpack.config.ts
├── package.json
├── rollup.config.js
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .babelrc
================================================
{
"presets": [
"@babel/preset-typescript"
],
"plugins": [
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-syntax-dynamic-import"
]
}
================================================
FILE: .gitignore
================================================
# logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# npm output
node_modules/
# lock files
package-lock.json
yarn.lock
pnpm-lock.yaml
# macOS
.DS_Store
# nuxtron dev output
bin
workspace
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2018 Shiono Yoshihide
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================

Build a [Nuxt.js](https://nuxtjs.org/) + [Electron](https://electronjs.org/) app for speed ⚡
(The screenshot above is a top page of [examples/with-javascript](./examples/with-javascript).)
## Support
| nuxtron | nuxt |
| --- | --- |
| `v0.x` | `v2.x` |
## My Belief for Nuxtron
1. Show a way of developing desktop apps only web knowledge
1. Easy to use
1. Be transparent and open to OSS developers
## Usage
### Install
```bash
$ npm install --global nuxtron
```
### Create Application
To create `my-app`, just run the command below:
```bash
$ nuxtron init my-app
```
### Create Application with Template
You can use `examples/*` apps as a template.
To create the `examples/with-typescript` app, run the command below:
```bash
$ nuxtron init my-app --example with-typescript
```
### Development Mode
Run `npm run dev`, and nuxtron automatically launches an electron app.
```json
{
"scripts": {
"dev": "nuxtron"
}
}
```
### Production Build
Run `npm run build`, and nuxtron outputs packaged bundles under the `dist` folder.
```json
{
"scripts": {
"build": "nuxtron build"
}
}
```
### Build Options
To build Windows 32 bit version, run `npm run build:win32` like below:
```json
{
"scripts": {
"build": "nuxtron build",
"build:all": "nuxtron build --all",
"build:win32": "nuxtron build --win --ia32",
"build:win64": "nuxtron build --win --x64",
"build:mac": "nuxtron build --mac --x64",
"build:linux": "nuxtron build --linux"
}
}
```
**CAUTION**: To build macOS binary, your host machine must be macOS!
### Build Configuration
Edit `electron-builder.yml` properties for custom build configuration.
```yml
appId: com.example.nuxtron
productName: My Nuxtron App
copyright: Copyright © 2019 Shiono Yoshihide
directories:
output: dist
buildResources: resources
files:
- from: .
filter:
- package.json
- app
publish: null
```
For more information, please check out [electron-builder official configuration documents](https://www.electron.build/configuration/configuration/).
## Examples
See [examples](./examples) folder for more information.
Or you can start the example app by `nuxtron init --example `.
To list all examples, just type the command below:
```bash
$ nuxtron list
```
### [examples/custom-build-options](./examples/custom-build-options)
```bash
$ nuxtron init my-app --example custom-build-options
```
### [examples/with-javascript](./examples/with-javascript)
```bash
$ nuxtron init my-app --example with-javascript
```
### [examples/with-typescript](./examples/with-typescript)
```bash
$ nuxtron init my-app --example with-typescript
```
## Develop `examples/*`
```bash
$ git clone https://github.com/saltyshiomix/nuxtron.git
$ cd nuxtron
$ yarn
$ yarn dev
```
## Related
- [Nextron](https://github.com/saltyshiomix/nextron) - ⚡ Electron + NEXT.js ⚡
================================================
FILE: dev.js
================================================
const { remove, existsSync } = require('fs-extra');
const { resolve } = require('path');
const { execSync } = require('child_process');
const chalk = require('chalk');
async function detectPackageManager() {
const { promisify } = require('util');
const { exec: defaultExec } = require('child_process');
const cwd = process.cwd();
const exec = promisify(defaultExec);
let pm = 'yarn';
try {
await exec(`${pm} -v`, { cwd });
} catch (_) {
pm = 'pnpm';
try {
await exec(`${pm} -v`, { cwd });
} catch (_ignore) {
pm = 'npm';
try {
await exec(`${pm} -v`, { cwd });
} catch (_) {
pm = undefined;
}
}
}
if (pm === undefined) {
console.log(chalk.red('No available package manager! (`yarn`, `pnpm` or `npm` is needed)'));
process.exit(1);
}
return pm;
}
async function dev() {
process.env.NODE_ENV = 'testing';
let example = 'with-javascript';
if (3 <= process.argv.length) {
const newExample = process.argv[2];
if (!existsSync(resolve(__dirname, `examples/${newExample}`))) {
console.log(chalk.red(`Not found examples/${newExample}`));
console.log('');
process.exit(1);
}
example = newExample;
}
await remove('workspace');
execSync('node ' + resolve(__dirname, 'bin/nuxtron') + ` init workspace --example ${example}`, {
cwd: __dirname,
stdio: 'inherit',
});
const pm = await detectPackageManager();
execSync(`${pm} install && ${pm} run dev`, {
cwd: resolve(__dirname, 'workspace'),
stdio: 'inherit',
});
}
dev();
================================================
FILE: examples/_template/gitignore.txt
================================================
node_modules
*.log
.nuxt
app
dist
================================================
FILE: examples/_template/js/main/background.js
================================================
import { app } from 'electron';
import serve from 'electron-serve';
import {
createWindow,
exitOnChange,
} from './helpers';
const isProd = process.env.NODE_ENV === 'production';
if (isProd) {
serve({ directory: 'app' });
} else {
exitOnChange();
app.setPath('userData', `${app.getPath('userData')} (development)`);
}
(async () => {
await app.whenReady();
const mainWindow = createWindow('main', {
width: 1000,
height: 600,
});
if (isProd) {
await mainWindow.loadURL('app://./home');
} else {
const port = process.argv[2];
await mainWindow.loadURL(`http://localhost:${port}/home`);
mainWindow.webContents.openDevTools();
}
})();
app.on('window-all-closed', () => {
app.quit();
});
================================================
FILE: examples/_template/js/main/helpers/create-window.js
================================================
import {
screen,
BrowserWindow,
} from 'electron';
import * as Store from 'electron-store';
export default function createWindow(windowName, options) {
const key = 'window-state';
const name = `window-state-${windowName}`;
const store = new Store({ name });
const defaultSize = {
width: options.width,
height: options.height,
};
let state = {};
let win;
const restore = () => store.get(key, defaultSize);
const getCurrentPosition = () => {
const position = win.getPosition();
const size = win.getSize();
return {
x: position[0],
y: position[1],
width: size[0],
height: size[1],
};
};
const windowWithinBounds = (windowState, bounds) => {
return (
windowState.x >= bounds.x &&
windowState.y >= bounds.y &&
windowState.x + windowState.width <= bounds.x + bounds.width &&
windowState.y + windowState.height <= bounds.y + bounds.height
);
};
const resetToDefaults = () => {
const bounds = screen.getPrimaryDisplay().bounds;
return Object.assign({}, defaultSize, {
x: (bounds.width - defaultSize.width) / 2,
y: (bounds.height - defaultSize.height) / 2
});
};
const ensureVisibleOnSomeDisplay = (windowState) => {
const visible = screen.getAllDisplays().some(display => {
return windowWithinBounds(windowState, display.bounds)
});
if (!visible) {
// Window is partially or fully not visible now.
// Reset it to safe defaults.
return resetToDefaults();
}
return windowState;
};
const saveState = () => {
if (!win.isMinimized() && !win.isMaximized()) {
Object.assign(state, getCurrentPosition());
}
store.set(key, state);
};
state = ensureVisibleOnSomeDisplay(restore());
win = new BrowserWindow({
...options,
...state,
webPreferences: {
nodeIntegration: true,
},
});
win.on('close', saveState);
return win;
};
================================================
FILE: examples/_template/js/main/helpers/exit-on-change.js
================================================
import { watchFile } from 'fs';
import { join } from 'path';
import { app } from 'electron';
export default function exitOnChange() {
watchFile(join(process.cwd(), 'app/background.js'), () => {
app.exit(0);
});
};
================================================
FILE: examples/_template/js/main/helpers/index.js
================================================
import createWindow from './create-window';
import exitOnChange from './exit-on-change';
export {
createWindow,
exitOnChange,
};
================================================
FILE: examples/_template/ts/main/background.ts
================================================
import { app } from 'electron';
import serve from 'electron-serve';
import {
createWindow,
exitOnChange,
} from './helpers';
const isProd: boolean = process.env.NODE_ENV === 'production';
if (isProd) {
serve({ directory: 'app' });
} else {
exitOnChange();
app.setPath('userData', `${app.getPath('userData')} (development)`);
}
(async () => {
await app.whenReady();
const mainWindow = createWindow('main', {
width: 1000,
height: 600,
});
if (isProd) {
await mainWindow.loadURL('app://./home');
} else {
const port = process.argv[2];
await mainWindow.loadURL(`http://localhost:${port}/home`);
mainWindow.webContents.openDevTools();
}
})();
app.on('window-all-closed', () => {
app.quit();
});
================================================
FILE: examples/_template/ts/main/helpers/create-window.ts
================================================
import {
screen,
BrowserWindow,
BrowserWindowConstructorOptions,
Rectangle,
} from 'electron';
import Store from 'electron-store';
export default (windowName: string, options: BrowserWindowConstructorOptions): BrowserWindow => {
const key = 'window-state';
const name = `window-state-${windowName}`;
const store = new Store({ name });
const defaultSize = {
width: options.width,
height: options.height,
};
let state = {};
let win: BrowserWindow;
const restore = () => store.get(key, defaultSize);
const getCurrentPosition = () => {
const position = win.getPosition();
const size = win.getSize();
return {
x: position[0],
y: position[1],
width: size[0],
height: size[1],
};
};
const windowWithinBounds = (windowState: Rectangle, bounds: Rectangle) => {
return (
windowState.x >= bounds.x &&
windowState.y >= bounds.y &&
windowState.x + windowState.width <= bounds.x + bounds.width &&
windowState.y + windowState.height <= bounds.y + bounds.height
);
};
const resetToDefaults = () => {
const bounds = screen.getPrimaryDisplay().bounds;
return Object.assign({}, defaultSize, {
x: (bounds.width - defaultSize.width) / 2,
y: (bounds.height - defaultSize.height) / 2,
});
};
const ensureVisibleOnSomeDisplay = (windowState: Rectangle) => {
const visible = screen.getAllDisplays().some(display => {
return windowWithinBounds(windowState, display.bounds);
});
if (!visible) {
// Window is partially or fully not visible now.
// Reset it to safe defaults.
return resetToDefaults();
}
return windowState;
};
const saveState = () => {
if (!win.isMinimized() && !win.isMaximized()) {
Object.assign(state, getCurrentPosition());
}
store.set(key, state);
};
state = ensureVisibleOnSomeDisplay(restore());
const browserOptions: BrowserWindowConstructorOptions = {
...options,
...state,
webPreferences: {
nodeIntegration: true,
},
};
win = new BrowserWindow(browserOptions);
win.on('close', saveState);
return win;
};
================================================
FILE: examples/_template/ts/main/helpers/exit-on-change.ts
================================================
import { watchFile } from 'fs';
import { join } from 'path';
import { app } from 'electron';
export default function exitOnChange(): void {
watchFile(join(process.cwd(), 'app/background.js'), () => {
app.exit(0);
});
};
================================================
FILE: examples/_template/ts/main/helpers/index.ts
================================================
import createWindow from './create-window';
import exitOnChange from './exit-on-change';
export {
createWindow,
exitOnChange,
};
================================================
FILE: examples/custom-build-options/README.md
================================================

## Usage
```bash
# create an app
$ nuxtron init my-app --example custom-build-options
# install dependencies
$ cd my-app
$ yarn (or `npm install`)
# development mode
$ yarn dev (or `npm run dev`)
# production build
$ yarn build (or `npm run build`)
# production build for all platform
$ yarn build:all (or `npm run build:all`)
# production build for windows 32 bit
$ yarn build:win (or `npm run build:win`)
# production build for macOS 64 bit
$ yarn build:mac (or `npm run build:mac`)
# production build for Linux
$ yarn build:linux (or `npm run build:linux`)
```
================================================
FILE: examples/custom-build-options/electron-builder.yml
================================================
appId: com.example.nuxtron
productName: My Nuxtron App
copyright: Copyright © 2019 Shiono Yoshihide
directories:
output: dist
buildResources: resources
files:
- from: .
filter:
- package.json
- app
publish: null
================================================
FILE: examples/custom-build-options/package.json
================================================
{
"private": true,
"name": "custom-build-options",
"description": "My application description",
"version": "1.0.0",
"author": "Shiono Yoshihide ",
"main": "app/background.js",
"scripts": {
"dev": "nuxtron",
"build": "nuxtron build",
"build:all": "nuxtron build --all",
"build:win": "nuxtron build --win --ia32",
"build:mac": "nuxtron build --mac --x64",
"build:linux": "nuxtron build --linux"
},
"dependencies": {
"electron-serve": "^1.0.0",
"electron-store": "^6.0.1"
},
"devDependencies": {
"electron": "^10.1.5",
"electron-builder": "^22.9.1",
"nuxt": "^2.14.7",
"nuxtron": "^0.3.1"
}
}
================================================
FILE: examples/custom-build-options/renderer/nuxt.config.js
================================================
export default {
head: {
title: 'Nuxtron (custom-build-options)',
},
build: {
extend: (config) => {
config.target = 'electron-renderer';
},
},
}
================================================
FILE: examples/custom-build-options/renderer/pages/about.vue
================================================
Thank you for testing Nuxtron
Loaded from the {{ name }}
Back home
================================================
FILE: examples/custom-build-options/renderer/pages/home.vue
================================================
Hello Nuxtron.
Loaded from the {{ name }}
About
================================================
FILE: examples/with-javascript/README.md
================================================

## Usage
```bash
# create an app
$ nuxtron init my-app --example with-javascript
# install dependencies
$ cd my-app
$ yarn (or `npm install`)
# development mode
$ yarn dev (or `npm run dev`)
# production build
$ yarn build (or `npm run build`)
```
================================================
FILE: examples/with-javascript/electron-builder.yml
================================================
appId: com.example.nuxtron
productName: My Nuxtron App
copyright: Copyright © 2019 Shiono Yoshihide
directories:
output: dist
buildResources: resources
files:
- from: .
filter:
- package.json
- app
publish: null
================================================
FILE: examples/with-javascript/package.json
================================================
{
"private": true,
"name": "with-javascript",
"description": "My application description",
"version": "1.0.0",
"author": "Shiono Yoshihide ",
"main": "app/background.js",
"scripts": {
"dev": "nuxtron",
"build": "nuxtron build"
},
"dependencies": {
"electron-serve": "^1.0.0",
"electron-store": "^6.0.1"
},
"devDependencies": {
"electron": "^10.1.5",
"electron-builder": "^22.9.1",
"nuxt": "^2.14.7",
"nuxtron": "^0.3.1"
}
}
================================================
FILE: examples/with-javascript/renderer/nuxt.config.js
================================================
export default {
head: {
title: 'Nuxtron (with-javascript)',
},
build: {
extend: (config) => {
config.target = 'electron-renderer';
},
},
}
================================================
FILE: examples/with-javascript/renderer/pages/about.vue
================================================
Thank you for testing Nuxtron
Loaded from the {{ name }}
Back home
================================================
FILE: examples/with-javascript/renderer/pages/home.vue
================================================
Hello Nuxtron.
Loaded from the {{ name }}
About
================================================
FILE: examples/with-typescript/README.md
================================================

## Usage
```bash
# create an app
$ nuxtron init my-app --example with-typescript
# install dependencies
$ cd my-app
$ yarn (or `npm install`)
# development mode
$ yarn dev (or `npm run dev`)
# production build
$ yarn build (or `npm run build`)
```
================================================
FILE: examples/with-typescript/electron-builder.yml
================================================
appId: com.example.nuxtron
productName: My Nuxtron App
copyright: Copyright © 2019 Shiono Yoshihide
directories:
output: dist
buildResources: resources
files:
- from: .
filter:
- package.json
- app
publish: null
================================================
FILE: examples/with-typescript/package.json
================================================
{
"private": true,
"name": "with-typescript",
"description": "My application description",
"version": "1.0.0",
"author": "Shiono Yoshihide ",
"main": "app/background.js",
"scripts": {
"dev": "nuxtron",
"build": "nuxtron build"
},
"dependencies": {
"electron-serve": "^1.0.0",
"electron-store": "^6.0.1"
},
"devDependencies": {
"@nuxt/typescript": "^2.8.1",
"@types/node": "^12.7.12",
"electron": "^10.1.5",
"electron-builder": "^22.9.1",
"nuxt": "^2.14.7",
"nuxtron": "^0.3.1",
"typescript": "^3.6.4"
}
}
================================================
FILE: examples/with-typescript/renderer/nuxt.config.js
================================================
export default {
head: {
title: 'Nuxtron (with-typescript)',
},
build: {
extend: (config) => {
config.target = 'electron-renderer';
},
},
}
================================================
FILE: examples/with-typescript/renderer/pages/about.vue
================================================
Thank you for testing Nuxtron
Loaded from the {{ name }}
Back home
================================================
FILE: examples/with-typescript/renderer/pages/home.vue
================================================
Hello Nuxtron.
Loaded from the {{ name }}
About
================================================
FILE: examples/with-typescript/tsconfig.json
================================================
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"jsx": "preserve",
"strict": true,
"sourceMap": true,
"importHelpers": true,
"esModuleInterop": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true
},
"exclude": [
"node_modules"
]
}
================================================
FILE: lib/logger.ts
================================================
import chalk from 'chalk';
const log = (text: string) => {
console.log(chalk`{cyan [nuxtron]} ${text}`);
};
export default log;
================================================
FILE: lib/nuxtron-build.ts
================================================
import fs from 'fs-extra';
import path from 'path';
import { SpawnSyncOptions } from 'child_process';
import arg from 'arg';
import chalk from 'chalk';
import spawn from 'cross-spawn';
import { getNuxtronConfig } from './webpack/helpers';
import log from './logger';
const args = arg({
'--help': Boolean,
'--version': Boolean,
'--all': Boolean,
'--win': Boolean,
'--mac': Boolean,
'--linux': Boolean,
'--x64': Boolean,
'--ia32': Boolean,
'--armv7l': Boolean,
'--arm64': Boolean,
'--config': String,
'-h': '--help',
'-v': '--version',
'-w': '--win',
'-m': '--mac',
'-l': '--linux',
'-c': '--config',
});
if (args['--help']) {
console.log(chalk`
{bold.cyan nuxtron build} - Build and export the application for production deployment
{bold USAGE}
{bold $} {cyan nuxtron build} --help
{bold $} {cyan nuxtron build} [options]
{bold OPTIONS}
--help, -h shows this help message
--version, -v displays the current version of nuxtron
--all builds for Windows, macOS and Linux
--win, -w builds for Windows, accepts target list (see https://goo.gl/jYsTEJ)
--mac, -m builds for macOS, accepts target list (see https://goo.gl/5uHuzj)
--linux, -l builds for Linux, accepts target list (see https://goo.gl/4vwQad)
--x64 builds for x64
--ia32 builds for ia32
--armv7l builds for armv7l
--arm64 builds for arm64
`);
process.exit(0);
}
const cwd = process.cwd();
const spawnOptions: SpawnSyncOptions = {
cwd,
stdio: 'inherit',
};
async function build() {
// Ignore missing dependencies
process.env.ELECTRON_BUILDER_ALLOW_UNRESOLVED_DEPENDENCIES = 'true';
const rendererSrcDir = getNuxtronConfig().rendererSrcDir || 'renderer';
try {
log('Clearing previous builds');
fs.removeSync(path.join(cwd, 'app'));
fs.removeSync(path.join(cwd, 'dist'));
fs.removeSync(path.join(cwd, rendererSrcDir, '.nuxt'));
log('Building renderer process');
const outdir = path.join(cwd, rendererSrcDir, 'dist');
const appdir = path.join(cwd, 'app');
spawn.sync('nuxt', ['build', path.join(cwd, rendererSrcDir)], spawnOptions);
spawn.sync('nuxt', ['generate', path.join(cwd, rendererSrcDir)], spawnOptions);
fs.copySync(outdir, appdir);
fs.removeSync(outdir);
log('Building main process');
spawn.sync('node', [path.join(__dirname, 'webpack/build.production.js')], spawnOptions);
log('Packaging - please wait a moment');
spawn.sync('electron-builder', createBuilderArgs(), spawnOptions);
log('See `dist` directory');
} catch (err) {
console.log(chalk`
{bold.red Cannot build electron packages:}
{bold.yellow ${err}}
`);
process.exit(1);
}
}
function createBuilderArgs() {
let results = [];
if (args['--config']) {
results.push('--config');
results.push(args['--config'] || 'electron-builder.yml');
}
if (args['--all']) {
results.push('-wml');
results.push(...createArchArgs());
} else {
args['--win'] && results.push('--win');
args['--mac'] && results.push('--mac');
args['--linux'] && results.push('--linux');
results.push(...createArchArgs());
}
return results;
}
function createArchArgs() {
let archArgs = [];
args['--x64'] && archArgs.push('--x64');
args['--ia32'] && archArgs.push('--ia32');
args['--armv7l'] && archArgs.push('--armv7l');
args['--arm64'] && archArgs.push('--arm64');
return archArgs;
}
build();
================================================
FILE: lib/nuxtron-dev.ts
================================================
import {
ChildProcess,
SpawnSyncOptions,
} from 'child_process';
import arg from 'arg';
import chalk from 'chalk';
import spawn from 'cross-spawn';
import delay from 'delay';
import webpack from 'webpack';
import {
getNuxtronConfig,
getWebpackConfig,
} from './webpack/helpers';
const args = arg({
'--help': Boolean,
'--version': Boolean,
'--port': Number,
'--custom-server': String,
'-h': '--help',
'-v': '--version',
'-p': '--port',
'-c': '--custom-server',
});
if (args['--help']) {
console.log(chalk`
{bold.cyan nuxtron dev} - Starts the nuxtron application in development mode
{bold USAGE}
{bold $} {cyan nuxtron dev} --help
{bold $} {cyan nuxtron dev}
{bold OPTIONS}
--help, -h shows this help message
--version, -v displays the current version of nuxtron
`);
process.exit(0);
}
const rendererPort = args['--port'] || 8888;
const spawnOptions: SpawnSyncOptions = {
cwd: process.cwd(),
stdio: 'inherit',
};
async function dev() {
const { rendererSrcDir } = getNuxtronConfig();
let firstCompile = true;
let watching: any;
let mainProcess: ChildProcess;
let rendererProcess: ChildProcess;
const startMainProcess = () => {
mainProcess = spawn('electron', ['.', `${rendererPort}`], {
detached: true,
...spawnOptions,
});
mainProcess.unref();
};
const startRendererProcess = () => {
const child = spawn('nuxt', ['-p', rendererPort, rendererSrcDir || 'renderer'], spawnOptions);
child.on('close', () => {
process.exit(0);
});
return child;
};
const killWholeProcess = () => {
if (watching) {
watching.close(() => {});
}
if (mainProcess) {
mainProcess.kill();
}
if (rendererProcess) {
rendererProcess.kill();
}
};
process.on('SIGINT', killWholeProcess);
process.on('SIGTERM', killWholeProcess);
process.on('exit', killWholeProcess);
rendererProcess = startRendererProcess();
// wait until renderer process is ready
await delay(8000);
const compiler = webpack(getWebpackConfig('development'));
watching = compiler.watch({}, async (err: any) => {
if (err) {
console.error(err.stack || err);
if (err.details) {
console.error(err.details);
}
}
if (firstCompile) {
firstCompile = false;
}
if (!err) {
if (!firstCompile) {
if (mainProcess) {
mainProcess.kill();
}
}
startMainProcess();
}
});
}
dev();
================================================
FILE: lib/nuxtron-init.ts
================================================
import fs from 'fs-extra';
import path from 'path';
import { execSync } from 'child_process';
import arg from 'arg';
import chalk from 'chalk';
import log from './logger';
const cwd = process.cwd();
const args = arg({
'--help': Boolean,
'--version': Boolean,
'--template': String,
'--example': '--template',
'-h': '--help',
'-v': '--version',
'-t': '--template',
'-e': '--template',
});
if (args['--version']) {
const pkg = require(path.resolve(__dirname, '../package.json'));
console.log(`nuxtron v${pkg.version}`);
process.exit(0);
}
if (args['--help'] || (!args._[0])) {
console.log(chalk`
{bold.cyan nuxtron} - ⚡ Electron + Nuxt.js ⚡
{bold USAGE}
{bold $} {cyan nuxtron init} --help
{bold $} {cyan nuxtron init} {underline my-app}
{bold $} {cyan nuxtron init} {underline my-app} [--example {underline example_folder_name}]
{bold OPTIONS}
--help, -h shows this help message
--version, -v displays the current version of nuxtron
--example, -e {underline example_folder_name} sets the example as a template
`);
process.exit(0);
}
function detectPackageManager() {
let pm: string | undefined = 'yarn';
try {
execSync(`${pm} -v`, { cwd });
} catch (_) {
pm = 'pnpm';
try {
execSync(`${pm} -v`, { cwd });
} catch (_ignore) {
pm = 'npm';
try {
execSync(`${pm} -v`, { cwd });
} catch (_) {
pm = undefined;
}
}
}
if (pm === undefined) {
console.log(chalk.red('No available package manager! (`yarn`, `pnpm` or `npm` is needed)'));
process.exit(1);
}
return pm;
}
const example = args['--template'] || args['--example'] || 'with-javascript';
if (!fs.existsSync(path.resolve(__dirname, `../examples/${example}`))) {
console.log(chalk.red(`Not found examples/${example}`));
process.exit(1);
}
function init(name: string) {
log('Copy template');
const ext = fs.existsSync(path.resolve(__dirname, `../examples/${example}/tsconfig.json`)) ? 'ts' : 'js';
fs.copySync(path.resolve(__dirname, `../examples/_template/gitignore.txt`), path.join(cwd, `${name}/.gitignore`));
fs.copySync(path.resolve(__dirname, `../examples/_template/${ext}`), path.join(cwd, name));
fs.copySync(path.resolve(__dirname, `../examples/${example}`), path.join(cwd, name));
log('Set meta information');
const pkg = path.resolve(cwd, `${name}/package.json`);
const content = fs.readJSONSync(pkg);
content.name = name;
if (process.env.NODE_ENV === 'testing') {
content.devDependencies.nuxtron = cwd;
}
fs.writeJSONSync(pkg, {...content}, {spaces: 2});
let cmd: string;
const pm = detectPackageManager();
switch (pm) {
case 'yarn':
cmd = 'yarn && yarn dev';
break;
case 'pnpm':
cmd = 'pnpm install && pnpm run dev';
break;
default:
cmd = 'npm install && npm run dev';
break;
}
log(`Run \`${cmd}\` inside of "${name}" to start the app`);
}
init(args._[0] || 'my-nuxtron-app');
================================================
FILE: lib/nuxtron-list.ts
================================================
import fs from 'fs';
import path from 'path';
import arg from 'arg';
import chalk from 'chalk';
const args = arg({
'--help': Boolean,
'--version': Boolean,
'-h': '--help',
'-v': '--version',
});
if (args['--version']) {
const pkg = require(path.resolve(__dirname, '../package.json'));
console.log(`nuxtron v${pkg.version}`);
process.exit(0);
}
if (args['--help']) {
console.log(chalk`
{bold.cyan nuxtron} - ⚡ Electron + Nuxt.js ⚡
{bold USAGE}
{bold $} {cyan nuxtron list} --help
{bold $} {cyan nuxtron list}
{bold OPTIONS}
--help, -h shows this help message
--version, -v displays the current version of nuxtron
`);
process.exit(0);
}
let names = fs.readdirSync(path.resolve(__dirname, '../examples'));
names = names.filter(name => name.toLowerCase() !== '_template' && name.toLowerCase() !== '.ds_store');
console.log(chalk`
{bold.cyan Available examples (${names.length.toString()}):}
`);
for (let i = 0; i < names.length; i++) {
console.log(chalk` {bold - ${names[i]}}`);
}
console.log(chalk`
{bold USAGE}
{bold $} {cyan nuxtron init} {underline my-app} [--example {underline example_folder_name}]
If you want to use "{underline with-typescript}", just type the command below:
{bold $} nuxtron init my-app --example {underline with-typescript}
`);
================================================
FILE: lib/nuxtron.ts
================================================
import path from 'path';
import chalk from 'chalk';
import spawn from 'cross-spawn';
const defaultCommand = 'dev';
const commands = new Set([
'list',
'init',
'build',
defaultCommand,
]);
let cmd = process.argv[2];
let args: string[] = [];
let nodeArgs: string[] = [];
if (new Set(['--version', '-v']).has(cmd)) {
const pkg = require(path.resolve(__dirname, '../package.json'));
console.log(`nuxtron v${pkg.version}`);
process.exit(0);
}
if (new Set(['--help', '-h']).has(cmd)) {
console.log(chalk`
{bold.cyan nuxtron} - ⚡ Electron + Nuxt.js ⚡
{bold USAGE}
{bold $} {cyan nuxtron init} --help
{bold $} {cyan nuxtron init} {underline my-app}
{bold $} {cyan nuxtron init} {underline my-app} [--example {underline example_folder_name}]
`);
process.exit(0);
}
const inspectArg = process.argv.find(arg => arg.includes('--inspect'));
if (inspectArg) {
nodeArgs.push(inspectArg);
}
if (commands.has(cmd)) {
args = process.argv.slice(3);
} else {
cmd = defaultCommand;
args = process.argv.slice(2);
}
const defaultEnv = cmd === 'dev' ? 'development' : 'production';
process.env.NODE_ENV = process.env.NODE_ENV || defaultEnv;
const cli = path.join(__dirname, `nuxtron-${cmd}`);
const startProcess = () => {
const proc = spawn('node', [...nodeArgs, cli, ...args], { stdio: 'inherit' });
proc.on('close', (code: number, signal: string) => {
if (code !== null) {
process.exit(code);
}
if (signal) {
if (signal === 'SIGKILL') {
process.exit(137);
}
process.exit(1);
}
process.exit(0);
});
proc.on('error', (err) => {
console.error(err);
process.exit(1);
});
return proc;
}
const proc = startProcess();
const wrapper = () => {
if (proc) {
proc.kill();
}
}
process.on('SIGINT', wrapper);
process.on('SIGTERM', wrapper);
process.on('exit', wrapper);
================================================
FILE: lib/webpack/build.production.ts
================================================
import webpack from 'webpack';
import { getWebpackConfig } from './helpers';
const compiler = webpack(getWebpackConfig('production'));
compiler.run((err: Error, stats: webpack.Stats) => {
err && console.error(err.stack || err);
stats.hasErrors() && console.error(stats.toString());
});
================================================
FILE: lib/webpack/helpers.ts
================================================
import fs from 'fs';
import path from 'path';
import merge from 'webpack-merge';
import configure from './webpack.config';
const cwd = process.cwd();
const ext = fs.existsSync(path.join(cwd, 'tsconfig.json')) ? '.ts' : '.js';
const getNuxtronConfig = () => {
const configPath = path.join(cwd, 'nuxtron.config.js');
if (fs.existsSync(configPath)) {
return require(configPath);
} else {
return {};
}
};
const getWebpackConfig = (env: 'development' | 'production') => {
const { mainSrcDir, webpack } = getNuxtronConfig();
const userConfig = merge(configure(env), {
entry: {
background: path.join(cwd, mainSrcDir || 'main', `background${ext}`),
},
output: {
filename: '[name].js',
path: path.join(cwd, 'app'),
},
});
const userWebpack = webpack || {};
if (typeof userWebpack === 'function') {
return userWebpack(userConfig, env);
} else {
return merge(userConfig, userWebpack);
}
};
export {
getNuxtronConfig,
getWebpackConfig,
};
================================================
FILE: lib/webpack/webpack.config.ts
================================================
import path from 'path';
import webpack from 'webpack';
const cwd = process.cwd();
const externals = require(path.join(cwd, 'package.json')).dependencies;
export default (env: 'development' | 'production'): webpack.Configuration => ({
mode: env,
target: 'electron-main',
node: {
__dirname: false,
__filename: false,
},
externals: [...Object.keys(externals || {})],
devtool: 'source-map',
resolve: {
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
modules: [path.join(cwd, 'app'), 'node_modules'],
},
output: {
libraryTarget: 'commonjs2',
},
module: {
rules: [
{
test: /\.(js|ts)x?$/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: ['@babel/preset-typescript'],
},
},
exclude: [
/node_modules/,
path.join(cwd, 'renderer'),
],
},
],
},
plugins: [
new webpack.EnvironmentPlugin({
NODE_ENV: env,
}),
],
});
================================================
FILE: package.json
================================================
{
"name": "nuxtron",
"version": "0.3.1",
"description": "⚡ Nuxt.js + Electron ⚡",
"repository": "git@github.com:saltyshiomix/nuxtron.git",
"author": "Shiono Yoshihide ",
"license": "MIT",
"homepage": "https://github.com/saltyshiomix/nuxtron",
"keywords": [
"electron",
"nuxt",
"nuxtjs",
"nuxt.js",
"vue",
"vuejs",
"vue.js",
"nuxtron"
],
"bugs": {
"url": "https://github.com/saltyshiomix/nuxtron/issues",
"email": "shiono.yoshihide@gmail.com"
},
"files": [
"bin",
"examples"
],
"bin": {
"nuxtron": "bin/nuxtron.js"
},
"scripts": {
"predev": "npm run build",
"dev": "node dev",
"prebuild": "rimraf bin",
"build": "rollup -c",
"prepublishOnly": "cross-env NODE_ENV=production npm run build"
},
"dependencies": {
"@babel/core": "^7.12.3",
"@babel/preset-typescript": "^7.12.1",
"arg": "^4.1.3",
"babel-loader": "^8.1.0",
"chalk": "^4.1.0",
"cross-spawn": "^7.0.3",
"delay": "^4.4.0",
"fs-extra": "^9.0.1",
"webpack": "^5.2.0",
"webpack-merge": "^5.2.0"
},
"devDependencies": {
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@babel/plugin-proposal-object-rest-spread": "^7.12.1",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@rollup/plugin-babel": "^5.2.1",
"@rollup/plugin-commonjs": "^16.0.0",
"@rollup/plugin-node-resolve": "^10.0.0",
"@types/cross-spawn": "^6.0.2",
"@types/fs-extra": "^9.0.2",
"@types/node": "^14.14.5",
"cross-env": "^7.0.2",
"rimraf": "^3.0.2",
"rollup": "^2.32.1",
"rollup-plugin-auto-external": "^2.0.0",
"rollup-plugin-terser": "^7.0.2",
"typescript": "^4.0.5"
}
}
================================================
FILE: rollup.config.js
================================================
import external from 'rollup-plugin-auto-external';
import resolve from '@rollup/plugin-node-resolve';
import babel from '@rollup/plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
import { terser } from 'rollup-plugin-terser';
const extensions = ['.js', '.jsx', '.ts'];
const coreConfig = {
plugins: [
external(),
resolve({
extensions,
}),
babel({
extensions,
exclude: /node_modules/,
}),
commonjs(),
(process.env.NODE_ENV === 'production' && terser()),
],
external: [
],
};
const cliConfig = (src) => ({
input: src,
output: {
dir: 'bin',
format: 'cjs',
banner: '#!/usr/bin/env node',
},
...coreConfig,
});
const config = (src, dist) => ({
input: src,
output: {
file: dist,
format: 'cjs',
},
...coreConfig,
});
export default [
cliConfig('lib/nuxtron.ts'),
cliConfig('lib/nuxtron-init.ts'),
cliConfig('lib/nuxtron-dev.ts'),
cliConfig('lib/nuxtron-build.ts'),
cliConfig('lib/nuxtron-list.ts'),
config('lib/webpack/build.production.ts', 'bin/webpack/build.production.js'),
];
================================================
FILE: tsconfig.json
================================================
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"moduleResolution": "node",
"strict": true,
"skipLibCheck": true,
"esModuleInterop": true
},
"include": [
"lib"
]
}