harp 0.43.0 → 0.46.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/README.md +4 -3
- package/bin/harp +38 -7
- package/lib/index.js +53 -37
- package/lib/middleware.js +35 -2
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -69,7 +69,7 @@ Harp can be used as a library or as a command line utility.
|
|
|
69
69
|
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
Harp 〜 Static Web Server v0.
|
|
72
|
+
Harp 〜 Static Web Server v0.46.0
|
|
73
73
|
|
|
74
74
|
USAGE
|
|
75
75
|
harp <source> serves project locally
|
|
@@ -78,8 +78,9 @@ Harp can be used as a library or as a command line utility.
|
|
|
78
78
|
OPTIONS
|
|
79
79
|
-p, --port 9000 server port to listen on
|
|
80
80
|
-h, --host 0.0.0.0 server host to answer to
|
|
81
|
-
-
|
|
82
|
-
-
|
|
81
|
+
-s, --silent false supresses logs
|
|
82
|
+
-h, --help outputs this help message
|
|
83
|
+
-v, --version outputs version of harp
|
|
83
84
|
|
|
84
85
|
╭───────────────────────────────────────────────────────────────────────────────╮
|
|
85
86
|
│ │
|
package/bin/harp
CHANGED
|
@@ -19,9 +19,9 @@ var help = function(){
|
|
|
19
19
|
var box = (...args) => console.log(boxt(...args).split("\n").join("\n "));
|
|
20
20
|
|
|
21
21
|
log()
|
|
22
|
-
log("Harp".underline.blue, "〜".grey,
|
|
22
|
+
log("Harp".underline.blue, "〜".grey, pkg.description.brightYellow, "v".grey + pkg.version.grey)
|
|
23
23
|
log()
|
|
24
|
-
// log("
|
|
24
|
+
// log("Server | Generator | Bundler".grey)
|
|
25
25
|
// log()
|
|
26
26
|
log("USAGE".grey)
|
|
27
27
|
log(" harp <source> serves project locally")
|
|
@@ -30,10 +30,11 @@ var help = function(){
|
|
|
30
30
|
log("OPTIONS".grey)
|
|
31
31
|
log(" -p, --port " +"9000".blue +" server port to listen on")
|
|
32
32
|
log(" -h, --host " +"0.0.0.0".blue +" server host to answer to")
|
|
33
|
+
log(" -s, --silent " +"false".grey +" supresses logs")
|
|
33
34
|
// log(" -c, --cache " +"false".blue +" server memory cache")
|
|
34
35
|
// log(" -t, --pretty " +"false".blue +" server/compile keep whitespace")
|
|
35
|
-
log(" -h, --help
|
|
36
|
-
log(" -v, --version
|
|
36
|
+
log(" -h, --help outputs this help message")
|
|
37
|
+
log(" -v, --version outputs version of harp")
|
|
37
38
|
box(
|
|
38
39
|
`${'PROCESSING'.grey } ${'DATA'.grey }
|
|
39
40
|
${'.ejs -> .html' } ${'_data.json - directory data' }
|
|
@@ -73,21 +74,40 @@ if ((argv["_"].length === 0) || argv.help || argv.h) return help()
|
|
|
73
74
|
var harp = require("../")
|
|
74
75
|
|
|
75
76
|
|
|
77
|
+
var duration = function(d){
|
|
78
|
+
if (d[0] < 1){
|
|
79
|
+
var ms = d[1].toString().substring(0,3)
|
|
80
|
+
return + ms + "ms"
|
|
81
|
+
} else {
|
|
82
|
+
var ms = d[1].toString().substring(0,1)
|
|
83
|
+
return [d[0], ms].join(".") + "s"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
76
87
|
/**
|
|
77
88
|
* Server
|
|
78
89
|
*/
|
|
79
90
|
|
|
80
91
|
if (argv["_"].length === 1){
|
|
92
|
+
const serverStart = process.hrtime()
|
|
93
|
+
|
|
94
|
+
argv.log = !(argv.silent || argv.s)
|
|
81
95
|
var projectPath = path.resolve(process.cwd(), argv["_"][0])
|
|
82
96
|
var host = argv.host || '0.0.0.0'
|
|
83
97
|
var port = argv.port || 9000
|
|
98
|
+
|
|
84
99
|
var server = harp.server(projectPath, argv)
|
|
85
100
|
|
|
86
101
|
server.listen(port, host, function(error){
|
|
87
102
|
if (error) process.exit(1)
|
|
103
|
+
|
|
104
|
+
var serverReady = process.hrtime(serverStart)
|
|
105
|
+
|
|
88
106
|
box(
|
|
89
107
|
`${ 'Harp'.blue } ${ ('v' + pkg.version).grey}
|
|
90
|
-
${ ('http://localhost:' + port + "/").underline.cyan }
|
|
108
|
+
${ ('http://localhost:' + port + "/").underline.cyan }
|
|
109
|
+
${ duration(serverReady).grey }`, { align: "left", color: "grey", padding: 3 })
|
|
110
|
+
|
|
91
111
|
})
|
|
92
112
|
}
|
|
93
113
|
|
|
@@ -97,15 +117,26 @@ ${ ('http://localhost:' + port + "/").underline.cyan }`, { align: "left", color:
|
|
|
97
117
|
*/
|
|
98
118
|
|
|
99
119
|
if (argv["_"].length === 2){
|
|
120
|
+
argv.log = !(argv.silent || argv.s)
|
|
121
|
+
|
|
100
122
|
var projectPath = path.resolve(process.cwd(), argv["_"][0])
|
|
101
123
|
var buildPath = path.resolve(process.cwd(), argv["_"][1])
|
|
102
124
|
|
|
103
|
-
|
|
125
|
+
console.log()
|
|
126
|
+
console.log(" ", `Harp v${ pkg.version }`.yellow)
|
|
127
|
+
console.log(" ", "Generating Site & Bundling Assets...".blue)
|
|
128
|
+
if (argv.log) console.log()
|
|
129
|
+
|
|
130
|
+
harp.compile(projectPath, buildPath, argv, function(errors, output){
|
|
104
131
|
if(errors) {
|
|
105
132
|
console.log(JSON.stringify(errors, null, 2))
|
|
106
133
|
process.exit(1)
|
|
107
134
|
}
|
|
108
|
-
|
|
135
|
+
|
|
136
|
+
if (argv.log) console.log()
|
|
137
|
+
console.log(" ", "Done!".green, `(${ duration(output.stats.duration) })`.grey)
|
|
138
|
+
console.log()
|
|
109
139
|
})
|
|
140
|
+
|
|
110
141
|
}
|
|
111
142
|
|
package/lib/index.js
CHANGED
|
@@ -8,6 +8,7 @@ var helpers = require('./helpers')
|
|
|
8
8
|
var middleware = require('./middleware')
|
|
9
9
|
var pkg = require('../package.json')
|
|
10
10
|
var url = require("url")
|
|
11
|
+
var hrn = require("human-readable-numbers")
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
|
|
@@ -19,7 +20,14 @@ var url = require("url")
|
|
|
19
20
|
*/
|
|
20
21
|
|
|
21
22
|
exports.server = function(dirPath, options){
|
|
23
|
+
options = options || {}
|
|
24
|
+
|
|
22
25
|
var app = connect()
|
|
26
|
+
|
|
27
|
+
if (options.log || options.l){
|
|
28
|
+
app.use(middleware.setupLog)
|
|
29
|
+
}
|
|
30
|
+
|
|
23
31
|
app.use(middleware.regProjectFinder(dirPath))
|
|
24
32
|
app.use(middleware.setup)
|
|
25
33
|
app.use(middleware.basicAuth)
|
|
@@ -153,7 +161,17 @@ exports.middleware = middleware;
|
|
|
153
161
|
*
|
|
154
162
|
*/
|
|
155
163
|
|
|
156
|
-
exports.compile = function(projectPath, outputPath, callback){
|
|
164
|
+
exports.compile = function(projectPath, outputPath, options, callback){
|
|
165
|
+
if (!callback){
|
|
166
|
+
callback = options
|
|
167
|
+
options = { log: false }
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const compileStart = process.hrtime()
|
|
171
|
+
|
|
172
|
+
var stats = {
|
|
173
|
+
types: {}
|
|
174
|
+
}
|
|
157
175
|
|
|
158
176
|
/**
|
|
159
177
|
* Both projectPath and outputPath are optional
|
|
@@ -176,7 +194,7 @@ exports.compile = function(projectPath, outputPath, callback){
|
|
|
176
194
|
try{
|
|
177
195
|
outputPath = path.resolve(projectPath, outputPath)
|
|
178
196
|
var setup = helpers.setup(projectPath, "production")
|
|
179
|
-
var terra
|
|
197
|
+
var terra = terraform.root(setup.publicPath, setup.config.globals)
|
|
180
198
|
}catch(err){
|
|
181
199
|
return callback(err)
|
|
182
200
|
}
|
|
@@ -196,6 +214,13 @@ exports.compile = function(projectPath, outputPath, callback){
|
|
|
196
214
|
})
|
|
197
215
|
}
|
|
198
216
|
|
|
217
|
+
var toHuman = function(bytes){
|
|
218
|
+
var human = hrn.toHumanString(bytes)
|
|
219
|
+
var pattern = /\d+\D$/
|
|
220
|
+
if (pattern.test(human)) return human
|
|
221
|
+
return human + "B"
|
|
222
|
+
}
|
|
223
|
+
|
|
199
224
|
|
|
200
225
|
/**
|
|
201
226
|
* Compile and save file
|
|
@@ -204,40 +229,19 @@ exports.compile = function(projectPath, outputPath, callback){
|
|
|
204
229
|
var compileFile = function(file, done){
|
|
205
230
|
process.nextTick(function () {
|
|
206
231
|
terra.render(file, function(error, body){
|
|
207
|
-
if(error)
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
var results = esbuild.buildSync({
|
|
218
|
-
absWorkingDir: setup.publicPath,
|
|
219
|
-
entryPoints: [setup.publicPath + '/app.jsx'],
|
|
220
|
-
outfile: 'app.js',
|
|
221
|
-
bundle: true,
|
|
222
|
-
write: false,
|
|
223
|
-
plugins: [],
|
|
224
|
-
})
|
|
225
|
-
fs.writeFile([outputPath, "app.js"].join(path.sep), results.outputFiles[0]["text"], done)
|
|
226
|
-
}else if (file === "bundle.cjs"){
|
|
227
|
-
var results = esbuild.buildSync({
|
|
228
|
-
absWorkingDir: setup.publicPath,
|
|
229
|
-
entryPoints: [setup.publicPath + '/bundle.cjs'],
|
|
230
|
-
outfile: 'bundle.js',
|
|
231
|
-
bundle: true,
|
|
232
|
-
write: false,
|
|
233
|
-
plugins: [],
|
|
234
|
-
})
|
|
235
|
-
fs.writeFile([outputPath, "bundle.js"].join(path.sep), results.outputFiles[0]["text"], done)
|
|
236
|
-
} else {
|
|
237
|
-
done()
|
|
238
|
-
}
|
|
232
|
+
if(error) return done(error)
|
|
233
|
+
if(!body) return done()
|
|
234
|
+
var dest = path.resolve(outputPath, terraform.helpers.outputPath(file))
|
|
235
|
+
fs.mkdirp(path.dirname(dest), function(err){
|
|
236
|
+
var sizeInBytes = body.length
|
|
237
|
+
var sizeHuman = toHuman(sizeInBytes)
|
|
238
|
+
var sizePadded = sizeHuman.padStart(8, " ")
|
|
239
|
+
var filePath = `/${ terraform.helpers.outputPath(file) }`
|
|
240
|
+
if (options.log){
|
|
241
|
+
console.log(sizePadded.green, filePath)
|
|
239
242
|
}
|
|
240
|
-
|
|
243
|
+
fs.writeFile(dest, body, done)
|
|
244
|
+
})
|
|
241
245
|
})
|
|
242
246
|
})
|
|
243
247
|
}
|
|
@@ -253,7 +257,16 @@ exports.compile = function(projectPath, outputPath, callback){
|
|
|
253
257
|
if(!terraform.helpers.shouldIgnore(file) && [".jsx", ".jade", ".ejs", ".md", ".styl", ".less", ".scss", ".sass", ".coffee", ".cjs"].indexOf(ext) === -1){
|
|
254
258
|
var localPath = path.resolve(outputPath, file)
|
|
255
259
|
fs.mkdirp(path.dirname(localPath), function(err){
|
|
256
|
-
fs.
|
|
260
|
+
fs.stat(path.resolve(setup.publicPath, file), function(err, stats){
|
|
261
|
+
var sizeInBytes = stats.size
|
|
262
|
+
var sizeHuman = toHuman(sizeInBytes)
|
|
263
|
+
var sizePadded = sizeHuman.padStart(8, " ")
|
|
264
|
+
var filePath = `/${ file }`
|
|
265
|
+
if (options.log){
|
|
266
|
+
console.log(sizePadded.grey, filePath)
|
|
267
|
+
}
|
|
268
|
+
fs.copy(path.resolve(setup.publicPath, file), localPath, done)
|
|
269
|
+
})
|
|
257
270
|
})
|
|
258
271
|
}else{
|
|
259
272
|
done()
|
|
@@ -273,9 +286,12 @@ exports.compile = function(projectPath, outputPath, callback){
|
|
|
273
286
|
callback(err)
|
|
274
287
|
}else{
|
|
275
288
|
async.each(results, copyFile, function(err){
|
|
289
|
+
stats.duration = process.hrtime(compileStart)
|
|
290
|
+
|
|
276
291
|
setup.config['harp_version'] = pkg.version
|
|
277
292
|
delete setup.config.globals
|
|
278
|
-
|
|
293
|
+
setup.stats = stats
|
|
294
|
+
callback(null, setup)
|
|
279
295
|
})
|
|
280
296
|
}
|
|
281
297
|
})
|
package/lib/middleware.js
CHANGED
|
@@ -11,6 +11,41 @@ var utilsPause = require('pause')
|
|
|
11
11
|
var parse = require('parseurl')
|
|
12
12
|
var url = require('url')
|
|
13
13
|
var auth = require('basic-auth')
|
|
14
|
+
var hrn = require("human-readable-numbers")
|
|
15
|
+
var onFinished = require("on-finished")
|
|
16
|
+
|
|
17
|
+
var toHuman = function(bytes){
|
|
18
|
+
var human = hrn.toHumanString(bytes)
|
|
19
|
+
var pattern = /\d+\D$/
|
|
20
|
+
if (pattern.test(human)) return human
|
|
21
|
+
return human + "B"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var measureBody = function(contentLength){
|
|
25
|
+
if (!contentLength) return ""
|
|
26
|
+
return `(${ toHuman(contentLength) })`
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
exports.setupLog = function(req, rsp, next){
|
|
30
|
+
onFinished(rsp, function (err, rsp) {
|
|
31
|
+
var contentLength = null
|
|
32
|
+
try{
|
|
33
|
+
contentLength = parseInt(rsp._header.split("\n").find(h => h.includes("Content-Length")).split(" ")[1].split("\r")[0])
|
|
34
|
+
}catch(e){}
|
|
35
|
+
console.log(new Date(), rsp.req.method.green, rsp.statusCode, rsp.req.url, measureBody(contentLength).grey)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// var start = process.hrtime()
|
|
39
|
+
// var _end = rsp.end
|
|
40
|
+
|
|
41
|
+
// rsp.end = function(body){
|
|
42
|
+
// var stop = process.hrtime(start)
|
|
43
|
+
// console.log(new Date(), this.req.method.green, this.statusCode, this.req.url, measureBody(body).grey)
|
|
44
|
+
// return _end.call(this, body)
|
|
45
|
+
// }
|
|
46
|
+
|
|
47
|
+
return next()
|
|
48
|
+
}
|
|
14
49
|
|
|
15
50
|
exports.notMultihostURL = function(req, rsp, next){
|
|
16
51
|
var host = req.headers.host
|
|
@@ -447,7 +482,6 @@ exports.static = function(req, res, next) {
|
|
|
447
482
|
}
|
|
448
483
|
|
|
449
484
|
function directory() {
|
|
450
|
-
|
|
451
485
|
if (!redirect) return resume();
|
|
452
486
|
var pathname = url.parse(req.originalUrl).pathname;
|
|
453
487
|
res.statusCode = 301;
|
|
@@ -572,7 +606,6 @@ var poly = exports.poly = function(req, rsp, next){
|
|
|
572
606
|
|
|
573
607
|
exports.denySymlink = function(options){
|
|
574
608
|
options = options || {}
|
|
575
|
-
|
|
576
609
|
return function(req, rsp, next){
|
|
577
610
|
if (!options.hasOwnProperty("deny-symlinks")) return next()
|
|
578
611
|
if (options["deny-symlinks"] === false) return next()
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "harp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Static
|
|
3
|
+
"version": "0.46.0",
|
|
4
|
+
"description": "Static Web Server/Generator/Bundler",
|
|
5
5
|
"author": "Brock Whitten <brock@chloi.io>",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"Brock Whitten <brock@chloi.io>",
|
|
@@ -50,12 +50,14 @@
|
|
|
50
50
|
"connect": "3.7.0",
|
|
51
51
|
"envy-json": "0.2.1",
|
|
52
52
|
"fs-extra": "10.1.0",
|
|
53
|
+
"human-readable-numbers": "0.9.5",
|
|
53
54
|
"mime-types": "2.1.35",
|
|
54
55
|
"minimist": "1.2.6",
|
|
56
|
+
"on-finished": "^2.4.1",
|
|
55
57
|
"parseurl": "1.3.3",
|
|
56
58
|
"pause": "0.1.0",
|
|
57
59
|
"send": "0.18.0",
|
|
58
|
-
"terraform": "1.22.
|
|
60
|
+
"terraform": "1.22.1"
|
|
59
61
|
},
|
|
60
62
|
"devDependencies": {
|
|
61
63
|
"axios": "0.27.2",
|