Skip to content

Commit

Permalink
fix(ionic1): fix --consolelogs
Browse files Browse the repository at this point in the history
fixes #2548
  • Loading branch information
imhoffd committed Sep 6, 2017
1 parent c8b4d11 commit 5763a38
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 7 deletions.
73 changes: 73 additions & 0 deletions packages/@ionic/cli-utils/assets/dev-server/dev-server.js
@@ -0,0 +1,73 @@
window.Ionic = window.Ionic || {}; window.Ionic.DevServer = {
start: function(config) {
var self = this;

if (config.consolelogs) {
this.socket = new WebSocket('ws://' + window.location.hostname + ':' + String(config.wsPort));
this.msgQueue = [];

this.socket.onopen = function() {
self.socketReady = true;

self.socket.onclose = function() {
self.socketReady = false;
console.warn('Dev server closed');
};
};

this.patchConsole();
}
},

queueMessageSend: function(msg) {
this.msgQueue.push(msg);
this.drainMessageQueue();
},

drainMessageQueue: function() {
var msg;
while (msg = this.msgQueue.shift()) {
if (this.socketReady) {
try {
this.socket.send(JSON.stringify(msg));
} catch(e) {
if (!(e instanceof TypeError)) {
console.error('ws error: ' + e);
}
}
}
}
},

patchConsole: function() {
var self = this;

function _patchConsole(consoleType) {
console[consoleType] = (function() {
var orgConsole = console[consoleType];
return function() {
orgConsole.apply(console, arguments);
var msg = {
category: 'console',
type: consoleType,
data: []
};
for (var i = 0; i < arguments.length; i++) {
msg.data.push(arguments[i]);
}
if (msg.data.length) {
self.queueMessageSend(msg);
}
};
})();
}

// https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-console/#supported-methods
var consoleFns = ['log', 'error', 'exception', 'warn', 'info', 'debug', 'assert', 'dir', 'dirxml', 'time', 'timeEnd', 'table'];
for (var i in consoleFns) {
_patchConsole(consoleFns[i]);
}
},
};

