@stencil/dev-server 0.0.19-0 → 5.0.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{LICENSE → LICENSE.md} +12 -6
- package/dist/client/index.d.ts +126 -0
- package/dist/client/index.js +1050 -0
- package/dist/connector.html +27 -0
- package/dist/index.d.mts +54 -0
- package/dist/index.mjs +1277 -0
- package/dist/static/favicon.ico +0 -0
- package/dist/templates/directory-index.html +176 -0
- package/dist/templates/initial-load.html +147 -0
- package/dist/worker-thread.js +61 -0
- package/package.json +45 -50
- package/static/favicon.ico +0 -0
- package/templates/directory-index.html +176 -0
- package/templates/initial-load.html +147 -0
- package/README.md +0 -57
- package/assets/404.html +0 -14
- package/assets/__stencil-dev-server__/favicon.ico +0 -0
- package/assets/index.html +0 -39
- package/bin/stencil-dev-server +0 -16
- package/dist/definitions.js +0 -2
- package/dist/index.js +0 -275
- package/dist/middlewares.js +0 -106
- package/dist/promisify.js +0 -18
- package/dist/utils.js +0 -139
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html dir="ltr" lang="en">
|
|
3
|
+
<head data-tmpl="tmpl-initial-load">
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<script>
|
|
6
|
+
if ('serviceWorker' in navigator) {
|
|
7
|
+
navigator.serviceWorker.getRegistration().then(function(registration) {
|
|
8
|
+
if (registration) {
|
|
9
|
+
registration.unregister().then(function(hasUnregistered) {
|
|
10
|
+
if (hasUnregistered) {
|
|
11
|
+
console.log('unregistered service worker');
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}).catch(function(err) {
|
|
16
|
+
console.error(err.message || err);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
</script>
|
|
20
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
21
|
+
<meta http-equiv="x-ua-compatible" content="IE=Edge">
|
|
22
|
+
<title>Initializing First Build...</title>
|
|
23
|
+
<link rel="shortcut icon" type="image/x-icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMAAAADACAMAAABlApw1AAAAjVBMVEUAAAD8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjL8kjLn7xn3AAAALnRSTlMAsFBgAaDxfPpAdTMcD/fs47kDBhVXJQpvLNbInIiBRvSqIb+TZ2OOONxdzUxpgKSpAAAAA69JREFUeNrt3FtvskAQxvERFQXFioqnCkqth572+3+8947dN00TliF5ZpP53ZOAveg/OzCklFJKKaWUUkoppQTZm77cCGFo+jIhhG/TlwchJAvTk/GIAA6x6Um+JoDti+nJ644A5h+mJ8eMALKj6cnHnAB2r80NLJ4jf3Vz+cuWANZ5cwPTM/l7by6PZwQwGptGQf4q++dLCOHdNIbkb2IvjwjAvYEf8pe6j4/wYxopr/9SQih4BXa3l5eEcJ7a++c9/gkSQE8bcCWvXwcrAjjYADrxHv8KCbi3JasgD5fm8i9IAG1swMXzDv0X2wDaEED21dzA5UDeVoPm8uUbAayvvAI42YA7EIDzA5pv8lc6/UoAoxMv4CZuvyKUpnHn9VNBAG6B7XkBtCeEO6/AbvbyihAiXsB92svfCcA9wap4j19DAmgWs37AZCrnBKvu8vgX9AmWE3BZh/6L7QkWJIA2RxtwHQpml9sAQp9gXWbkbxz4CdYDfIK1qk1j3IV9fPgJFlNECJXhYfSfsBHkhBCKwEd452nYI7wncwQJP8GKTU+uO0I4D/uSkVJKqXAkA5nK9icoIi3nrU9QRHrZtj5BESmetT5BEantPCh7NTJFrUdgMg1bj8BkSv1HYJ8RmjMQKf1HYDdC+/R/IyQFzbD4AxH+CIyPPxCJoEdQ/IFIMgXNEPkDkd8jMLQs5wRcTXA1J+By/BGO+0ovYwQGU3kPRLJfIzCkCSfgpgmhpc5AxD/gIkLb8wKO0DTgoNyaGQQecNfQAy7TgGtHA04DLtyA24UecHngAVdrwIkJuAitU8DJ1Dbghkam9gEnU+uAWxiRjhsdoXagI1TPgKNyIBO+ZpRSSrW3HfblTAA9/juPDwTAfiMK9VG3PY/hwX7Ubc9j+AoCWNWGp+NSH4HflE2IgXUEGPI3TTfmN4ndv2kSsRUJvpUn4W1FShbYb5rc84ySAtzKs3W3IgW4lWfO24q0zsFbebIjaysSjbtt5RHzUf0DHHCrAW8gVYEDzl0LGYW4lefB24uYQgOOfwN7dMANeW/k3DkBJ2CrUNE54GRsFYIHnPNR+iPEgHPWKo5DDDhnrWKeBRhwzlrFeNtlq5CgtYqzAAPODaBzgAH331rFAAOOqsDXKjL3IqboN7ILJ4BCDDh3r3SIAfd0AijEgHP3So/8wQNuvjRBbxVij5A6Bpy8EZJnwIkbIfkFnLwRkm/ASRshXbwDTtYICRRwt7BHqEoppZRSSimllFLqD/8AOXJZHefotiIAAAAASUVORK5CYII=">
|
|
24
|
+
<style>
|
|
25
|
+
* {
|
|
26
|
+
box-sizing: border-box;
|
|
27
|
+
}
|
|
28
|
+
html {
|
|
29
|
+
color-scheme: dark light;
|
|
30
|
+
}
|
|
31
|
+
body {
|
|
32
|
+
position: absolute;
|
|
33
|
+
padding: 0;
|
|
34
|
+
margin: 0;
|
|
35
|
+
width: 100%;
|
|
36
|
+
height: 100%;
|
|
37
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
|
38
|
+
}
|
|
39
|
+
.toast {
|
|
40
|
+
position: absolute;
|
|
41
|
+
top: 12px;
|
|
42
|
+
right: 10px;
|
|
43
|
+
left: 10px;
|
|
44
|
+
margin: auto;
|
|
45
|
+
max-width: 700px;
|
|
46
|
+
border-radius: 3px;
|
|
47
|
+
background: rgba(0, 0, 0, .9);
|
|
48
|
+
transform: translate3d(0px, -60px, 0px);
|
|
49
|
+
transition: transform 75ms ease-out;
|
|
50
|
+
pointer-events: none;
|
|
51
|
+
}
|
|
52
|
+
.active {
|
|
53
|
+
transform: translate3d(0px, 0px, 0px);
|
|
54
|
+
}
|
|
55
|
+
.content {
|
|
56
|
+
display: flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
pointer-events: auto;
|
|
59
|
+
}
|
|
60
|
+
.message {
|
|
61
|
+
flex: 1;
|
|
62
|
+
padding: 15px;
|
|
63
|
+
font-size: 14px;
|
|
64
|
+
color: #fff;
|
|
65
|
+
}
|
|
66
|
+
.spinner {
|
|
67
|
+
position: relative;
|
|
68
|
+
display: inline-block;
|
|
69
|
+
width: 56px;
|
|
70
|
+
height: 28px;
|
|
71
|
+
}
|
|
72
|
+
svg:not(:root) {
|
|
73
|
+
overflow: hidden;
|
|
74
|
+
}
|
|
75
|
+
svg {
|
|
76
|
+
position: absolute;
|
|
77
|
+
top: 0;
|
|
78
|
+
left: 0;
|
|
79
|
+
width: 100%;
|
|
80
|
+
height: 100%;
|
|
81
|
+
transform: translateZ(0);
|
|
82
|
+
animation: rotate 600ms linear infinite;
|
|
83
|
+
}
|
|
84
|
+
@keyframes rotate {
|
|
85
|
+
0% {
|
|
86
|
+
transform: rotate(0deg);
|
|
87
|
+
}
|
|
88
|
+
100% {
|
|
89
|
+
transform: rotate(360deg);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
svg circle {
|
|
93
|
+
fill: transparent;
|
|
94
|
+
stroke: white;
|
|
95
|
+
stroke-width: 4px;
|
|
96
|
+
stroke-dasharray: 128px;
|
|
97
|
+
stroke-dashoffset: 82px;
|
|
98
|
+
}
|
|
99
|
+
.logs {
|
|
100
|
+
position: absolute;
|
|
101
|
+
top: 50px;
|
|
102
|
+
right: 10px;
|
|
103
|
+
left: 10px;
|
|
104
|
+
margin: auto;
|
|
105
|
+
max-width: 700px;
|
|
106
|
+
padding: 32px;
|
|
107
|
+
line-height: 1.5;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@media (prefers-color-scheme: dark) {
|
|
111
|
+
.toast {
|
|
112
|
+
background: rgb(49, 49, 49, .9);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
</style>
|
|
116
|
+
</head>
|
|
117
|
+
<body>
|
|
118
|
+
|
|
119
|
+
<div class="toast">
|
|
120
|
+
<div class="content">
|
|
121
|
+
<div class="message">Initializing First Build...</div>
|
|
122
|
+
<div class="spinner">
|
|
123
|
+
<svg viewBox="0 0 64 64"><circle transform="translate(32,32)" r="26"></circle></svg>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
<div class="logs">
|
|
129
|
+
<pre id="log-output"></pre>
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
<script>
|
|
133
|
+
setTimeout(function() {
|
|
134
|
+
document.querySelector('.toast').classList.add('active');
|
|
135
|
+
}, 100);
|
|
136
|
+
|
|
137
|
+
var logOutput = document.getElementById('log-output');
|
|
138
|
+
window.addEventListener('devserver:buildlog', function(ev) {
|
|
139
|
+
var buildLog = ev.detail;
|
|
140
|
+
if (buildLog && buildLog.messages) {
|
|
141
|
+
logOutput.innerText = buildLog.messages.join('\n');
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
</script>
|
|
145
|
+
|
|
146
|
+
</body>
|
|
147
|
+
</html>
|
package/README.md
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
[![npm][npm-badge]][npm-badge-url]
|
|
2
|
-
[![Build Status][circle-badge]][circle-badge-url]
|
|
3
|
-
|
|
4
|
-
# Stencil Dev Server
|
|
5
|
-
|
|
6
|
-
This is a very simple http-server with a filewatcher and livereload built in. This server
|
|
7
|
-
was built with the purpose of making it easy to develop stencil apps and components, but it will work
|
|
8
|
-
with about any dev workflow.
|
|
9
|
-
|
|
10
|
-
Just provide a directory.
|
|
11
|
-
|
|
12
|
-
```
|
|
13
|
-
stencil-dev-server --root public
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
There are a number of options available, but all have sane defaults.
|
|
17
|
-
|
|
18
|
-
- **--root**
|
|
19
|
-
- The directory that should be watched and served
|
|
20
|
-
- It defaults to the current directory that the command was executed from.
|
|
21
|
-
- **--watchGlob**
|
|
22
|
-
- The pattern of files to watch in the root directory for changes.
|
|
23
|
-
- The glob defaults to **\*\*/\*\***.
|
|
24
|
-
- **--address**
|
|
25
|
-
- The ip address that the server should listen to.
|
|
26
|
-
- Defaults to *0.0.0.0*. Point your browser to localhost.
|
|
27
|
-
- **--httpPort**
|
|
28
|
-
- The port that the http server should use. If the number provided is in use it will choose another.
|
|
29
|
-
- Defaults to *3333*.
|
|
30
|
-
- **--liveReloadPort**
|
|
31
|
-
- The port that the live-reload server should use. If the number provided is in use it will choose another.
|
|
32
|
-
- Defaults to *35729*.
|
|
33
|
-
- **--additionalJsScripts**
|
|
34
|
-
- A comma separated list of javascript files that you would like appended to all html page body tags. This allows you to expand the dev server to do additional behaviors.
|
|
35
|
-
- **--config**
|
|
36
|
-
- The path to a config file for the dev server. This allows you to keep a specific set of default parameters in a configuration file.
|
|
37
|
-
- Defaults to *./stencil.config.js*
|
|
38
|
-
- **--no-open**
|
|
39
|
-
- Disables automatically opening a browser.
|
|
40
|
-
|
|
41
|
-
Config File Structure
|
|
42
|
-
|
|
43
|
-
```js
|
|
44
|
-
exports.devServer = {
|
|
45
|
-
root: './',
|
|
46
|
-
additionalJSScripts: [
|
|
47
|
-
'http://localhost:3529/debug.js',
|
|
48
|
-
'./scripts/additionalDebug.js'
|
|
49
|
-
],
|
|
50
|
-
watchGlob: '**/*'
|
|
51
|
-
};
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
[npm-badge]: https://img.shields.io/npm/v/@stencil/dev-server.svg?style=flat-square
|
|
55
|
-
[npm-badge-url]: https://www.npmjs.com/package/@stencil/dev-server
|
|
56
|
-
[circle-badge]: https://circleci.com/gh/ionic-team/stencil-dev-server.svg?style=shield
|
|
57
|
-
[circle-badge-url]: https://circleci.com/gh/ionic-team/stencil-dev-server
|
package/assets/404.html
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset='utf-8'>
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
|
6
|
-
<title>404: Resource not found</title>
|
|
7
|
-
<style>{style}</style>
|
|
8
|
-
</head>
|
|
9
|
-
<body class="directory">
|
|
10
|
-
<div id="wrapper">
|
|
11
|
-
<h1><a href="/">~</a>{linked-path}</h1>
|
|
12
|
-
</div>
|
|
13
|
-
</body>
|
|
14
|
-
</html>
|
|
Binary file
|
package/assets/index.html
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset='utf-8'>
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
|
6
|
-
<title>listing directory {directory}</title>
|
|
7
|
-
<link rel="shortcut icon" href="/__stencil-dev-server__/favicon.ico" type="image/x-icon">
|
|
8
|
-
<style>
|
|
9
|
-
html {
|
|
10
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
|
11
|
-
color: #16161d;
|
|
12
|
-
}
|
|
13
|
-
body {
|
|
14
|
-
margin: 50px auto;
|
|
15
|
-
width: 60%;
|
|
16
|
-
}
|
|
17
|
-
span.denote {
|
|
18
|
-
font-weight: 100;
|
|
19
|
-
display: inline-block;
|
|
20
|
-
width: 8px;
|
|
21
|
-
}
|
|
22
|
-
h1 > a, h1 > a:visited {
|
|
23
|
-
text-decoration: none;
|
|
24
|
-
color: #5850ff;
|
|
25
|
-
}
|
|
26
|
-
a, a:visited {
|
|
27
|
-
color: #16161d;
|
|
28
|
-
display: inline-block;
|
|
29
|
-
margin: 2px 0 2px 6px;
|
|
30
|
-
}
|
|
31
|
-
</style>
|
|
32
|
-
</head>
|
|
33
|
-
<body class="directory">
|
|
34
|
-
<div id="wrapper">
|
|
35
|
-
<h1><a href="/">~</a>{linked-path}</h1>
|
|
36
|
-
{files}
|
|
37
|
-
</div>
|
|
38
|
-
</body>
|
|
39
|
-
</html>
|
package/bin/stencil-dev-server
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
#! /usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
process.title = 'stencil-dev-server';
|
|
5
|
-
process.on('unhandledRejection', function(r) { console.error(r) });
|
|
6
|
-
process.env.TINY_STATIC_LR_BIN = __filename;
|
|
7
|
-
|
|
8
|
-
let cmdArgs = process.argv;
|
|
9
|
-
const npmRunArgs = process.env.npm_config_argv;
|
|
10
|
-
if (npmRunArgs) {
|
|
11
|
-
cmdArgs = cmdArgs.concat(JSON.parse(npmRunArgs).original);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const server = require('../dist');
|
|
15
|
-
|
|
16
|
-
server.run(cmdArgs);
|
package/dist/definitions.js
DELETED
package/dist/index.js
DELETED
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
const path = require("path");
|
|
12
|
-
const url = require("url");
|
|
13
|
-
const tinylr = require("tiny-lr");
|
|
14
|
-
const ecstatic = require("ecstatic");
|
|
15
|
-
const opn = require("opn");
|
|
16
|
-
const http = require("http");
|
|
17
|
-
const https = require("https");
|
|
18
|
-
const chokidar_1 = require("chokidar");
|
|
19
|
-
const utils_1 = require("./utils");
|
|
20
|
-
const middlewares_1 = require("./middlewares");
|
|
21
|
-
const discover_1 = require("@ionic/discover");
|
|
22
|
-
const RESERVED_STENCIL_PATH = '/__stencil-dev-server__';
|
|
23
|
-
const optionInfo = {
|
|
24
|
-
root: {
|
|
25
|
-
default: 'www',
|
|
26
|
-
type: String
|
|
27
|
-
},
|
|
28
|
-
verbose: {
|
|
29
|
-
default: false,
|
|
30
|
-
type: Boolean
|
|
31
|
-
},
|
|
32
|
-
html5mode: {
|
|
33
|
-
default: true,
|
|
34
|
-
type: Boolean
|
|
35
|
-
},
|
|
36
|
-
watchGlob: {
|
|
37
|
-
default: '**/*',
|
|
38
|
-
type: String
|
|
39
|
-
},
|
|
40
|
-
address: {
|
|
41
|
-
default: '0.0.0.0',
|
|
42
|
-
type: String
|
|
43
|
-
},
|
|
44
|
-
httpPort: {
|
|
45
|
-
default: 3333,
|
|
46
|
-
type: Number
|
|
47
|
-
},
|
|
48
|
-
liveReloadPort: {
|
|
49
|
-
default: 35729,
|
|
50
|
-
type: Number
|
|
51
|
-
},
|
|
52
|
-
additionalJsScripts: {
|
|
53
|
-
default: '',
|
|
54
|
-
type: String
|
|
55
|
-
},
|
|
56
|
-
config: {
|
|
57
|
-
default: './stencil.config.js',
|
|
58
|
-
type: String
|
|
59
|
-
},
|
|
60
|
-
ssl: {
|
|
61
|
-
default: false,
|
|
62
|
-
type: Boolean
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
function run(argv) {
|
|
66
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
67
|
-
const cliDefaultedOptions = utils_1.parseOptions(optionInfo, argv);
|
|
68
|
-
cliDefaultedOptions.additionalJsScripts = cliDefaultedOptions.additionalJsScripts
|
|
69
|
-
.split(',')
|
|
70
|
-
.filter((name) => !!name);
|
|
71
|
-
const isVerbose = cliDefaultedOptions.verbose;
|
|
72
|
-
const configOptions = yield utils_1.parseConfigFile(process.cwd(), cliDefaultedOptions.config);
|
|
73
|
-
const options = Object.keys(cliDefaultedOptions).reduce((options, optionName) => {
|
|
74
|
-
const newValue = (configOptions[optionName] == null) ?
|
|
75
|
-
cliDefaultedOptions[optionName] :
|
|
76
|
-
configOptions[optionName];
|
|
77
|
-
options[optionName] = newValue;
|
|
78
|
-
return options;
|
|
79
|
-
}, {});
|
|
80
|
-
const [foundHttpPort, foundLiveReloadPort] = yield Promise.all([
|
|
81
|
-
utils_1.findClosestOpenPort(options.address, options.httpPort),
|
|
82
|
-
utils_1.findClosestOpenPort(options.address, options.liveReloadPort),
|
|
83
|
-
]);
|
|
84
|
-
const protocol = options.ssl ? 'https' : 'http';
|
|
85
|
-
log(isVerbose, `Will serve requests using : ${protocol}`);
|
|
86
|
-
const wwwRoot = path.resolve(options.root);
|
|
87
|
-
const browserUrl = getAddressForBrowser(options.address);
|
|
88
|
-
const [tinyLrServer, lrScriptLocation, emitLiveReloadUpdate] = yield createLiveReload(foundLiveReloadPort, options.address, wwwRoot, options.ssl);
|
|
89
|
-
const jsScriptLocations = options.additionalJsScripts
|
|
90
|
-
.map((filePath) => filePath.trim())
|
|
91
|
-
.concat(lrScriptLocation);
|
|
92
|
-
const fileWatcher = createFileWatcher(wwwRoot, options.watchGlob, emitLiveReloadUpdate, isVerbose);
|
|
93
|
-
log(isVerbose, `watching: ${wwwRoot} ${options.watchGlob}`);
|
|
94
|
-
const requestHandler = createHttpRequestHandler(wwwRoot, jsScriptLocations, options.html5mode);
|
|
95
|
-
const httpServer = options.ssl ? https.createServer(yield utils_1.getSSL(), requestHandler).listen(foundHttpPort)
|
|
96
|
-
: http.createServer(requestHandler).listen(foundHttpPort);
|
|
97
|
-
log(isVerbose, `listening on ${protocol}://${browserUrl}:${foundHttpPort}`);
|
|
98
|
-
log(isVerbose, `serving: ${wwwRoot}`);
|
|
99
|
-
if (argv.indexOf('--no-open') === -1) {
|
|
100
|
-
opn(`${protocol}://${browserUrl}:${foundHttpPort}`);
|
|
101
|
-
}
|
|
102
|
-
if (argv.indexOf('--broadcast') >= 0) {
|
|
103
|
-
log(isVerbose, 'publishing broadcast');
|
|
104
|
-
discover_1.newSilentPublisher('devapp', 'stencil-dev', foundHttpPort);
|
|
105
|
-
}
|
|
106
|
-
function close() {
|
|
107
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
108
|
-
fileWatcher.close();
|
|
109
|
-
tinyLrServer.close();
|
|
110
|
-
yield new Promise((resolve, reject) => {
|
|
111
|
-
httpServer.close((err) => {
|
|
112
|
-
if (err) {
|
|
113
|
-
reject(err);
|
|
114
|
-
}
|
|
115
|
-
resolve();
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
process.once('SIGINT', () => __awaiter(this, void 0, void 0, function* () {
|
|
121
|
-
yield close();
|
|
122
|
-
process.exit(0);
|
|
123
|
-
}));
|
|
124
|
-
return {
|
|
125
|
-
httpServer,
|
|
126
|
-
fileWatcher,
|
|
127
|
-
tinyLrServer,
|
|
128
|
-
close
|
|
129
|
-
};
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
exports.run = run;
|
|
133
|
-
function createHttpRequestHandler(wwwDir, jsScriptsList, html5mode) {
|
|
134
|
-
const jsScriptsMap = jsScriptsList.reduce((map, fileUrl) => {
|
|
135
|
-
const urlParts = url.parse(fileUrl);
|
|
136
|
-
if (urlParts.host) {
|
|
137
|
-
map[fileUrl] = fileUrl;
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
const baseFileName = path.basename(fileUrl);
|
|
141
|
-
map[path.join(RESERVED_STENCIL_PATH, 'js_includes', baseFileName)] = path.resolve(process.cwd(), fileUrl);
|
|
142
|
-
}
|
|
143
|
-
return map;
|
|
144
|
-
}, {});
|
|
145
|
-
const staticFileMiddleware = ecstatic({ root: wwwDir, cache: 0 });
|
|
146
|
-
const devServerFileMiddleware = ecstatic({ root: path.resolve(__dirname, '..', 'assets') });
|
|
147
|
-
const sendHtml = middlewares_1.serveHtml(wwwDir, Object.keys(jsScriptsMap));
|
|
148
|
-
const sendDirectoryContents = middlewares_1.serveDirContents(wwwDir);
|
|
149
|
-
return function (req, res) {
|
|
150
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
151
|
-
const reqPath = utils_1.getRequestedPath(req.url || '');
|
|
152
|
-
const filePath = utils_1.getFileFromPath(wwwDir, req.url || '');
|
|
153
|
-
let pathStat;
|
|
154
|
-
const serveIndexFile = (directory) => __awaiter(this, void 0, void 0, function* () {
|
|
155
|
-
const indexFilePath = path.join(directory, 'index.html');
|
|
156
|
-
let indexFileStat;
|
|
157
|
-
try {
|
|
158
|
-
indexFileStat = yield utils_1.fsStatPr(indexFilePath);
|
|
159
|
-
}
|
|
160
|
-
catch (err) { }
|
|
161
|
-
if (indexFileStat && indexFileStat.isFile()) {
|
|
162
|
-
return sendHtml(indexFilePath, req, res);
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
// If the file is a member of the scripts we autoload then serve it
|
|
166
|
-
if (jsScriptsMap[(req.url || '')]) {
|
|
167
|
-
return middlewares_1.sendFile('application/javascript', jsScriptsMap[(req.url || '')], req, res);
|
|
168
|
-
}
|
|
169
|
-
// If the request is to a static file that is part of this package
|
|
170
|
-
// then just send it on using the static file middleware
|
|
171
|
-
if ((req.url || '').startsWith(RESERVED_STENCIL_PATH)) {
|
|
172
|
-
return devServerFileMiddleware(req, res);
|
|
173
|
-
}
|
|
174
|
-
try {
|
|
175
|
-
pathStat = yield utils_1.fsStatPr(filePath);
|
|
176
|
-
}
|
|
177
|
-
catch (err) {
|
|
178
|
-
// File or path does not exist
|
|
179
|
-
if (err.code === 'ENOENT' || err.code === 'ENOTDIR') {
|
|
180
|
-
if (html5mode && (['.html', ''].indexOf(path.extname(filePath)) !== -1)) {
|
|
181
|
-
yield serveIndexFile(wwwDir);
|
|
182
|
-
if (res.finished) {
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
// The wwwDir index.html file does not exist.
|
|
187
|
-
return middlewares_1.sendError(404, res, { error: err });
|
|
188
|
-
}
|
|
189
|
-
// No access to the file.
|
|
190
|
-
if (err.code === 'EACCES') {
|
|
191
|
-
return middlewares_1.sendError(403, res, { error: err });
|
|
192
|
-
}
|
|
193
|
-
// Not sure what happened.
|
|
194
|
-
return middlewares_1.sendError(500, res, { error: err });
|
|
195
|
-
}
|
|
196
|
-
// If this is the first request then try to serve an index.html file in the root dir
|
|
197
|
-
if (reqPath === '/') {
|
|
198
|
-
yield serveIndexFile(wwwDir);
|
|
199
|
-
if (res.finished) {
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
// If the request is to a directory then serve the directory contents
|
|
204
|
-
if (pathStat.isDirectory()) {
|
|
205
|
-
yield serveIndexFile(filePath);
|
|
206
|
-
if (res.finished) {
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
// If the request is to a directory but does not end in slash then redirect to use a slash
|
|
210
|
-
if (!reqPath.endsWith('/')) {
|
|
211
|
-
res.writeHead(302, {
|
|
212
|
-
'location': reqPath + '/'
|
|
213
|
-
});
|
|
214
|
-
return res.end();
|
|
215
|
-
}
|
|
216
|
-
return yield sendDirectoryContents(filePath, req, res);
|
|
217
|
-
}
|
|
218
|
-
// If the request is to a file and it is an html file then use sendHtml to parse and send on
|
|
219
|
-
if (pathStat.isFile() && filePath.endsWith('.html')) {
|
|
220
|
-
return yield sendHtml(filePath, req, res);
|
|
221
|
-
}
|
|
222
|
-
if (pathStat.isFile()) {
|
|
223
|
-
return staticFileMiddleware(req, res);
|
|
224
|
-
}
|
|
225
|
-
// Not sure what you are requesting but lets just send an error
|
|
226
|
-
return middlewares_1.sendError(415, res, { error: 'Resource requested cannot be served.' });
|
|
227
|
-
});
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
let timeoutId;
|
|
231
|
-
function createFileWatcher(wwwDir, watchGlob, changeCb, isVerbose) {
|
|
232
|
-
const watcher = chokidar_1.watch(watchGlob, {
|
|
233
|
-
cwd: wwwDir,
|
|
234
|
-
ignored: /(^|[\/\\])\../ // Ignore dot files, ie .git
|
|
235
|
-
});
|
|
236
|
-
function fileChanged(filePath) {
|
|
237
|
-
clearTimeout(timeoutId);
|
|
238
|
-
timeoutId = setTimeout(() => {
|
|
239
|
-
log(isVerbose, `[${new Date().toTimeString().slice(0, 8)}] ${filePath} changed`);
|
|
240
|
-
changeCb([filePath]);
|
|
241
|
-
}, 50);
|
|
242
|
-
}
|
|
243
|
-
watcher.on('change', fileChanged);
|
|
244
|
-
watcher.on('error', (err) => {
|
|
245
|
-
log(true, err.toString());
|
|
246
|
-
});
|
|
247
|
-
return watcher;
|
|
248
|
-
}
|
|
249
|
-
function createLiveReload(port, address, wwwDir, ssl) {
|
|
250
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
251
|
-
const options = ssl ? yield utils_1.getSSL() : {};
|
|
252
|
-
const protocol = ssl ? 'https' : 'http';
|
|
253
|
-
const liveReloadServer = tinylr(options);
|
|
254
|
-
liveReloadServer.listen(port, address);
|
|
255
|
-
return [
|
|
256
|
-
liveReloadServer,
|
|
257
|
-
`${protocol}://${getAddressForBrowser(address)}:${port}/livereload.js?snipver=1`,
|
|
258
|
-
(changedFiles) => {
|
|
259
|
-
liveReloadServer.changed({
|
|
260
|
-
body: {
|
|
261
|
-
files: changedFiles.map(changedFile => ('/' + path.relative(wwwDir, changedFile)))
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
];
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
function getAddressForBrowser(ipAddress) {
|
|
269
|
-
return (ipAddress === '0.0.0.0') ? 'localhost' : ipAddress;
|
|
270
|
-
}
|
|
271
|
-
function log(test, ...args) {
|
|
272
|
-
if (test) {
|
|
273
|
-
console.log(...args);
|
|
274
|
-
}
|
|
275
|
-
}
|
package/dist/middlewares.js
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
const path = require("path");
|
|
12
|
-
const url = require("url");
|
|
13
|
-
const fs = require("fs");
|
|
14
|
-
const utils_1 = require("./utils");
|
|
15
|
-
function serveHtml(wwwDir, scriptLocations) {
|
|
16
|
-
return function (filePath, req, res) {
|
|
17
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
18
|
-
const indexHtml = yield utils_1.fsReadFilePr(filePath);
|
|
19
|
-
const appendString = scriptLocations.map(sl => `<script type="text/javascript" src="${sl}" charset="utf-8"></script>`).join('\n');
|
|
20
|
-
const htmlString = indexHtml.toString()
|
|
21
|
-
.replace(`</body>`, `${appendString}
|
|
22
|
-
</body>`);
|
|
23
|
-
res.writeHead(200, {
|
|
24
|
-
'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
|
|
25
|
-
'Expires': '0',
|
|
26
|
-
'Content-Type': 'text/html'
|
|
27
|
-
});
|
|
28
|
-
res.end(htmlString);
|
|
29
|
-
});
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
exports.serveHtml = serveHtml;
|
|
33
|
-
function serveDirContents(wwwDir) {
|
|
34
|
-
return function (dirPath, req, res) {
|
|
35
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
-
let files;
|
|
37
|
-
const dirUrl = req.url;
|
|
38
|
-
if (!dirUrl) {
|
|
39
|
-
return sendError(500, res, { err: 'Somthing is not right' });
|
|
40
|
-
}
|
|
41
|
-
try {
|
|
42
|
-
files = yield utils_1.fsReadDirPr(dirPath);
|
|
43
|
-
}
|
|
44
|
-
catch (err) {
|
|
45
|
-
return sendError(500, res, { err: err });
|
|
46
|
-
}
|
|
47
|
-
const templateSrc = yield utils_1.fsReadFilePr(path.join(__dirname, '..', 'assets', 'index.html'));
|
|
48
|
-
if (!templateSrc) {
|
|
49
|
-
throw new Error('wait, where is my template src.');
|
|
50
|
-
}
|
|
51
|
-
files = files
|
|
52
|
-
.filter((fileName) => '.' !== fileName[0]) // remove hidden files
|
|
53
|
-
.sort();
|
|
54
|
-
const fileStats = yield Promise.all(files.map((fileName) => utils_1.fsStatPr(path.join(dirPath, fileName))));
|
|
55
|
-
if (dirUrl !== '/') {
|
|
56
|
-
const dirStat = yield utils_1.fsStatPr(dirPath);
|
|
57
|
-
files.unshift('..');
|
|
58
|
-
fileStats.unshift(dirStat);
|
|
59
|
-
}
|
|
60
|
-
const fileHtml = files
|
|
61
|
-
.map((fileName, index) => {
|
|
62
|
-
const isDirectory = fileStats[index].isDirectory();
|
|
63
|
-
return (`<span class="denote">${isDirectory ? 'd' : '-'}</span> <a class="${isDirectory ? 'directory' : 'file'}" href="${url.resolve(dirUrl, fileName)}">${fileName}</a>`);
|
|
64
|
-
})
|
|
65
|
-
.join('<br/>\n');
|
|
66
|
-
const templateHtml = templateSrc.toString()
|
|
67
|
-
.replace('{directory}', dirPath)
|
|
68
|
-
.replace('{files}', fileHtml)
|
|
69
|
-
.replace('{linked-path}', dirUrl.replace(/\//g, ' / '));
|
|
70
|
-
res.writeHead(200, {
|
|
71
|
-
'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
|
|
72
|
-
'Expires': '0',
|
|
73
|
-
'Content-Type': 'text/html'
|
|
74
|
-
});
|
|
75
|
-
res.end(templateHtml);
|
|
76
|
-
});
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
exports.serveDirContents = serveDirContents;
|
|
80
|
-
function sendFile(contentType, filePath, req, res) {
|
|
81
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
82
|
-
const stat = yield utils_1.fsStatPr(filePath);
|
|
83
|
-
if (!stat.isFile()) {
|
|
84
|
-
return sendError(404, res, { error: 'File not found' });
|
|
85
|
-
}
|
|
86
|
-
res.writeHead(200, {
|
|
87
|
-
'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
|
|
88
|
-
'Expires': '0',
|
|
89
|
-
'Content-Type': contentType,
|
|
90
|
-
'Content-Length': stat.size
|
|
91
|
-
});
|
|
92
|
-
fs.createReadStream(filePath)
|
|
93
|
-
.pipe(res);
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
exports.sendFile = sendFile;
|
|
97
|
-
function sendError(httpStatus, res, content = {}) {
|
|
98
|
-
res.writeHead(httpStatus, {
|
|
99
|
-
'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0',
|
|
100
|
-
'Expires': '0',
|
|
101
|
-
'Content-Type': 'text/plain'
|
|
102
|
-
});
|
|
103
|
-
res.write(JSON.stringify(content, null, 2));
|
|
104
|
-
res.end();
|
|
105
|
-
}
|
|
106
|
-
exports.sendError = sendError;
|
package/dist/promisify.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
/**
|
|
4
|
-
* @example: const rReadFile = promisify<Buffer, string>(fs.readFile);
|
|
5
|
-
*
|
|
6
|
-
*/
|
|
7
|
-
exports.promisify = function (func) {
|
|
8
|
-
return (...args) => {
|
|
9
|
-
return new Promise((resolve, reject) => {
|
|
10
|
-
func(...args, (err, response) => {
|
|
11
|
-
if (err) {
|
|
12
|
-
return reject(err);
|
|
13
|
-
}
|
|
14
|
-
resolve(response);
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
};
|
|
18
|
-
};
|