Skip to content

Commit b49fb78

Browse files
committed
Initial commit
1 parent 19e90ff commit b49fb78

12 files changed

+5838
-0
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.git
2+
node_modules/
3+
iobroker-data/
4+
.devserver/

.npmignore

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.*
2+
node_modules/
3+
iobroker-data/
4+
.devserver/
5+
6+
# TypeScript sources and project configuration
7+
src/
8+
tsconfig.json
9+
tsconfig.*.json
10+
11+
# Sourcemaps
12+
*.map

.prettierignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package.json
2+
package-lock.json
3+
build/

.prettierrc.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module.exports = {
2+
semi: true,
3+
trailingComma: 'all',
4+
singleQuote: true,
5+
printWidth: 120,
6+
useTabs: false,
7+
tabWidth: 2,
8+
endOfLine: 'auto',
9+
};

.vscode/extensions.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
3+
}

.vscode/settings.json

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"typescript.tsdk": "node_modules/typescript/lib",
3+
"eslint.enable": true,
4+
"editor.formatOnSave": true,
5+
"editor.defaultFormatter": "esbenp.prettier-vscode",
6+
"[typescript]": {
7+
"editor.codeActionsOnSave": {
8+
"source.organizeImports": true
9+
}
10+
}
11+
}

build/index.js

