Install scripts, build app with rollup & configurable mirror app id

This commit is contained in:
Benjamin Dobell
2018-09-20 02:42:50 +10:00
parent c4ed13fb0b
commit 131935507a
24 changed files with 15381 additions and 663 deletions

18
app/.babelrc Normal file
View File

@@ -0,0 +1,18 @@
{
"presets": [
[
"@babel/preset-env"
, {
"targets": {
"node": "current"
}
}
]
],
"plugins": [
"@babel/plugin-syntax-dynamic-import"
, "@babel/plugin-syntax-import-meta"
, "@babel/plugin-proposal-class-properties"
, "@babel/plugin-proposal-json-strings"
]
}

View File

@@ -1,3 +0,0 @@
#!/bin/sh
# TODO

3370
app/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,38 @@
{
"dependencies": {
"castv2": "^0.1.9",
"mdns-js": "^1.0.1"
}
"name": "fx_cast_bridge",
"license": "MIT",
"version": "0.1.0-alpha1",
"scripts": {
"build": "node scripts/build.js",
"install-manifest": "node scripts/install-manifest.js",
"start-debug": "node scripts/start-debug.js",
"start": "node dist/app.js"
},
"dependencies": {
"@babel/runtime": "^7.0.0",
"castv2": "^0.1.9",
"mdns-js": "^1.0.1",
"mkdirp": "^0.5.1"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/plugin-proposal-class-properties": "^7.0.0",
"@babel/plugin-proposal-json-strings": "^7.0.0",
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
"@babel/plugin-syntax-import-meta": "^7.0.0",
"@babel/plugin-transform-runtime": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"@babel/register": "^7.0.0",
"magic-string": "^0.25.0",
"minimist": "^1.2.0",
"rollup": "^0.66.0",
"rollup-plugin-babel": "^4.0.3",
"rollup-plugin-commonjs": "^9.1.3",
"rollup-plugin-json": "^3.1.0",
"rollup-plugin-node-builtins": "^2.1.2",
"rollup-plugin-node-resolve": "^3.4.0"
},
"optionalDependencies": {
"regedit": "^3.0.0"
}
}

View File

@@ -0,0 +1,34 @@
import MagicString from 'magic-string';
const MEMCPY_REQUIRE_STRING = 'require("memcpy")';
const REPLACEMENT_STRING = 'null';
// We're doing this because memcpy is an optional dependency of ByteBufferNB,
// but Rollup doesn't understand optional dependencies and tries to use it.
// We can't simply use memcpy, because it has native code for older versions of
// Node and no longer builds!
export default (variant) => {
let mainId = null;
return {
name: 'no-memcpy-plugin'
, transform: (code, id) => {
if (id.endsWith('ByteBufferNB.js')) {
const start = code.indexOf(MEMCPY_REQUIRE_STRING);
if (start >= 0) {
const magicString = new MagicString(code);
const end = start + MEMCPY_REQUIRE_STRING.length;
magicString.overwrite(start, end, REPLACEMENT_STRING);
return {
code: magicString.toString()
, map: magicString.generateMap()
};
}
}
return null;
}
}
}

View File

@@ -0,0 +1,56 @@
import { resolve } from 'path'
import babel from 'rollup-plugin-babel'
import builtins from 'rollup-plugin-node-builtins'
import commonjs from 'rollup-plugin-commonjs'
import json from 'rollup-plugin-json'
import nodeResolve from 'rollup-plugin-node-resolve'
import noMemcpy from './no-memcpy-plugin'
export default options => {
// TODO: Enabling this option presently doesn't work because castv2 proto
// files aren't bundled, can be fixed with a couple of plugins
const external = options.dependencies ? () => false : (id, parentId) => {
if (!parentId) {
return true;
}
return !!id.match(/^[^./].+$/)
|| resolve(parentId, '..', id).includes('/node_modules/');
};
return {
external
, input: './src/js/main.js'
, plugins: [
noMemcpy()
, babel({
exclude: [
'node_modules/**'
]
, runtimeHelpers: true
})
, json()
, builtins()
, nodeResolve({
module: true
, jsnext: true
, main: true
, browser: false
})
, commonjs({
// Protobuf detects itself running in Node by attempting to
// require fs, so we better allow it...
ignore: ['fs']
})
]
, output: [
{
file: resolve(__dirname, '../../dist/app/app.js')
, format: 'cjs'
, sourcemap: options.sourcemap || false
}
]
};
}

