tranfi 0.0.1

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/index.html ADDED
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width" />
6
+ <title>Tranfi</title>
7
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css">
8
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons|Material+Icons+Outlined">
9
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@6.5.95/css/materialdesignicons.min.css">
10
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.4/css/fontawesome.min.css">
11
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;900&display=swap" rel="stylesheet">
12
+ </head>
13
+ <body>
14
+ <div id="progress"></div>
15
+ <div id="tranfi-container"></div>
16
+ <script src="dist/bundle.js"></script>
17
+ </body>
18
+ </html>
package/logo.png ADDED
Binary file
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "tranfi",
3
+ "version": "0.0.1",
4
+ "description": "Stream-based tool for file processing",
5
+ "main": "src/main.js",
6
+ "scripts": {
7
+ "build-dev": "webpack --mode=development --progress --stats-children --env DEVELOPMENT",
8
+ "build": "webpack --mode=production --progress && webpack --mode=production --progress --env RUNTIME",
9
+ "watch": "nodemon --watch . --ignore dist --ext vue,js,css,html --exec 'npm run build-dev'",
10
+ "prepublishOnly": "npm run build",
11
+ "test": "jest test.js --detectOpenHandles",
12
+ "test-head": "HEADLESS=false npm test"
13
+ },
14
+ "author": "Anton Zemlyansky",
15
+ "license": "MIT",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/tranfi/tranfi"
19
+ },
20
+ "dependencies": {
21
+ "@jseeio/jsee": "^0.2.8",
22
+ "buffer": "^6.0.3",
23
+ "bulma": "^0.9.3",
24
+ "csv-parse": "^4.16.3",
25
+ "element-plus": "^1.2.0-beta.6",
26
+ "equal-vue": "^0.79.3",
27
+ "file-saver": "^2.0.2",
28
+ "filestream": "^5.0.0",
29
+ "filtrex": "^2.2.3",
30
+ "JSONStream": "^1.3.5",
31
+ "notyf": "^3.10.0",
32
+ "process": "^0.11.10",
33
+ "stream-browserify": "^3.0.0",
34
+ "stream-http": "^3.2.0",
35
+ "through2": "^4.0.2",
36
+ "unzip-stream": "^0.3.1",
37
+ "url": "^0.11.0",
38
+ "vue": "^3.2.23",
39
+ "vue-style-loader": "^4.1.3",
40
+ "vue3-json-viewer": "^1.0.4",
41
+ "vuedraggable": "^4.1.0",
42
+ "vuex": "^4.0.2"
43
+ },
44
+ "devDependencies": {
45
+ "@babel/core": "^7.16.5",
46
+ "@babel/plugin-transform-runtime": "^7.4.4",
47
+ "@babel/preset-env": "^7.16.5",
48
+ "babel-loader": "^8.2.3",
49
+ "css-loader": "^6.5.1",
50
+ "http-server": "^14.0.0",
51
+ "jest": "^27.4.5",
52
+ "jest-puppeteer": "^6.0.3",
53
+ "node-sass": "^7.0.0",
54
+ "nodemon": "^2.0.15",
55
+ "puppeteer": "^1.20.0",
56
+ "sass-loader": "^12.4.0",
57
+ "source-map-loader": "^3.0.0",
58
+ "style-loader": "^3.3.1",
59
+ "tape": "^4.9.1",
60
+ "terser-webpack-plugin": "^5.3.0",
61
+ "uglify-es": "^3.3.9",
62
+ "vue-loader": "^17.0.0",
63
+ "vue-template-compiler": "^2.6.14",
64
+ "webpack": "^5.65.0",
65
+ "webpack-cli": "^4.9.1",
66
+ "worker-loader": "^3.0.8"
67
+ }
68
+ }
package/src/app.css ADDED
@@ -0,0 +1,160 @@
1
+ html, body {
2
+ font-family: sans-serif;
3
+ overflow-x: auto;
4
+ overflow-y: auto;
5
+ }
6
+
7
+ .navbar-brand {
8
+ align-items: center;
9
+ justify-content: space-between;
10
+ }
11
+
12
+ .pipeline {
13
+ min-height: calc(100vh - 77px);
14
+ background: #f2f2f2;
15
+ }
16
+
17
+ .pipeline .card.active .card-content, .card.active .card-footer {
18
+ display: flex;
19
+ }
20
+
21
+ .pipeline .card .card-content, .card .card-footer {
22
+ display: none;
23
+ }
24
+
25
+ .pipeline .card .card-header-title {
26
+ cursor: move;
27
+ cursor: grab;
28
+ cursor: -moz-grab;
29
+ cursor: -webkit-grab;
30
+ }
31
+
32
+ .pipeline .card .card-header-title:active {
33
+ cursor: grabbing;
34
+ cursor: -moz-grabbing;
35
+ cursor: -webkit-grabbing;
36
+ }
37
+
38
+ .columns {
39
+ margin: 0;
40
+ }
41
+
42
+ .columns:last-child {
43
+ margin-bottom: 0;
44
+ }
45
+
46
+ .column {
47
+ padding: 10px;
48
+ }
49
+
50
+ .it-drawer-body--left {
51
+ top: 100px !important;
52
+ height: calc(100% - 120px) !important;
53
+ }
54
+
55
+ .mainbar-left {
56
+ padding-top: 12px;
57
+ background-color: #222326;
58
+ }
59
+
60
+ .mainbar-right {
61
+ background-color: #2b2e35;
62
+ align-items: stretch;
63
+ display: flex;
64
+ }
65
+
66
+ .mainbar-right .navbar-start{
67
+ justify-content: flex-start;
68
+ margin-right: auto;
69
+ align-items: stretch;
70
+ display: flex;
71
+ }
72
+
73
+ .mainbar-right .navbar-item {
74
+ align-items: center;
75
+ display: flex;
76
+ color: white;
77
+ }
78
+
79
+ .mainbar-right input {
80
+ background: #222326;
81
+ border: none;
82
+ color: #c3c6ce;
83
+ }
84
+
85
+ .mainbar-right input::placeholder {
86
+ color: #6b6f79;
87
+ }
88
+
89
+
90
+ .mainbar-title {
91
+ font-weight: 500;
92
+ font-size: 16px;
93
+ }
94
+
95
+ .navbar-item {
96
+ padding: .5rem 0.4rem;
97
+ }
98
+
99
+ .breadcrumb {
100
+ margin: 6px auto 13px !important;
101
+ opacity: 0.5;
102
+ font-size: 12px;
103
+ }
104
+
105
+ .preview-panel {
106
+ max-width: 400px;
107
+ margin: 25px auto;
108
+ }
109
+
110
+ /*
111
+ .mainbar-title:before {
112
+ content: '> ';
113
+ opacity: 0.4;
114
+ margin-right: 10px;
115
+ display: inline-block;
116
+ font-weight: 200;
117
+ }
118
+ */
119
+
120
+ hr {
121
+ height: 1px;
122
+ margin: 0.2rem 0;
123
+ }
124
+
125
+ .preview-button {
126
+ min-width: 100px;
127
+ }
128
+
129
+ .preview-content pre {
130
+ background: none;
131
+ font-size: 12px;
132
+ }
133
+
134
+ #progress {
135
+ background: #00d1b2;
136
+ position: fixed;
137
+ top: 0;
138
+ left: 0;
139
+ height: 3px;
140
+ z-index: 1000;
141
+ }
142
+
143
+ @media screen and (max-width:768px) {
144
+ .mainbar-left {
145
+ display: none;
146
+ }
147
+
148
+ .desktop-only {
149
+ display: none;
150
+ }
151
+
152
+ .preview-button {
153
+ min-width: 0px;
154
+ }
155
+
156
+ .button.mobile-flexible .icon {
157
+ margin-left: calc(-.5em - 1px) !important;
158
+ margin-right: calc(-.5em - 1px) !important;
159
+ }
160
+ }
package/src/app.js ADDED
@@ -0,0 +1,203 @@
1
+ const through2 = require('through2')
2
+ const transforms = require('./transforms')
3
+
4
+ async function run (pipeline, isBatch) {
5
+ let readStream
6
+ let writeStream
7
+
8
+ for (const transform of pipeline) {
9
+ // Convert inputs to params object
10
+ const params = {}
11
+ transform.inputs.forEach(i => {
12
+ params[i.name] = i.type === 'file' ? i.file : i.value
13
+ })
14
+ // Init stream
15
+ let nextStream = await transforms[transform.name].initStream(params)
16
+ if (typeof readStream === 'undefined') {
17
+ readStream = writeStream = nextStream
18
+ if ('File' in params) {
19
+ let size = params['File'].size
20
+ let progressBytes = 0
21
+ let progressBar = document.getElementById('progress')
22
+ progressBar.style.display = 'initial'
23
+ const progressStream = through2(function (chunk, enc, callback) {
24
+ progressBytes += chunk.length
25
+ let progressPercents = ((progressBytes / size) * 100).toFixed(1)
26
+ progressBar.style.width = progressPercents + '%'
27
+ this.push(chunk)
28
+ callback()
29
+ })
30
+ writeStream = writeStream.pipe(progressStream)
31
+ }
32
+ } else {
33
+ writeStream = writeStream.pipe(nextStream) //, {end: false})
34
+ }
35
+ }
36
+
37
+ writeStream.on('data', (piece) => {
38
+ if (isBatch) {
39
+ console.log('Pausing stream')
40
+ readStream.pause()
41
+ }
42
+ })
43
+
44
+ return {readStream, writeStream}
45
+ }
46
+
47
+ function resetInputs (inputs) {
48
+ inputs.forEach(input => {
49
+ if (input.default) {
50
+ input.value = input.default
51
+ } else {
52
+ switch (input.type) {
53
+ case 'int':
54
+ case 'float':
55
+ case 'number':
56
+ input.value = 0
57
+ break
58
+ case 'string':
59
+ case 'text':
60
+ input.value = ''
61
+ break
62
+ case 'color':
63
+ input.value = '#000000'
64
+ break
65
+ case 'categorical':
66
+ case 'select':
67
+ input.value = input.options ? input.options[0] : ''
68
+ break
69
+ case 'bool':
70
+ case 'checkbox':
71
+ input.value = false
72
+ break
73
+ case 'file':
74
+ input.file = null
75
+ input.value = ''
76
+ break
77
+ case 'group':
78
+ resetInputs(input.elements)
79
+ break
80
+ default:
81
+ input.value = ''
82
+ }
83
+ }
84
+ })
85
+ }
86
+
87
+ let readStream = null
88
+ let writeStream = null
89
+ export default {
90
+ components: {
91
+ // draggable,
92
+ // 'vue-input': bulmaInput
93
+ },
94
+ data() {
95
+ return {
96
+ drag: false,
97
+ preview: false,
98
+ loadedAllData: true,
99
+ title: '',
100
+ showResults: false,
101
+ modalAddTransforms: false,
102
+ counter: 0,
103
+ transforms: transforms,
104
+ pipeline: []
105
+ }
106
+ },
107
+ methods: {
108
+ getTransformIndex (t) {
109
+ return this.pipeline.findIndex((el) => el.id === t.id)
110
+ },
111
+ cloneTransform (t) {
112
+ const i = this.getTransformIndex(t)
113
+ const newTransform = JSON.parse(JSON.stringify(t))
114
+ newTransform.id = this.counter
115
+ this.counter += 1
116
+ this.pipeline.splice(i + 1, 0, newTransform)
117
+ },
118
+ resetTransform (t) {
119
+ resetInputs(t.inputs)
120
+ },
121
+ deleteTransform (t) {
122
+ const i = this.getTransformIndex(t)
123
+ this.pipeline.splice(i, 1)
124
+ },
125
+ showLoading (p) {
126
+ this.$Loading.update(p)
127
+ },
128
+ addTransform (Transform) {
129
+ const newTransform = new Transform(this.counter)
130
+ this.resetTransform(newTransform)
131
+ this.pipeline.push(newTransform)
132
+ this.modalAddTransforms = false
133
+ this.counter += 1
134
+ },
135
+ showMessage (type) {
136
+ switch (type) {
137
+ case 'success':
138
+ this.$Message.success({ text: 'Success message!' })
139
+ break
140
+ case 'danger':
141
+ this.$Message.danger({ text: 'Danger message!' })
142
+ break
143
+ case 'warning':
144
+ this.$Message.warning({ text: 'Success message!' })
145
+ break
146
+ default:
147
+ this.$Message({ text: 'Primary message!' })
148
+ break
149
+ }
150
+ },
151
+ run (isBatch) {
152
+ run(this.pipeline, isBatch).then(streams => {
153
+ this.loadedAllData = false
154
+ readStream = streams.readStream
155
+ readStream.on('end', function () {
156
+ this.loadedAllData = true
157
+ console.log('End of stream')
158
+ let progressBar = document.getElementById('progress')
159
+ progressBar.style.display = 'none'
160
+ })
161
+ })
162
+ },
163
+ runMore () {
164
+ readStream.resume()
165
+ }
166
+ },
167
+ watch: {
168
+ // pipeline: {
169
+ // handler (pipeline) {
170
+ // this.env.data.inputs = pipeline.map((v, i) => ({type: 'int', name: v.name}))
171
+ // },
172
+ // deep: true
173
+ // }
174
+ },
175
+ computed: {
176
+ // a computed getter
177
+ displayInputs() {
178
+ const inputs = []
179
+ this.pipeline.forEach(transform => {
180
+ transform.displayInputs.forEach(i => {
181
+ inputs.push(transform.inputs[i])
182
+ })
183
+ })
184
+ return inputs
185
+ }
186
+ },
187
+ mounted () {
188
+ // const tranfi = this
189
+ // this.env = new JSEE({
190
+ // model: {
191
+ // code: function run (params) {
192
+ // tranfi.run(params)
193
+ // },
194
+ // worker: false
195
+ // },
196
+ // design: {
197
+ // grid: [6, 12]
198
+ // },
199
+ // inputs: []
200
+ // }, "#jsee-container")
201
+ }
202
+ }
203
+