Skip to content

Commit 213247f

Browse files
fix(scully): fix Could not connect to server (#178)
* fix(scully): fix Could not connect to server * improvement(small refactor): refactor server so it doesn't collash anymore added better support for handling multiple servers, added better error messages. * fix(startbackgroundserver): remove stray console.log Co-authored-by: Sander Elias <SanderElias@users.noreply.github.com>
1 parent d543a1f commit 213247f

13 files changed

Lines changed: 227 additions & 206 deletions

scully.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ require('./extraPlugin/voidPlugin');
66
exports.config = {
77
/** projectRoot is mandatory! */
88
projectRoot: './projects/sampleBlog/src/app',
9-
/** outFolder is where the static distribution files end up */
10-
outFolder: './dist/static',
9+
/** outDir is where the static distribution files end up */
10+
outDir: './dist/static',
1111

1212
routes: {
1313
'/demo/:id': {

scully/renderPlugins/puppeteerRenderPlugin.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
// tslint:disable: no-string-literal
22
// const puppeteer = require('puppeteer');
3+
import {readFileSync} from 'fs-extra';
4+
import {join} from 'path';
35
import {Browser, Page} from 'puppeteer';
46
import {HandledRoute} from '../routerPlugins/addOptionalRoutesPlugin';
5-
import {launchedBrowser} from './launchedBrowser';
67
import {scullyConfig} from '../utils/config';
78
import {logError, yellow} from '../utils/log';
9+
import {launchedBrowser} from './launchedBrowser';
810

911
export const puppeteerRender = async (route: HandledRoute): Promise<string> => {
12+
const {version} = JSON.parse(readFileSync(join(__dirname, '../package.json')).toString()) || '0.0.0';
1013
const path = `http://localhost:${scullyConfig.appPort}${route.route}`;
1114
let pageHtml: string;
1215
let browser: Browser;
@@ -25,6 +28,8 @@ export const puppeteerRender = async (route: HandledRoute): Promise<string> => {
2528
resolve();
2629
});
2730

31+
windowSet(page, 'scullyVersion', version);
32+
2833
/** Inject this into the running page, runs in browser*/
2934
await page.evaluateOnNewDocument(() => {
3035
/** set "running" mode */
@@ -34,6 +39,7 @@ export const puppeteerRender = async (route: HandledRoute): Promise<string> => {
3439
const d = document.createElement('script');
3540
d.innerHTML = `window['ScullyIO']='generated';`;
3641
document.head.appendChild(d);
42+
document.body.setAttribute('scully-version', window['scullyVersion']);
3743
window['onCustomEvent']();
3844
});
3945
});
@@ -63,3 +69,12 @@ export const puppeteerRender = async (route: HandledRoute): Promise<string> => {
6369
function waitForIt(milliSeconds) {
6470
return new Promise(resolve => setTimeout(() => resolve(), milliSeconds));
6571
}
72+
73+
const windowSet = (page, name, value) =>
74+
page.evaluateOnNewDocument(`
75+
Object.defineProperty(window, '${name}', {
76+
get() {
77+
return '${value}'
78+
}
79+
})
80+
`);

scully/scully.ts

Lines changed: 61 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1,180 +1,98 @@
11
#!/usr/bin/env node
2-
// the above line is needed for node bin running
3-
4-
import {spawn} from 'child_process';
5-
import {existsSync} from 'fs-extra';
2+
import {readFileSync} from 'fs-extra';
63
import {join} from 'path';
74
import * as yargs from 'yargs';
85
import './pluginManagement/systemPlugins';
96
import {routeContentRenderer} from './renderPlugins/routeContentRenderer';
7+
import {startBackgroundServer} from './startBackgroundServer';
108
import {loadConfig} from './utils/config';
11-
import {checkChangeAngular, existDistAngular, moveDistAngular} from './utils/fsAngular';
12-
import {checkStaticFolder} from './utils/fsFolder';
9+
import {moveDistAngular} from './utils/fsAngular';
1310
import {httpGetJson} from './utils/httpGetJson';
14-
import {RouteTypes, ScullyConfig} from './utils/interfacesandenums';
11+
import {RouteTypes} from './utils/interfacesandenums';
1512
import {isPortTaken} from './utils/isPortTaken';
1613
import {logError} from './utils/log';
1714
import {startScully} from './utils/startup';
18-
import {closeExpress, staticServer} from './utils/staticServer';
1915
import {waitForServerToBeAvailable} from './utils/waitForServerToBeAvailable';
16+
import {bootServe, isBuildThere, watchMode} from './watchMode';
2017

2118
/** the default of 10 is too shallow for generating pages. */
2219
require('events').defaultMaxListeners = 100;
2320

2421
let port;
2522
// tslint:disable-next-line:variable-name
26-
let _options = {};
23+
export let _options = {};
24+
25+
const {argv: options} = yargs
26+
.option('path', {
27+
alias: 'p',
28+
type: 'string',
29+
description: 'The path to generate',
30+
})
31+
.option('type', {
32+
alias: 't',
33+
type: 'string',
34+
description: 'The type to generate',
35+
})
36+
.option('port', {
37+
alias: 'p',
38+
type: 'number',
39+
description: 'The port to run on',
40+
})
41+
.option('folder', {
42+
type: 'string',
43+
description: 'home folder',
44+
});
45+
46+
if (process.argv.includes('version')) {
47+
const {version} = JSON.parse(readFileSync(join(__dirname, './package.json')).toString());
48+
console.log('version:', version);
49+
process.exit(0);
50+
}
2751

2852
(async () => {
53+
if (process.argv.includes('killServer')) {
54+
await httpGetJson('http://localhost:1864/killMe', {suppressErrors: true});
55+
process.exit(0);
56+
return;
57+
}
2958
/** make sure not to do something before the config is ready */
3059
const scullyConfig = await loadConfig;
3160
await isBuildThere(scullyConfig);
3261

33-
const {argv: options} = yargs
34-
.option('path', {
35-
alias: 'p',
36-
type: 'string',
37-
description: 'The path to generate',
38-
})
39-
.option('type', {
40-
alias: 't',
41-
type: 'string',
42-
description: 'The type to generate',
43-
})
44-
.option('port', {
45-
alias: 'p',
46-
type: 'number',
47-
description: 'The port to run on',
48-
});
49-
5062
if (process.argv.includes('serve')) {
51-
port = options.path;
52-
console.log('starting static server...');
53-
process.title = 'ScullyServer';
54-
checkChangeAngular(options.path);
55-
restartStaticServer();
63+
await bootServe(scullyConfig);
5664
} else {
5765
const folder = join(scullyConfig.homeFolder, scullyConfig.distFolder);
66+
/** copy in current buildfile */
67+
await moveDistAngular(folder, scullyConfig.outDir, {removeStaticDist: true, reset: false});
68+
69+
/** server already up and running? */
70+
const isTaken = await isPortTaken(scullyConfig.staticport);
71+
if (!isTaken) {
72+
startBackgroundServer(scullyConfig);
73+
} else {
74+
// debug only
75+
console.log(`Background servers already running.`);
76+
}
5877

59-
if (!existDistAngular(scullyConfig.homeFolder)) {
78+
if (!(await waitForServerToBeAvailable().catch(e => false))) {
79+
logError('Could not connect to server');
6080
process.exit(15);
6181
}
6282

63-
await moveDistAngular(folder, scullyConfig.outDir, {removeStaticDist: true, reset: false});
83+
console.log('servers available');
84+
await startScully();
6485

65-
if (options.path && options.type) {
66-
routeContentRenderer({
67-
route: options.path,
68-
type: (options.type as unknown) as RouteTypes,
69-
});
70-
if (process.argv.includes('watch')) {
71-
_options = options;
72-
watchMode();
73-
}
86+
if (process.argv.includes('watch')) {
87+
_options = options;
88+
watchMode();
7489
} else {
75-
/** server already up and running? */
76-
const isTaken = await isPortTaken(scullyConfig.staticport);
7790
if (!isTaken) {
78-
spawn('node', [join(scullyConfig.homeFolder, './node_modules/.bin/scully'), 'serve'], {
79-
detached: true,
80-
}).on('close', err => {
81-
if (+err > 0) {
82-
spawn(
83-
'node',
84-
[join(scullyConfig.homeFolder, './node_modules/@scullyio/scully/scully.js'), 'serve'],
85-
{
86-
detached: true,
87-
}
88-
).on('close', err2 => {
89-
if (+err2 > 0) {
90-
spawn('node', [join(scullyConfig.homeFolder, '/dist/scully/scully'), 'serve'], {
91-
detached: true,
92-
});
93-
}
94-
});
95-
}
96-
});
97-
98-
console.log('started servers in background');
99-
} else {
100-
// debug only
101-
console.log(`Background servers already running.`);
102-
}
103-
104-
if (!(await waitForServerToBeAvailable().catch(e => false))) {
105-
logError('Could not connect to server');
106-
process.exit(15);
91+
// kill serve ports
92+
await httpGetJson('http://localhost:1864/killMe', {suppressErrors: true});
10793
}
108-
109-
console.log('servers available');
110-
await startScully();
111-
112-
if (process.argv.includes('watch')) {
113-
_options = options;
114-
watchMode();
115-
} else {
116-
if (!isTaken) {
117-
// kill serve ports
118-
await httpGetJson('http://localhost:1864/killMe', {suppressErrors: true});
119-
}
120-
/** done, stop the program */
121-
process.exit(0);
122-
}
123-
}
124-
}
125-
})();
126-
127-
// TODO : we need rewrite this to observables for don't have memory leaks
128-
async function watchMode() {
129-
await checkStaticFolder();
130-
// g for generate and the q for quit
131-
checkForManualRestart();
132-
// @ts-ignore
133-
await checkChangeAngular(_options.path, false, true);
134-
}
135-
136-
export function checkForManualRestart() {
137-
const readline = require('readline').createInterface({
138-
input: process.stdin,
139-
output: process.stdout,
140-
});
141-
142-
readline.question(`Press g for manual regenerate, or q for close the server. \n`, command => {
143-
if (command.toLowerCase() === 'g') {
144-
startScully().then(() => checkForManualRestart());
145-
} else if (command.toLowerCase() === 'q') {
146-
readline.close();
94+
/** done, stop the program */
14795
process.exit(0);
148-
} else {
149-
readline.close();
150-
checkForManualRestart();
15196
}
152-
});
153-
}
154-
155-
export function startScullyWatchMode() {
156-
startScully();
157-
}
158-
159-
function startStaticServer() {
160-
staticServer();
161-
}
162-
163-
let restartTimer: NodeJS.Timer;
164-
export function restartStaticServer() {
165-
// tslint:disable-next-line: no-unused-expression
166-
restartTimer && clearTimeout(restartTimer);
167-
restartTimer = setTimeout(() => {
168-
closeExpress();
169-
startStaticServer();
170-
}, 500);
171-
}
172-
173-
export async function isBuildThere(config: ScullyConfig) {
174-
const dist = join(config.homeFolder, config.distFolder);
175-
if (existsSync(dist) && existsSync(join(dist, 'index.html'))) {
176-
return true;
17797
}
178-
logError(`Angular distribution files not found, run "ng build" first`);
179-
process.exit(15);
180-
}
98+
})();

scully/startBackgroundServer.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import {spawn} from 'child_process';
2+
import {existsSync} from 'fs-extra';
3+
import {join} from 'path';
4+
import {ScullyConfig} from './utils/interfacesandenums';
5+
import {logError, log, green} from './utils/log';
6+
7+
export function startBackgroundServer(scullyConfig: ScullyConfig) {
8+
const binary = ['/dist/scully/scully', '/node_modules/.bin/scully', '/node_modules/@scullyio/scully/scully']
9+
.map(p => join(scullyConfig.homeFolder, p + '.js'))
10+
.find(p => existsSync(p));
11+
12+
if (!binary) {
13+
logError('Could not find scully binaries');
14+
process.exit(15);
15+
return;
16+
}
17+
spawn('node', [binary, 'serve'], {
18+
detached: true,
19+
// stdio: 'inherit',
20+
}).on('close', err => {
21+
if (+err > 0) {
22+
logError('Problem starting background servers', err);
23+
process.exit(15);
24+
}
25+
});
26+
log(` ${green('☺')} Started servers in background`);
27+
}

scully/tsconfig.scully.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,5 @@
2727
]
2828
},
2929
"files": ["./index.ts", "scully.ts"],
30-
"exclude": ["bin/**/*","bin/**/*.d.ts", "bin/index.js"]
30+
"exclude": ["bin/**/*", "bin/**/*.d.ts", "bin/index.js", "../dist/**/*"]
3131
}

scully/utils/fsAngular.ts

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@ import {copy, remove} from 'fs-extra';
44
import {join} from 'path';
55
import {Observable} from 'rxjs';
66
import {debounceTime, filter, tap} from 'rxjs/operators';
7-
import {restartStaticServer, startScullyWatchMode} from '../scully';
7+
import {restartStaticServer, startScullyWatchMode} from '../watchMode';
88
import {green, log, logWarn, red} from './log';
99
import {scullyConfig} from './config';
1010
import {createFolderFor} from './createFolderFor';
1111

12-
1312
export async function checkChangeAngular(
1413
folder = join(scullyConfig.homeFolder, scullyConfig.distFolder) ||
1514
join(scullyConfig.homeFolder, './dist/browser'),
@@ -57,19 +56,6 @@ function watchFolder(folder): Observable<{eventType: string; fileName: string}>
5756
});
5857
}
5958

60-
export function existDistAngular(src) {
61-
try {
62-
if (!existsSync(src)) {
63-
log(`${red(`Build not found`)}.`);
64-
log(`Please build first your angular app`);
65-
return false;
66-
}
67-
return true;
68-
} catch (e) {
69-
return false;
70-
}
71-
}
72-
7359
// tslint:disable-next-line:no-shadowed-variable
7460
export async function moveDistAngular(src, dest, {reset = true, removeStaticDist = false}, watch = false) {
7561
try {

0 commit comments

Comments
 (0)