Ionic.DevServer.start(Ionic.DevServerConfig || {});
4 changes: 3 additions & 1 deletion packages/@ionic/cli-utils/package.json
Expand Up @@ -64,7 +64,8 @@
"tiny-lr": "^1.0.5",
"tslib": "^1.7.1",
"uuid": "^3.0.1",
"wrap-ansi": "^3.0.1"
"wrap-ansi": "^3.0.1",
"ws": "^3.1.0"
},
"devDependencies": {
"@angular/compiler": "^4.3.3",
Expand All @@ -85,6 +86,7 @@
"@types/semver": "^5.3.33",
"@types/tar": "^1.0.29",
"@types/uuid": "^3.4.0",
"@types/ws": "^3.0.2",
"rxjs": "^5.4.2"
},
"jest": {
Expand Down
6 changes: 6 additions & 0 deletions packages/@ionic/cli-utils/src/definitions.ts
Expand Up @@ -716,3 +716,9 @@ export interface StarterTemplateType {
}

export type LiveReloadFunction = (changedFiles: string[]) => void;

export interface DevServerMessage {
category: 'console';
type: string;
data: any[];
}
8 changes: 8 additions & 0 deletions packages/@ionic/cli-utils/src/guards.ts
Expand Up @@ -10,6 +10,7 @@ import {
DeployChannel,
DeploySnapshot,
DeploySnapshotRequest,
DevServerMessage,
ExitCodeException,
ICommand,
INamespace,
Expand Down Expand Up @@ -269,3 +270,10 @@ export function isDeploySnapshotRequestResponse(r: APIResponse): r is Response<D
&& typeof res.data.presigned_post.url === 'string'
&& res.data.presigned_post.fields && typeof res.data.presigned_post.fields === 'object';
}

export function isDevServerMessage(m: any): m is DevServerMessage {
return m
&& typeof m.category === 'string'
&& typeof m.type === 'string'
&& m.data && typeof m.data.length === 'number';
}
Expand Up @@ -4,6 +4,35 @@ import { IonicEnvironment, LiveReloadFunction } from '../definitions';

import { BIND_ALL_ADDRESS } from './serve';

export const DEV_SERVER_PREFIX = '__ionic';

export function injectDevServerScript(content: any): any {
let contentStr = content.toString();
const devServerScript = getDevServerScript();

if (contentStr.indexOf(`/${DEV_SERVER_PREFIX}/dev-server.js`) > -1) {
// already added script
return content;
}

let match = contentStr.match(/<\/body>(?![\s\S]*<\/body>)/i);
if (!match) {
match = contentStr.match(/<\/html>(?![\s\S]*<\/html>)/i);
}
if (match) {
contentStr = contentStr.replace(match[0], `${devServerScript}\n${match[0]}`);
} else {
contentStr += devServerScript;
}

return contentStr;
}

function getDevServerScript() {
return ` <!-- Ionic Dev Server: Injected Dev Server Script -->\n` +
` <script src="${DEV_SERVER_PREFIX}/dev-server.js" async="" defer=""></script>`;
}

export async function createLiveReloadServer(env: IonicEnvironment, { port, wwwDir }: { port: number; wwwDir: string; }): Promise<LiveReloadFunction> {
const tinylr = await import('tiny-lr');
const lrserver = tinylr();
Expand All @@ -20,7 +49,7 @@ export async function createLiveReloadServer(env: IonicEnvironment, { port, wwwD
};
}

export function injectLiveReloadScript(content: any, host: string, port: number): any {
export function injectLiveReloadScript(content: any, host: string, port: number): string {
let contentStr = content.toString();
const liveReloadScript = getLiveReloadScript(host, port);

Expand All @@ -46,6 +75,7 @@ function getLiveReloadScript(host: string, port: number) {
if (host === BIND_ALL_ADDRESS) {
host = 'localhost';
}

const src = `//${host}:${port}/livereload.js?snipver=1`;

return ` <!-- Ionic Dev Server: Injected LiveReload Script -->\n` +
Expand Down
76 changes: 71 additions & 5 deletions packages/@ionic/cli-utils/src/lib/ionic1/serve.ts
@@ -1,10 +1,12 @@
import * as path from 'path';
import * as util from 'util';

import * as chalk from 'chalk';

import * as expressType from 'express';

import { IonicEnvironment, LiveReloadFunction, ServeDetails, ServeOptions } from '../../definitions';
import { IonicEnvironment, LiveReloadFunction, LogLevel, ServeDetails, ServeOptions } from '../../definitions';
import { isDevServerMessage } from '../../guards';

import { BIND_ALL_ADDRESS, IONIC_LAB_URL, LOCAL_ADDRESSES } from '../serve';
import { FatalException } from '../errors';
Expand Down Expand Up @@ -84,7 +86,17 @@ export async function serve({ env, options }: { env: IonicEnvironment; options:
throw new FatalException(`${chalk.green(options.address)} is not available--cannot bind.`);
}

env.log.info(`Starting server (address: ${chalk.bold(options.address)}, port: ${chalk.bold(String(options.port))}, livereload port: ${chalk.bold(String(options.livereloadPort))}) - Ctrl+C to cancel`);
const details = [
`address: ${chalk.bold(options.address)}`,
`port: ${chalk.bold(String(options.port))}`,
`dev server port: ${chalk.bold(String(options.notificationPort))}`,
];

if (options.livereload) {
details.push(`livereload port: ${chalk.bold(String(options.livereloadPort))}`);
}

env.log.info(`Starting server (${details.join(', ')}) - Ctrl+C to cancel`);

// Start up server
const settings = await setupServer(env, { externalIP, wwwDir, ...options });
Expand All @@ -102,7 +114,7 @@ async function setupServer(env: IonicEnvironment, options: ServeMetaOptions): Pr
let reloadfn: LiveReloadFunction | undefined;

if (options.livereload) {
const { createLiveReloadServer } = await import('../livereload');
const { createLiveReloadServer } = await import('../dev-server');
reloadfn = await createLiveReloadServer(env, { port: options.livereloadPort, wwwDir: options.wwwDir });
}

Expand Down Expand Up @@ -141,7 +153,10 @@ async function setupServer(env: IonicEnvironment, options: ServeMetaOptions): Pr
* Create HTTP server
*/
async function createHttpServer(env: IonicEnvironment, options: ServeMetaOptions): Promise<expressType.Application> {
const express = await import('express');
const { DEV_SERVER_PREFIX, injectDevServerScript, injectLiveReloadScript } = await import('../dev-server');
const [ WebSocket, express ] = await Promise.all([import('ws'), import('express')]);
const { LOGGER_STATUS_COLORS } = await import('../../lib/utils/logger');

const app = express();
app.listen(options.port, options.address);

Expand All @@ -153,8 +168,9 @@ async function createHttpServer(env: IonicEnvironment, options: ServeMetaOptions
const indexFileName = path.join(options.wwwDir, 'index.html');
let indexHtml = await fsReadFile(indexFileName, { encoding: 'utf8' });

indexHtml = injectDevServerScript(indexHtml);

if (options.livereload) {
const { injectLiveReloadScript } = await import('../livereload');
indexHtml = injectLiveReloadScript(indexHtml, options.externalAddressRequired ? options.externalIP : 'localhost', options.livereloadPort);
}

Expand Down Expand Up @@ -210,6 +226,56 @@ async function createHttpServer(env: IonicEnvironment, options: ServeMetaOptions
await setupProxies(env, app);
}

app.get(`/${DEV_SERVER_PREFIX}/dev-server.js`, async (req, res) => {
res.set('Content-Type', 'application/javascript');

const devServerConfig = {
consolelogs: options.consolelogs,
wsPort: options.notificationPort,
};

const devServerJs = await fsReadFile(path.join(__dirname, '..', '..', 'assets', 'dev-server', 'dev-server.js'), { encoding: 'utf8' });

res.send(
`window.Ionic = window.Ionic || {}; window.Ionic.DevServerConfig = ${JSON.stringify(devServerConfig)};\n\n` +
`${devServerJs}`.trim()
);
});

const wss = new WebSocket.Server({ port: options.notificationPort });

wss.on('connection', (ws) => {
ws.on('message', (data) => {
let msg;

try {
data = data.toString();
msg = JSON.parse(data);
} catch (e) {
env.log.error(`Error parsing JSON message from dev server: "${data}" ${chalk.red(e.stack ? e.stack : e)}`);
return;
}

if (!isDevServerMessage(msg)) {
const m = util.inspect(msg, { colors: chalk.enabled });
env.log.error(`Bad format in dev server message: ${m}`);
return;
}

if (msg.category === 'console') {
const status = LOGGER_STATUS_COLORS.get(<LogLevel>msg.type);

if (status) {
env.log.msg(`[${status('console.' + msg.type)}]: ${msg.data.join(' ')}`);
} else if (msg.type === 'log') {
env.log.msg(`[${chalk.gray('console.log')}]: ${msg.data.join(' ')}`);
} else {
env.log.msg(`[console]: ${msg.data.join(' ')}`);
}
}
});
});

return app;
}

Expand Down

0 comments on commit 5763a38

Please sign in to comment.