48
app/scripts/build.js Normal file
View File

@@ -0,0 +1,48 @@
const fs = require('fs');
const os = require('os');
const path = require('path');
require('@babel/register');
const argv = require('minimist')(process.argv.slice(2));
const rollup = require('rollup');
const config = require('../rollup/rollup.config').default;
const MANIFEST_NAME = 'fx_cast_bridge.json';
async function build() {
const {path: executablePath, platform, ...configOptions} = argv;
const {output: bundleOutputs, ...bundleOptions} = config(configOptions);
const bundle = await rollup.rollup(bundleOptions);
for (const output of bundleOutputs) {
await bundle.write(output);
fs.chmodSync(output.file, '755');
}
const targetPlatform = platform || os.type();
const launcherExt = targetPlatform.toLowerCase().startsWith('win')
? 'bat'
: 'sh';
const launcherName = `launcher.${launcherExt}`;
const launcherPath = path.join(__dirname, '../../dist', launcherName);
fs.copyFileSync(path.join(`src`, launcherName), launcherPath);
const manifest = {
...(JSON.parse(fs.readFileSync(`src/${MANIFEST_NAME}`, 'utf8')))
, path: (executablePath || path.resolve(launcherPath))
};
fs.writeFileSync(
path.join('../dist/app', MANIFEST_NAME)
, JSON.stringify(manifest, null, 4)
);
}
build().catch(e => {
console.log("Build failed", e);
process.exit(1);
});

View File

@@ -0,0 +1,69 @@
const fs = require('fs');
const os = require('os');
const path = require('path');
const argv = require('minimist')(process.argv.slice(2));
const mkdirpSync = require('mkdirp').sync;
const MANIFEST_NAME = 'fx_cast_bridge.json';
const MANIFEST_PATH = path.resolve(__dirname, '../../dist/app', MANIFEST_NAME);
const WIN_REGISTRY_KEY = 'fx_cast_bridge';
let destination = argv.destination;
switch (os.type()) {
case 'Darwin': {
if (!destination) {
const root = argv.root || process.env.HOME;
destination = path.resolve(
path.join(
root
, 'Library/Application Support/Mozilla/NativeMessagingHosts'
)
);
}
break;
}
case 'Linux': {
if (!destination) {
const root = argv.root || `${process.env.HOME}/.`;
destination = root.endsWith('/.')
? `${root}mozilla/native-messaging-hosts/`
: path.join(root, 'mozilla/native-messaging-hosts/');
}
break;
}
case 'Windows_NT': {
const regedit = require('regedit');
const destinationManifestPath = path.join(destination, MANIFEST_NAME)
|| MANIFEST_PATH;
regedit.putValue({
'HKEY_CURRENT_USER\\SOFTWARE\\Mozilla\\NativeMessagingHosts': {
[WIN_REGISTRY_KEY]: {
value: destinationManifestPath
, type: 'REG_DEFAULT'
}
}
});
break;
}
default:
console.error('Sorry, this installer does not yet support your OS');
process.exit(1);
}
if (destination) {
mkdirpSync(destination);
fs.copyFileSync(
MANIFEST_PATH
, path.join(destination, MANIFEST_NAME)
);
}

View File

@@ -0,0 +1,21 @@
require('@babel/register')({
presets: [
[
"@babel/preset-env"
, {
targets: {
node: "current"
}
}
]
]
, plugins: [
"@babel/plugin-transform-runtime"
, "@babel/plugin-syntax-dynamic-import"
, "@babel/plugin-syntax-import-meta"
, "@babel/plugin-proposal-class-properties"
, "@babel/plugin-proposal-json-strings"
]
});
require('../src/js/main');

View File