+274
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
"use strict";
2+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3+
if (k2 === undefined) k2 = k;
4+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5+
}) : (function(o, m, k, k2) {
6+
if (k2 === undefined) k2 = k;
7+
o[k2] = m[k];
8+
}));
9+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10+
Object.defineProperty(o, "default", { enumerable: true, value: v });
11+
}) : function(o, v) {
12+
o["default"] = v;
13+
});
14+
var __importStar = (this && this.__importStar) || function (mod) {
15+
if (mod && mod.__esModule) return mod;
16+
var result = {};
17+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18+
__setModuleDefault(result, mod);
19+
return result;
20+
};
21+
var __importDefault = (this && this.__importDefault) || function (mod) {
22+
return (mod && mod.__esModule) ? mod : { "default": mod };
23+
};
24+
Object.defineProperty(exports, "__esModule", { value: true });
25+
const yargs = require("yargs/yargs");
26+
const child_process_1 = require("child_process");
27+
const express_1 = __importDefault(require("express"));
28+
const fs = __importStar(require("fs"));
29+
const http_proxy_middleware_1 = require("http-proxy-middleware");
30+
const os_1 = require("os");
31+
const path = __importStar(require("path"));
32+
const util_1 = require("util");
33+
const chalk = require("chalk");
34+
const mkdirAsync = util_1.promisify(fs.mkdir);
35+
const writeFileAsync = util_1.promisify(fs.writeFile);
36+
const TEMP_DIR_NAME = '.devserver';
37+
const CORE_MODULE = 'iobroker.js-controller';
38+
const IOBROKER_COMMAND = 'node node_modules/iobroker.js-controller/iobroker.js';
39+
const HIDDEN_ADMIN_PORT = 18881;
40+
const HIDDEN_BROWSER_SYNC_PORT = 18882;
41+
class DevServer {
42+
constructor() { }
43+
async run() {
44+
const argv = yargs(process.argv.slice(2)).options({
45+
adapter: { type: 'string', alias: 'a' },
46+
adminPort: { type: 'number', default: 8081, alias: 'p' },
47+
forceInstall: { type: 'boolean', hidden: true },
48+
root: { type: 'string', alias: 'r', hidden: true, default: '.' },
49+
}).argv;
50+
//console.log('argv', argv);
51+
const rootDir = path.resolve(argv.root);
52+
const jsControllerDir = path.join(rootDir, 'node_modules', CORE_MODULE);
53+
if (!argv.forceInstall && fs.existsSync(jsControllerDir)) {
54+
await this.runLocally(rootDir, argv.adapter || this.findAdapterName(path.join(rootDir, '..')), argv.adminPort);
55+
}
56+
else {
57+
const tempDir = path.join(rootDir, TEMP_DIR_NAME);
58+
await this.installAndLaunch(tempDir, argv.adapter || this.findAdapterName(rootDir), argv.adminPort);
59+
}
60+
}
61+
findAdapterName(dir) {
62+
const pkg = this.readPackageJson(dir);
63+
const adapterName = pkg.name.split('.')[1];
64+
console.log(chalk.gray(`Found adapter name: "${adapterName}"`));
65+
return adapterName;
66+
}
67+
readPackageJson(dir) {
68+
const json = fs.readFileSync(path.join(dir, 'package.json'), 'utf-8');
69+
return JSON.parse(json);
70+
}
71+
async runLocally(rootDir, adapter, adminPort) {
72+
console.log(chalk.gray(`Running inside ${rootDir}`));
73+
const proc = child_process_1.spawn('node', ['node_modules/iobroker.js-controller/controller.js'], {
74+
stdio: ['ignore', 'inherit', 'inherit'],
75+
cwd: rootDir,
76+
});
77+
proc.on('exit', (code) => {
78+
console.error(chalk.yellow(`ioBroker controller exited with code ${code}`));
79+
process.exit(-1);
80+
});
81+
process.on('SIGINT', () => {
82+
server.close();
83+
// do not kill this process when receiving SIGINT, but let all child processes exit first
84+
});
85+
this.startBrowserSync();
86+
const app = express_1.default();
87+
const adminPattern = `/adapter/${adapter}/**`;
88+
// browser-sync proxy
89+
const pathRewrite = {};
90+
pathRewrite[`^/adapter/${adapter}/`] = '/';
91+
app.use(http_proxy_middleware_1.createProxyMiddleware([adminPattern, '/browser-sync/**'], {
92+
target: `http://localhost:${HIDDEN_BROWSER_SYNC_PORT}`,
93+
// ws: true,
94+
pathRewrite,
95+
}));
96+
// admin proxy
97+
app.use(http_proxy_middleware_1.createProxyMiddleware(`!${adminPattern}`, { target: `http://localhost:${HIDDEN_ADMIN_PORT}`, ws: true }));
98+
const server = app.listen(adminPort);
99+
console.log(chalk.green(`Admin is now reachable under http://localhost:${adminPort}/`));
100+
}
101+
startBrowserSync() {
102+
var bs = require('browser-sync').create();
103+
/**
104+
* Run Browsersync with server config
105+
*/
106+
bs.init({
107+
server: { baseDir: '../admin', directory: true },
108+
port: HIDDEN_BROWSER_SYNC_PORT,
109+
open: false,
110+
ui: false,
111+
logLevel: 'silent',
112+
files: ['../admin/**'],
113+
plugins: [
114+
{
115+
module: 'bs-html-injector',
116+
options: {
117+
files: ['../admin/*.html'],
118+
},
119+
},
120+
],
121+
});
122+
}
123+
async installAndLaunch(tempDir, adapter, adminPort) {
124+
if (!fs.existsSync(path.join(tempDir, 'iobroker-data'))) {
125+
await this.install(tempDir, adapter);
126+
}
127+
console.log(chalk.gray(`Starting locally in ${tempDir}`));
128+
child_process_1.execSync(`node node_modules/iobroker-dev-server/build/index.js -a ${adapter} -p ${adminPort}`, {
129+
stdio: ['ignore', 'inherit', 'inherit'],
130+
cwd: tempDir,
131+
});
132+
}
133+
async install(tempDir, adapter) {
134+
console.log(chalk.blue(`Installing to ${tempDir}`));
135+
if (!fs.existsSync(tempDir)) {
136+
await mkdirAsync(tempDir);
137+
}
138+
// create the data directory
139+
const dataDir = path.join(tempDir, 'iobroker-data');
140+
if (!fs.existsSync(dataDir)) {
141+
await mkdirAsync(dataDir);
142+
}
143+
// create the configuration
144+
const config = {
145+
system: {
146+
memoryLimitMB: 0,
147+
hostname: `dev-${adapter}-${os_1.hostname()}`,
148+
instanceStartInterval: 2000,
149+
compact: false,
150+
allowShellCommands: false,
151+
memLimitWarn: 100,
152+
memLimitError: 50,
153+
},
154+
multihostService: {
155+
enabled: false,
156+
},
157+
network: {
158+
IPv4: true,
159+
IPv6: false,
160+
bindAddress: '127.0.0.1',
161+
useSystemNpm: true,
162+
},
163+
objects: {
164+
type: 'file',
165+
host: '127.0.0.1',
166+
port: 19901,
167+
noFileCache: false,
168+
maxQueue: 1000,
169+
connectTimeout: 2000,
170+
writeFileInterval: 5000,
171+
dataDir: '',
172+
options: {
173+
auth_pass: null,
174+
retry_max_delay: 5000,
175+
retry_max_count: 19,
176+
db: 0,
177+
family: 0,
178+
},
179+
},
180+
states: {
181+
type: 'file',
182+
host: '127.0.0.1',
183+
port: 19900,
184+
connectTimeout: 2000,
185+
writeFileInterval: 30000,
186+
dataDir: '',
187+
options: {
188+
auth_pass: null,
189+
retry_max_delay: 5000,
190+
retry_max_count: 19,
191+
db: 0,
192+
family: 0,
193+
},
194+
},
195+
log: {
196+
level: 'debug',
197+
maxDays: 7,
198+
noStdout: true,
199+
transport: {
200+
file1: {
201+
type: 'file',
202+
enabled: true,
203+
filename: 'log/iobroker',
204+
fileext: '.log',
205+
maxsize: null,
206+
maxFiles: null,
207+
},
208+
},
209+
},
210+
plugins: {},
211+
dataDir: '../../iobroker-data/',
212+
};
213+
await writeFileAsync(path.join(dataDir, 'iobroker.json'), JSON.stringify(config, null, 2));
214+
// create the package file
215+
const myPkg = this.readPackageJson(path.join(__dirname, '..'));
216+
const dependencies = {
217+
'iobroker.js-controller': 'latest',
218+
'iobroker.admin': 'latest',
219+
'iobroker.info': 'latest',
220+
};
221+
//dependencies[myPkg.name] = myPkg.version;
222+
const pkg = {
223+
name: 'unused__launcher',
224+
version: '1.0.0',
225+
private: true,
226+
dependencies,
227+
scripts: {
228+
devserver: 'iobroker-dev-server',
229+
},
230+
};
231+
await writeFileAsync(path.join(tempDir, 'package.json'), JSON.stringify(pkg, null, 2));
232+
console.log(chalk.blue('Installing everything...'));
233+
child_process_1.execSync('npm install --loglevel error --production', {
234+
stdio: 'inherit',
235+
cwd: tempDir,
236+
});
237+
this.uploadAndAddAdapter('admin', tempDir);
238+
this.uploadAndAddAdapter('info', tempDir);
239+
// reconfigure admin instance (only listen to local IP address)
240+
console.log(chalk.blue('Configure admin.0'));
241+
child_process_1.execSync(`${IOBROKER_COMMAND} set admin.0 --port ${HIDDEN_ADMIN_PORT} --bind 127.0.0.1`, {
242+
stdio: 'inherit',
243+
cwd: tempDir,
244+
});
245+
console.log(chalk.blue(`Link local iobroker.${adapter}`));
246+
child_process_1.execSync('npm link', {
247+
stdio: 'inherit',
248+
cwd: path.join(tempDir, '..'),
249+
});
250+
child_process_1.execSync(`npm link iobroker.${adapter}`, {
251+
stdio: 'inherit',
252+
cwd: tempDir,
253+
});
254+
this.uploadAndAddAdapter(adapter, tempDir);
255+
}
256+
uploadAndAddAdapter(name, cwd) {
257+
// upload the already installed adapter
258+
console.log(chalk.blue(`Upload iobroker.${name}`));
259+
child_process_1.execSync(`${IOBROKER_COMMAND} upload ${name}`, {
260+
stdio: 'inherit',
261+
cwd: cwd,
262+
});
263+
// create an instance
264+
console.log(chalk.blue(`Add ${name}.0`));
265+
child_process_1.execSync(`${IOBROKER_COMMAND} add ${name} 0`, {
266+
stdio: 'inherit',
267+
cwd: cwd,
268+
});
269+
}
270+
}
271+
(() => new DevServer().run().catch((e) => {
272+
console.error(chalk.red(e));
273+
process.exit(-1);
274+
}))();

0 commit comments

Comments
 (0)