@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 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
@@ -0,0 +1,8 @@
1
+ const app = require("@live-change/framework").app()
2
+
3
+ const definition = require('./definition.js')
4
+
5
+ require('./endpoint.js')
6
+ require('./model.js')
7
+
8
+ module.exports = definition
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
+ }