Skip to content

Commit ee690dc

Browse files
jambuludsuprishi
authored andcommitted
added nextjs base code
1 parent 25da20b commit ee690dc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+12587
-0
lines changed

.gitignore

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# next.js
12+
/.next/
13+
/out/
14+
/renderer/.next/
15+
/renderer/out/
16+
/main/out/
17+
/dist/
18+
19+
# production
20+
/build
21+
22+
# misc
23+
.DS_Store
24+
.env*
25+
26+
# debug
27+
npm-debug.log*
28+
yarn-debug.log*
29+
yarn-error.log*
30+
31+
### react ###
32+
.DS_*
33+
*.log
34+
logs
35+
**/*.backup.*
36+
**/*.back.*
37+
38+
node_modules
39+
bower_componets
40+
41+
*.sublime*
42+
43+
psd
44+
thumb
45+
sketch
46+
47+
### VisualStudioCode ###
48+
.vscode/*
49+
!.vscode/settings.json
50+
!.vscode/tasks.json
51+
!.vscode/launch.json
52+
!.vscode/extensions.json
53+
54+
### VisualStudioCode Patch ###
55+
# Ignore all local history of files
56+
.history

README.md

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Nextjs + Electron + Typescript application example
2+
3+
## How to use
4+
5+
* Download or clone this project
6+
* run `npm install` in the root folder of the project
7+
8+
## Start
9+
10+
* run `npm run start`
11+
12+
## Build executable file
13+
14+
* run `npm run dist`

main/decorators/process.ts

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { ipcMain, IpcMainEvent } from 'electron';
2+
3+
function Process(path: string) { // this is the decorator factory
4+
return function (
5+
target: Object,
6+
propertyName: string,
7+
propertyDescriptor: PropertyDescriptor): PropertyDescriptor {
8+
const method = propertyDescriptor.value;
9+
10+
propertyDescriptor.value = function (...args: any[]) {
11+
let result: any;
12+
const eventHandler = (event: IpcMainEvent, ...eventArgs: any[]) => {
13+
Promise.resolve(method.apply(this, eventArgs)).then(result => {
14+
const r = JSON.stringify(result);
15+
16+
const params = eventArgs.map(a => JSON.stringify(a)).join();
17+
console.log(`Path: ${path}\t---> Call: ${propertyName}(${params}) => ${r}`)
18+
event.sender.send(path, result)
19+
});
20+
}
21+
22+
// invoke foo() and get its return value
23+
ipcMain.removeListener(path, eventHandler);
24+
ipcMain.on(path, eventHandler);
25+
26+
// return the result of invoking the method
27+
return result;
28+
}
29+
return propertyDescriptor;
30+
};
31+
}
32+
33+
export default Process;

main/global.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
declare module NodeJS {
2+
interface Global {
3+
ipcRenderer: any;
4+
}
5+
}

main/index.ts

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Native
2+
import { join } from 'path';
3+
import { format } from 'url';
4+
import { IpcMainEvent } from 'electron';
5+
import { spawn, exec, StdioOptions, SpawnOptions } from 'child_process';
6+
7+
// Packages
8+
import { BrowserWindow, app, ipcMain } from 'electron';
9+
import isDev from 'electron-is-dev';
10+
import prepareNext from 'electron-next';
11+
12+
// Other dependencies
13+
import { TerminalService } from './services/terminal.service';
14+
15+
const terminalService = new TerminalService();
16+
17+
// Prepare the renderer once the app is ready
18+
app.on('ready', async () => {
19+
await prepareNext('./renderer')
20+
21+
const mainWindow = new BrowserWindow({
22+
width: 1000,
23+
height: 600,
24+
webPreferences: {
25+
nodeIntegration: false,
26+
preload: join(__dirname, 'preload.js'),
27+
},
28+
})
29+
30+
if (isDev) {
31+
mainWindow.webContents.openDevTools();
32+
}
33+
34+
const url = isDev
35+
? 'http://localhost:8000/start'
36+
: format({
37+
pathname: join(__dirname, '../../renderer/start.html'),
38+
protocol: 'file:',
39+
slashes: true,
40+
})
41+
42+
mainWindow.loadURL(url)
43+
})
44+
45+
// Quit the app once all windows are closed
46+
app.on('window-all-closed', app.quit);
47+
48+
terminalService.ls();
49+
terminalService.mkdir(null);
50+
terminalService.rmdir(null);
51+
terminalService.pwd();
52+
terminalService.openDialog();
53+
terminalService.mvnInstall();
54+
terminalService.allCommands(null, null);
55+
56+
/* */
57+
58+
const eventHandler = (event: IpcMainEvent, ...eventArgs: any[]) => {
59+
const command = eventArgs[0];
60+
const cwd = eventArgs[1];
61+
console.log('received message:' + command)
62+
63+
if (!command) event.sender.send('terminal/powershell', '');
64+
const stdioOptions: StdioOptions = ['pipe', 'pipe', 'pipe'];
65+
66+
let options: SpawnOptions = { stdio: stdioOptions };
67+
options = cwd ? { ...options, cwd } : options
68+
const terminal = spawn(`powershell.exe`, [], options);
69+
70+
terminal.stdout.on('data', data => {
71+
console.log('sending data: ' + data.toString())
72+
event.sender.send('terminal/powershell', data.toString())
73+
});
74+
terminal.stderr.on('data', data => console.error(data.toString()));
75+
terminal.on('close', () => {
76+
console.log('closed stream')
77+
});
78+
79+
terminal.stdin.write(command + "\n")
80+
}
81+
82+
ipcMain.on('terminal/powershell', eventHandler);

