@live-change/upload-service 0.2.22
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/definition.js +11 -0
- package/endpoint.js +117 -0
- package/index.js +8 -0
- package/model.js +119 -0
- package/package.json +30 -0
package/definition.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const app = require("@live-change/framework").app()
|
|
2
|
+
|
|
3
|
+
const relationsPlugin = require('@live-change/relations-plugin')
|
|
4
|
+
const userService = require('@live-change/user-service')
|
|
5
|
+
|
|
6
|
+
const definition = app.createServiceDefinition({
|
|
7
|
+
name: "upload",
|
|
8
|
+
use: [ relationsPlugin, userService ]
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
module.exports = definition
|
package/endpoint.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
const app = require("@live-change/framework").app()
|
|
2
|
+
const definition = require('./definition.js')
|
|
3
|
+
const config = definition.config
|
|
4
|
+
|
|
5
|
+
const progress = require('progress-stream')
|
|
6
|
+
|
|
7
|
+
const uploadsPath = config.uploadsPath || "./storage/uploads/"
|
|
8
|
+
|
|
9
|
+
const crypto = require("crypto")
|
|
10
|
+
const fs = require('fs')
|
|
11
|
+
|
|
12
|
+
const express = require("express")
|
|
13
|
+
|
|
14
|
+
fs.mkdirSync(uploadsPath, { recursive: true })
|
|
15
|
+
|
|
16
|
+
const { Upload } = require("./model.js")
|
|
17
|
+
|
|
18
|
+
async function setStreamInfo(info) {
|
|
19
|
+
console.dir(info)
|
|
20
|
+
if(info.progress.eta == Infinity) delete info.progress.eta
|
|
21
|
+
await Upload.update(info.id, { ...info, lastUpdate: new Date() })
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
definition.endpoint({
|
|
25
|
+
name: 'upload',
|
|
26
|
+
create() {
|
|
27
|
+
const expressApp = express()
|
|
28
|
+
expressApp.post('/:purpose/:fileName/:id', (req, res) => {
|
|
29
|
+
console.log("HANDLE UPLOAD!")
|
|
30
|
+
const { id, purpose, fileName } = req.params
|
|
31
|
+
console.log("HANDLE UPLOAD", req.params)
|
|
32
|
+
|
|
33
|
+
const internalName = id.replace(/[^a-zA-Z0-9\[\]@\.-]/g,"_")
|
|
34
|
+
const path = uploadsPath + internalName
|
|
35
|
+
|
|
36
|
+
app.emitEvents(definition.name, [
|
|
37
|
+
{
|
|
38
|
+
type: 'uploadStarted',
|
|
39
|
+
upload: id, purpose, fileName, internalName
|
|
40
|
+
}
|
|
41
|
+
])
|
|
42
|
+
|
|
43
|
+
const maxSize = config.maxSize || 100 * 1024 * 1024
|
|
44
|
+
|
|
45
|
+
const size = +req.header('Content-Length')
|
|
46
|
+
if(size == 0 || size > maxSize) {
|
|
47
|
+
req.resume()
|
|
48
|
+
res.status(400)
|
|
49
|
+
res.send("too_big")
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if(config.check) {
|
|
54
|
+
const error = config.check({ id, purpose, fileName, size })
|
|
55
|
+
if(error) {
|
|
56
|
+
req.resume()
|
|
57
|
+
res.status(error.status || 503)
|
|
58
|
+
res.send(error.message || error)
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
fs.access(path, fs.constants.F_OK, (err) => {
|
|
64
|
+
if(!err) {
|
|
65
|
+
req.resume()
|
|
66
|
+
res.status(400)
|
|
67
|
+
res.send("file_exists")
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const prog = progress({
|
|
72
|
+
length: size,
|
|
73
|
+
time: 600
|
|
74
|
+
})
|
|
75
|
+
req.pipe(prog)
|
|
76
|
+
const fileStream = fs.createWriteStream(path)
|
|
77
|
+
prog.pipe(fileStream)
|
|
78
|
+
|
|
79
|
+
setStreamInfo({
|
|
80
|
+
id, purpose, fileName, internalName,
|
|
81
|
+
progress: prog.progress(),
|
|
82
|
+
state: "uploading"
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
prog.on("progress", function(progress) {
|
|
86
|
+
setStreamInfo({
|
|
87
|
+
id, purpose, fileName, internalName,
|
|
88
|
+
progress,
|
|
89
|
+
state: progress.transferred >= size ? "done" : "uploading"
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
fileStream.on('finish', () => {
|
|
94
|
+
setStreamInfo({
|
|
95
|
+
id, purpose, fileName, internalName,
|
|
96
|
+
progress: prog.progress(),
|
|
97
|
+
state: "done"
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
app.emitEvents(definition.name, [
|
|
101
|
+
{ type: 'uploadFinished', upload: id }
|
|
102
|
+
])
|
|
103
|
+
|
|
104
|
+
res.status(200)
|
|
105
|
+
res.send("done")
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
expressApp.use('*', async (req, res) => {
|
|
110
|
+
res.writeHead(200, { "Content-Type": "text/plain" })
|
|
111
|
+
res.end("UPLOAD!")
|
|
112
|
+
})
|
|
113
|
+
return expressApp
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
module.exports = {}
|
package/index.js
ADDED
package/model.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
const definition = require('./definition.js')
|
|
2
|
+
|
|
3
|
+
const Upload = definition.model({
|
|
4
|
+
name: 'Upload',
|
|
5
|
+
properties: {
|
|
6
|
+
purpose: {
|
|
7
|
+
type: String
|
|
8
|
+
},
|
|
9
|
+
fileName: {
|
|
10
|
+
type: String
|
|
11
|
+
},
|
|
12
|
+
internalName: {
|
|
13
|
+
type: String
|
|
14
|
+
},
|
|
15
|
+
lastUpdate: {
|
|
16
|
+
type: Date
|
|
17
|
+
},
|
|
18
|
+
state: {
|
|
19
|
+
type: String
|
|
20
|
+
},
|
|
21
|
+
progress: {
|
|
22
|
+
type: Object,
|
|
23
|
+
props: {
|
|
24
|
+
percentage: {
|
|
25
|
+
type: Number
|
|
26
|
+
},
|
|
27
|
+
transferred: {
|
|
28
|
+
type: Number
|
|
29
|
+
},
|
|
30
|
+
length: {
|
|
31
|
+
type: Number
|
|
32
|
+
},
|
|
33
|
+
remaining: {
|
|
34
|
+
type: Number
|
|
35
|
+
},
|
|
36
|
+
eta: {
|
|
37
|
+
type: Number
|
|
38
|
+
},
|
|
39
|
+
runtime: {
|
|
40
|
+
type: Number
|
|
41
|
+
},
|
|
42
|
+
delta: {
|
|
43
|
+
type: Number
|
|
44
|
+
},
|
|
45
|
+
speed: {
|
|
46
|
+
type: Number
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
definition.event({
|
|
54
|
+
name: "uploadStarted",
|
|
55
|
+
async execute({ upload, purpose, fileName, internalName }) {
|
|
56
|
+
await Upload.update(upload, [
|
|
57
|
+
{ op: 'reverseMerge', value: { id: upload, purpose, fileName, internalName, state: 'started' } },
|
|
58
|
+
])
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
definition.event({
|
|
63
|
+
name: "uploadFailed",
|
|
64
|
+
async execute({ upload }) {
|
|
65
|
+
await Upload.update(upload, [
|
|
66
|
+
{ op: 'reverseMerge', value: { id: upload, state: 'failed' } },
|
|
67
|
+
])
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
definition.event({
|
|
72
|
+
name: "uploadFinished",
|
|
73
|
+
async execute({ upload }) {
|
|
74
|
+
await Upload.update(upload, [
|
|
75
|
+
{ op: 'reverseMerge', value: { id: upload, state: 'done' } },
|
|
76
|
+
])
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
definition.event({
|
|
81
|
+
name: "uploadUsed",
|
|
82
|
+
async execute({ upload }) {
|
|
83
|
+
await Upload.delete(upload)
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
definition.view({
|
|
88
|
+
name: 'upload',
|
|
89
|
+
properties: {
|
|
90
|
+
upload: {
|
|
91
|
+
type: Upload,
|
|
92
|
+
validation: ['nonEmpty']
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
returns: {
|
|
96
|
+
type: Upload
|
|
97
|
+
},
|
|
98
|
+
daoPath({ upload }, { client, context }) {
|
|
99
|
+
return Upload.path( upload )
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
definition.trigger({
|
|
104
|
+
name: "uploadUsed",
|
|
105
|
+
properties: {
|
|
106
|
+
upload: {
|
|
107
|
+
type: Upload
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
async execute({ upload }, context, emit) {
|
|
111
|
+
emit({
|
|
112
|
+
type: 'uploadUsed',
|
|
113
|
+
upload
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
module.exports = { Upload }
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@live-change/upload-service",
|
|
3
|
+
"version": "0.2.22",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "NODE_ENV=test tape tests/*"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/live-change/live-change-services.git"
|
|
12
|
+
},
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/live-change/live-change-services/issues"
|
|
16
|
+
},
|
|
17
|
+
"homepage": "https://github.com/live-change/live-change-services",
|
|
18
|
+
"author": {
|
|
19
|
+
"email": "michal@laszczewski.pl",
|
|
20
|
+
"name": "Michał Łaszczewski",
|
|
21
|
+
"url": "https://www.viamage.com/"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@live-change/framework": "0.6.5",
|
|
25
|
+
"@live-change/relations-plugin": "0.6.5",
|
|
26
|
+
"progress-stream": "^2.0.0",
|
|
27
|
+
"pluralize": "8.0.0"
|
|
28
|
+
},
|
|
29
|
+
"gitHead": "48b13d32478da797b31f73ed1d6f4271cd68b574"
|
|
30
|
+
}
|