@@ -4,4 +4,4 @@
, "path": ""
, "type": "stdio"
, "allowed_extensions": [ "fx_cast@matt.tf" ]
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,107 +1,107 @@
"use strict";
const { Transform } = require("stream");
/**
* Takes a handler function that implements the transform
* and calls the transform callback.
*/
const response = (handler) => new Transform({
readableObjectMode: true
, writableObjectMode: true
, transform (chunk, encoding, callback) {
Promise.resolve(handler(chunk, callback))
.then(response => {
if (response) {
callback(null, response);
} else {
callback(null);
}
});
}
});
/**
* Takes input, decodes the message string, parses as JSON
* and outputs the parsed result.
*/
const decode = new Transform({
readableObjectMode: true
, transform (chunk, encoding, callback) {
// Setup persistent data
if (!this.hasOwnProperty("buf")
&& !this.hasOwnProperty("message_length")) {
this.buf = new Buffer(0);
this.message_length = null;
}
// Append next chunk to buffer
this.buf = Buffer.concat([ this.buf, chunk ]);
while (true) {
if (this.message_length === null) {
if (this.buf.length >= 4) {
// Read message length
this.message_length = this.buf.readUInt32LE(0);
// Offset buffer
this.buf = this.buf.slice(4);
continue;
}
} else {
if (this.buf.length >= this.message_length) {
const message = JSON.parse(this.buf.slice(
0, this.message_length));
this.push(message);
// Cleanup persistent data
this.buf = this.buf.slice(this.message_length);
this.message_length = null;
// Parse next message
continue;
}
}
// No complete messages left
callback();
break;
}
}
});
/**
* Takes input, encodes the message length and content and
* outputs the encoded result.
*/
const encode = new Transform({
writableObjectMode: true
, transform (chunk, encoding, callback) {
const message_length = new Buffer(4);
const message = new Buffer(JSON.stringify(chunk));
// Write message length
message_length.writeUInt32LE(message.length, 0);
// Output joined message length and content
callback(null, Buffer.concat([message_length, message]));
}
});
module.exports = {
response
, decode
, encode
};
"use strict";
const { Transform } = require("stream");
/**
* Takes a handler function that implements the transform
* and calls the transform callback.
*/
const response = (handler) => new Transform({
readableObjectMode: true
, writableObjectMode: true
, transform (chunk, encoding, callback) {
Promise.resolve(handler(chunk, callback))
.then(response => {
if (response) {
callback(null, response);
} else {
callback(null);
}
});
}
});
/**
* Takes input, decodes the message string, parses as JSON
* and outputs the parsed result.
*/
const decode = new Transform({
readableObjectMode: true
, transform (chunk, encoding, callback) {
// Setup persistent data
if (!this.hasOwnProperty("buf")
&& !this.hasOwnProperty("message_length")) {
this.buf = new Buffer(0);
this.message_length = null;
}
// Append next chunk to buffer
this.buf = Buffer.concat([ this.buf, chunk ]);
while (true) {
if (this.message_length === null) {
if (this.buf.length >= 4) {
// Read message length
this.message_length = this.buf.readUInt32LE(0);
// Offset buffer
this.buf = this.buf.slice(4);
continue;
}
} else {
if (this.buf.length >= this.message_length) {
const message = JSON.parse(this.buf.slice(
0, this.message_length));
this.push(message);
// Cleanup persistent data
this.buf = this.buf.slice(this.message_length);
this.message_length = null;
// Parse next message
continue;
}
}
// No complete messages left
callback();
break;
}
}
});
/**
* Takes input, encodes the message length and content and
* outputs the encoded result.
*/
const encode = new Transform({
writableObjectMode: true
, transform (chunk, encoding, callback) {
const message_length = new Buffer(4);
const message = new Buffer(JSON.stringify(chunk));
// Write message length
message_length.writeUInt32LE(message.length, 0);
// Output joined message length and content
callback(null, Buffer.concat([message_length, message]));
}
});
export {
response
, decode
, encode
};

View File

@@ -1,4 +1,4 @@
#!/bin/sh
AVAHI_COMPAT_NOWARN=1 node main.js
#!/usr/bin/env bash
BASEDIR=$(dirname $0)
PATH=/usr/local/bin:$PATH
AVAHI_COMPAT_NOWARN=1 node $BASEDIR/app.js

View File

@@ -1,3 +0,0 @@
#!/bin/sh
# TODO