main/preload.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { ipcRenderer } from 'electron'
2+
3+
4+
// Since we disabled nodeIntegration we can reintroduce
5+
// needed node functionality here
6+
process.once('loaded', () => {
7+
global.ipcRenderer = ipcRenderer;
8+
})

main/services/terminal.service.ts

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import { spawn, exec, ChildProcessWithoutNullStreams } from 'child_process';
2+
import Process from '../decorators/process';
3+
import { dialog } from 'electron';
4+
5+
interface Command {
6+
command: string,
7+
arguments: string[],
8+
}
9+
10+
export const CMD_LS: Command = { command: 'ls', arguments: ['-lh'] };
11+
12+
export const CMD_MKDIR: Command = { command: 'mkdir', arguments: [] };
13+
14+
export const CMD_RMDIR: Command = { command: 'rmdir', arguments: [] };
15+
16+
export const CMD_PWD: Command = { command: 'pwd', arguments: [] };
17+
18+
export const POWERSHELL: Command = { command: 'cmd.exe', arguments: ['mvn', '--help'] };
19+
20+
const MAX_BUFFER = 1024 * 500; /* 500 KB */
21+
22+
export class TerminalService {
23+
24+
private standardHandler(spawn: ChildProcessWithoutNullStreams): Promise<{}> {
25+
return new Promise((resolve, reject) => {
26+
let result = '';
27+
let error = ''
28+
spawn.stdout.on('data', data => { result += data });
29+
spawn.stderr.on('data', data => { error += data });
30+
spawn.on('close', () => {
31+
if (error) {
32+
reject(result + error)
33+
} else {
34+
resolve(result + error)
35+
}
36+
});
37+
spawn.stdin.end()
38+
});
39+
}
40+
41+
@Process('terminal/ls')
42+
async ls() {
43+
const ls = spawn(CMD_LS.command, CMD_LS.arguments)
44+
const result = await this.standardHandler(ls);
45+
46+
return result;
47+
}
48+
49+
@Process('terminal/mkdir')
50+
async mkdir(dirname: string) {
51+
const mkdir = spawn(CMD_MKDIR.command, [dirname]);
52+
try {
53+
const result = await this.standardHandler(mkdir);
54+
55+
return result;
56+
} catch (error) {
57+
return error;
58+
}
59+
}
60+
61+
@Process('terminal/rmdir')
62+
async rmdir(dirname: string) {
63+
const rmdir = spawn(CMD_RMDIR.command, [dirname]);
64+
try {
65+
const result = await this.standardHandler(rmdir);
66+
return result;
67+
68+
} catch (error) {
69+
return error;
70+
}
71+
}
72+
73+
@Process('terminal/pwd')
74+
async pwd() {
75+
const pwd = spawn(CMD_PWD.command, CMD_PWD.arguments);
76+
77+
try {
78+
const result = await this.standardHandler(pwd);
79+
return result;
80+
81+
} catch (error) {
82+
return error;
83+
}
84+
}
85+
86+
@Process('terminal/open-dialog')
87+
async openDialog() {
88+
const res = await dialog.showOpenDialog({ properties: ['openDirectory'] });
89+
return res;
90+
}
91+
92+
93+
@Process('terminal/mvn-install')
94+
async mvnInstall(cwd?: string) {
95+
const options = cwd ? { cwd, maxBuffer: MAX_BUFFER } : undefined
96+
let mvn = exec('mvn --help', options);
97+
98+
try {
99+
const result = await this.standardHandler(mvn);
100+
return result;
101+
102+
} catch (error) {
103+
return error;
104+
}
105+
}
106+
107+
@Process('terminal/all-commands')
108+
async allCommands(command: string, cwd?: string) {
109+
if (!command) return '';
110+
111+
const options = cwd ? { cwd, maxBuffer: MAX_BUFFER } : undefined
112+
let mvn = exec(command, options);
113+
114+
try {
115+
const result = await this.standardHandler(mvn);
116+
return new ReturnMessage(false, result);
117+
118+
} catch (error) {
119+
return new ReturnMessage(true, error);
120+
}
121+
}
122+
}
123+
124+
class ReturnMessage {
125+
error: boolean;
126+
body: any;
127+
128+
constructor(error: boolean, body: any) {
129+
this.error = error;
130+
this.body = body;
131+
}
132+
}

main/tsconfig.json

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es5",
4+
"allowJs": true,
5+
"skipLibCheck": true,
6+
"strict": false,
7+
"esModuleInterop": true,
8+
"module": "commonjs",
9+
"moduleResolution": "node",
10+
"resolveJsonModule": true,
11+
"isolatedModules": true,
12+
"outDir": "./out",
13+
"experimentalDecorators": true,
14+
},
15+
"exclude": [
16+
"node_modules"
17+
],
18+
"include": ["./**/*.ts"],
19+
}

0 commit comments

Comments
 (0)