@jseeio/jsee 0.2.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/404.html +22 -0
- package/README.md +60 -0
- package/_config.yml +26 -0
- package/dist/fb93af989abd7020d0c6.svg +5 -0
- package/dist/jsee.js +1 -0
- package/dist/jsee.runtime.js +1 -0
- package/dist/port.js +1 -0
- package/dist/port.runtime.js +1 -0
- package/load.html +31 -0
- package/main.js +449 -0
- package/package.json +51 -0
- package/src/app.js +188 -0
- package/src/overlay.js +33 -0
- package/src/worker.js +113 -0
- package/templates/bulma-app.vue +65 -0
- package/templates/bulma-input.vue +114 -0
- package/templates/bulma-output.vue +38 -0
- package/templates/common-inputs.js +28 -0
- package/templates/common-outputs.js +39 -0
- package/webpack.config.js +94 -0
package/load.html
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
6
|
+
<title>JSEE Schema Loader</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="jsee-container"></div>
|
|
10
|
+
<div id="txt-container">
|
|
11
|
+
<p>You can use this script for testing purposes. Placing your apps in the <b>apps</b> folder (e.g. <code>./apps/myapp</code> will make it possible to load it with <code>load.html?s=myapp</code> </p>
|
|
12
|
+
</div>
|
|
13
|
+
<script src="dist/jsee.js" type="text/javascript"></script>
|
|
14
|
+
<script>
|
|
15
|
+
var params = new URLSearchParams(window.location.search)
|
|
16
|
+
var schema = params.get('s')
|
|
17
|
+
if (schema) {
|
|
18
|
+
if (typeof schema === 'string') {
|
|
19
|
+
schema = schema.includes('/') ? schema : '/apps/' + schema + '/schema.json'
|
|
20
|
+
}
|
|
21
|
+
const env = new JSEE({
|
|
22
|
+
container: document.getElementById('jsee-container'),
|
|
23
|
+
schema: schema
|
|
24
|
+
})
|
|
25
|
+
} else {
|
|
26
|
+
document.getElementById('port-container').style.display = 'none'
|
|
27
|
+
document.getElementById('txt-container').style.display = 'block'
|
|
28
|
+
}
|
|
29
|
+
</script>
|
|
30
|
+
</body>
|
|
31
|
+
</html>
|
package/main.js
ADDED
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
import { createVueApp } from './src/app'
|
|
2
|
+
import Worker from './src/worker.js'
|
|
3
|
+
|
|
4
|
+
const { Notyf } = require('notyf')
|
|
5
|
+
const notyf = new Notyf({
|
|
6
|
+
types: [
|
|
7
|
+
{
|
|
8
|
+
type: 'success',
|
|
9
|
+
background: '#00d1b2',
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
type: 'error',
|
|
13
|
+
background: '#f14668',
|
|
14
|
+
duration: 2000,
|
|
15
|
+
dismissible: true
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
// const createVueApp = require('./src/app')
|
|
21
|
+
const Overlay = require('./src/overlay')
|
|
22
|
+
|
|
23
|
+
require('notyf/notyf.min.css')
|
|
24
|
+
|
|
25
|
+
const fetch = window['fetch']
|
|
26
|
+
const Blob = window['Blob']
|
|
27
|
+
|
|
28
|
+
function log () {
|
|
29
|
+
console.log(`[JSEE v${VERSION}]`, ...arguments)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// const Worker = window['Worker']
|
|
33
|
+
|
|
34
|
+
// Deep clone a simple object
|
|
35
|
+
function clone (obj) {
|
|
36
|
+
// return JSON.parse(JSON.stringify(obj))
|
|
37
|
+
return Object.assign({}, obj)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// https://stackoverflow.com/questions/8511281/check-if-a-value-is-an-object-in-javascript
|
|
41
|
+
function isObject (item) {
|
|
42
|
+
return (typeof item === 'object' && !Array.isArray(item) && item !== null)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Return input value
|
|
46
|
+
function getValue (input) {
|
|
47
|
+
if (input.type === 'group') {
|
|
48
|
+
const value = {}
|
|
49
|
+
input.elements.forEach(el => {
|
|
50
|
+
value[el.name] = getValue(el)
|
|
51
|
+
})
|
|
52
|
+
return value
|
|
53
|
+
} else {
|
|
54
|
+
return input.value
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export default class JSEE {
|
|
59
|
+
constructor (params) {
|
|
60
|
+
log('Initializing JSEE with parameters: ', params)
|
|
61
|
+
params.schema = params.schema || params.config
|
|
62
|
+
this.params = params
|
|
63
|
+
this.__version__ = VERSION
|
|
64
|
+
|
|
65
|
+
// Get schema then initialize a model
|
|
66
|
+
if (params.schema) {
|
|
67
|
+
if (typeof params.schema === 'object') {
|
|
68
|
+
log('Received schema as object')
|
|
69
|
+
this.init(params.schema)
|
|
70
|
+
} else if (typeof params.schema === 'string') {
|
|
71
|
+
log('Received schema as string')
|
|
72
|
+
this.schemaUrl = params.schema.indexOf('json') ? params.schema : params.schema + '.json'
|
|
73
|
+
fetch(this.schemaUrl)
|
|
74
|
+
.then(res => res.json())
|
|
75
|
+
.then(res => {
|
|
76
|
+
log('Loaded schema from url')
|
|
77
|
+
this.init(res)
|
|
78
|
+
})
|
|
79
|
+
.catch((err) => {
|
|
80
|
+
console.error(err)
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
notify (txt) {
|
|
87
|
+
notyf.success(txt)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Initialize model from schema
|
|
91
|
+
init (schema) {
|
|
92
|
+
log('Initializing schema', schema)
|
|
93
|
+
|
|
94
|
+
// Convert JS code to string
|
|
95
|
+
if (schema.model.code && (typeof schema.model.code !== 'string')) {
|
|
96
|
+
log('Convert code in schema to string')
|
|
97
|
+
schema.model.code = schema.model.code.toString()
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Update model URL if needed
|
|
101
|
+
if (schema.model.url && !schema.model.url.includes('/') && this.schemaUrl && this.schemaUrl.includes('/')) {
|
|
102
|
+
let oldModelUrl = schema.model.url
|
|
103
|
+
log('Schema URL:', this.schemaUrl)
|
|
104
|
+
schema.model.url = window.location.protocol + '//' + window.location.host + this.schemaUrl.split('/').slice(0, -1).join('/') + '/' + oldModelUrl
|
|
105
|
+
log('Changed the old model URL to absolute one:', oldModelUrl, schema.model.url)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Check for worker flag
|
|
109
|
+
if (typeof schema.model.worker === 'undefined') {
|
|
110
|
+
schema.model.worker = true
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Check if name is present, if not - get name from the file
|
|
114
|
+
if (typeof schema.model.name === 'undefined') {
|
|
115
|
+
// Two options here
|
|
116
|
+
if (schema.model.url) {
|
|
117
|
+
// 1. Get the name from the file name
|
|
118
|
+
schema.model.name = schema.model.url.split('/').pop().split('.')[0]
|
|
119
|
+
log('Use name from url: ', schema.model.name)
|
|
120
|
+
} else if (schema.model.code) {
|
|
121
|
+
// 2. Get the name from the url
|
|
122
|
+
schema.model.name = schema.model.code.name
|
|
123
|
+
log('Use name from code: ', schema.model.name)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
this.schema = clone(schema)
|
|
128
|
+
|
|
129
|
+
// Init Vue app
|
|
130
|
+
this.app = createVueApp(this, this.schema, (container) => {
|
|
131
|
+
// Called when the app is mounted
|
|
132
|
+
// FYI "this" here refers to port object
|
|
133
|
+
this.outputsContainer = container.querySelector('#outputs')
|
|
134
|
+
this.inputsContainer = container.querySelector('#inputs')
|
|
135
|
+
this.modelContainer = container.querySelector('#model')
|
|
136
|
+
|
|
137
|
+
// Init overlay
|
|
138
|
+
this.overlay = new Overlay(this.inputsContainer)
|
|
139
|
+
})
|
|
140
|
+
this.data = this.app.$data
|
|
141
|
+
|
|
142
|
+
// Init Model
|
|
143
|
+
// ----------
|
|
144
|
+
if (this.schema.model.type === 'py') {
|
|
145
|
+
// Add loading indicator
|
|
146
|
+
this.overlay.show()
|
|
147
|
+
let script = document.createElement('script')
|
|
148
|
+
script.src = 'https://cdn.jsdelivr.net/pyodide/v0.18.1/full/pyodide.js'
|
|
149
|
+
script.onload = async () => {
|
|
150
|
+
this.pyodide = await loadPyodide({ indexURL : "https://cdn.jsdelivr.net/pyodide/v0.18.1/full/" });
|
|
151
|
+
notyf.success('Loaded: Python')
|
|
152
|
+
const resRaw = await fetch(this.schema.model.url)
|
|
153
|
+
const res = await resRaw.text()
|
|
154
|
+
this.pymodel = res
|
|
155
|
+
log('Loaded python code:', res)
|
|
156
|
+
// Check if micropip is used
|
|
157
|
+
if (res.includes('micropip')) {
|
|
158
|
+
await this.pyodide.loadPackage('micropip')
|
|
159
|
+
log('Loaded micropip')
|
|
160
|
+
}
|
|
161
|
+
// Import packages if defined
|
|
162
|
+
if ('packages' in this.schema.model) {
|
|
163
|
+
await this.pyodide.loadPackage(this.schema.model.packages)
|
|
164
|
+
log('Loaded packages from schema')
|
|
165
|
+
} else {
|
|
166
|
+
await this.pyodide.loadPackagesFromImports(res)
|
|
167
|
+
log('Loaded packages from Python code')
|
|
168
|
+
}
|
|
169
|
+
this.overlay.hide()
|
|
170
|
+
}
|
|
171
|
+
document.head.appendChild(script)
|
|
172
|
+
} else if (['function', 'class', 'async-init', 'async-function'].includes(this.schema.model.type)) {
|
|
173
|
+
// Initialize worker with the model
|
|
174
|
+
if (this.schema.model.worker) {
|
|
175
|
+
// this.worker = new Worker(new URL('./src/worker.js', import.meta.url))
|
|
176
|
+
this.worker = new Worker()
|
|
177
|
+
if (this.schema.model.url) {
|
|
178
|
+
fetch(this.schema.model.url)
|
|
179
|
+
.then(res => res.text())
|
|
180
|
+
.then(res => {
|
|
181
|
+
log('Loaded js code for worker')
|
|
182
|
+
this.schema.model.code = res
|
|
183
|
+
this.worker.postMessage(this.schema.model)
|
|
184
|
+
})
|
|
185
|
+
} else if (typeof this.schema.model.code !== 'undefined') {
|
|
186
|
+
this.worker.postMessage(this.schema.model)
|
|
187
|
+
} else {
|
|
188
|
+
notyf.error('No code provided')
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
this.worker.onmessage = (e) => {
|
|
192
|
+
this.overlay.hide()
|
|
193
|
+
const res = e.data
|
|
194
|
+
if ((typeof res === 'object') && (res._status)) {
|
|
195
|
+
switch (res._status) {
|
|
196
|
+
case 'loaded':
|
|
197
|
+
notyf.success('Loaded: JS model (in worker)')
|
|
198
|
+
break
|
|
199
|
+
case 'log':
|
|
200
|
+
log(...res._log)
|
|
201
|
+
break
|
|
202
|
+
}
|
|
203
|
+
} else {
|
|
204
|
+
log('Response from worker:', res)
|
|
205
|
+
this.output(res)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
this.worker.onerror = (e) => {
|
|
209
|
+
this.overlay.hide()
|
|
210
|
+
notyf.error(e.message)
|
|
211
|
+
log('Error from worker:', e)
|
|
212
|
+
}
|
|
213
|
+
} else {
|
|
214
|
+
// Initialize model in main window
|
|
215
|
+
log('Init model in window')
|
|
216
|
+
let script = document.createElement('script')
|
|
217
|
+
script.src = this.schema.model.url
|
|
218
|
+
script.onload = () => {
|
|
219
|
+
notyf.success('Loaded: JS model')
|
|
220
|
+
this.overlay.hide()
|
|
221
|
+
log('Loaded JS model in main window')
|
|
222
|
+
|
|
223
|
+
// Initializing the model (same in worker)
|
|
224
|
+
if (this.schema.model.type === 'class') {
|
|
225
|
+
log('Init class')
|
|
226
|
+
const modelClass = new window[this.schema.model.name]()
|
|
227
|
+
this.modelFunc = (...a) => {
|
|
228
|
+
return modelClass[this.schema.model.method || 'predict'](...a)
|
|
229
|
+
}
|
|
230
|
+
} else if (this.schema.model.type === 'async-init') {
|
|
231
|
+
log('Init function with promise')
|
|
232
|
+
window[this.schema.model.name]().then((m) => {
|
|
233
|
+
log('Async init resolved: ', m)
|
|
234
|
+
this.modelFunc = m
|
|
235
|
+
})
|
|
236
|
+
} else {
|
|
237
|
+
log('Init function')
|
|
238
|
+
this.modelFunc = window[this.schema.model.name]
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
document.head.appendChild(script)
|
|
242
|
+
}
|
|
243
|
+
} else if (this.schema.model.type === 'tf') {
|
|
244
|
+
// Initialize TF
|
|
245
|
+
let script = document.createElement('script')
|
|
246
|
+
script.src = 'dist/tf.min.js'
|
|
247
|
+
script.onload = () => {
|
|
248
|
+
log('Loaded TF.js')
|
|
249
|
+
this.overlay.hide()
|
|
250
|
+
window['tf'].loadLayersModel(this.schema.model.url).then(res => {
|
|
251
|
+
log('Loaded Tensorflow model')
|
|
252
|
+
})
|
|
253
|
+
}
|
|
254
|
+
document.head.appendChild(script)
|
|
255
|
+
} else if (this.schema.model.type === 'get') {
|
|
256
|
+
this.overlay.hide()
|
|
257
|
+
this.modelFunc = (data) => {
|
|
258
|
+
const query = new window['URLSearchParams'](data).toString()
|
|
259
|
+
log('Generated query string:', query)
|
|
260
|
+
const resPromise = fetch(this.schema.model.url +'?' + query)
|
|
261
|
+
.then(response => response.json())
|
|
262
|
+
return resPromise
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Init render
|
|
267
|
+
// -----------
|
|
268
|
+
if (this.schema.render && this.schema.render.url) {
|
|
269
|
+
log('Init render in window')
|
|
270
|
+
let script = document.createElement('script')
|
|
271
|
+
script.src = this.schema.render.url
|
|
272
|
+
script.onload = () => {
|
|
273
|
+
notyf.success('Loaded: JS render')
|
|
274
|
+
log('Loaded JS render')
|
|
275
|
+
|
|
276
|
+
// Initializing the render (same in worker)
|
|
277
|
+
if (this.schema.render.type === 'class') {
|
|
278
|
+
log('Init render as class')
|
|
279
|
+
const renderClass = new window[this.schema.render.name]()
|
|
280
|
+
this.renderFunc = (...a) => {
|
|
281
|
+
return renderClass[this.schema.render.method || 'render'](...a)
|
|
282
|
+
}
|
|
283
|
+
} else if (this.schema.render.type === 'async-init') {
|
|
284
|
+
log('Init render function with promise')
|
|
285
|
+
window[this.schema.render.name]().then((m) => {
|
|
286
|
+
log('Async rebder init resolved: ', m)
|
|
287
|
+
this.renderFunc = m
|
|
288
|
+
})
|
|
289
|
+
} else {
|
|
290
|
+
log('Init render as function')
|
|
291
|
+
this.renderFunc = window[this.schema.render.name]
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
document.head.appendChild(script)
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
run () {
|
|
299
|
+
const schema = this.schema
|
|
300
|
+
const data = this.data
|
|
301
|
+
log('Running the model...')
|
|
302
|
+
// Collect input values
|
|
303
|
+
let inputValues
|
|
304
|
+
|
|
305
|
+
if (schema.model && schema.model.container && schema.model.container === 'args') {
|
|
306
|
+
log('Pass inputs as function arguments')
|
|
307
|
+
inputValues = data.inputs.map(input => getValue(input))
|
|
308
|
+
} else {
|
|
309
|
+
log('Pass inputs in an object')
|
|
310
|
+
inputValues = {}
|
|
311
|
+
data.inputs.forEach(input => {
|
|
312
|
+
if (input.name) {
|
|
313
|
+
inputValues[input.name] = getValue(input)
|
|
314
|
+
}
|
|
315
|
+
})
|
|
316
|
+
}
|
|
317
|
+
log('Input values:', inputValues)
|
|
318
|
+
// We have all input values here, pass them to worker, window.modelFunc or tf
|
|
319
|
+
if (!schema.model.autorun) {
|
|
320
|
+
this.overlay.show()
|
|
321
|
+
}
|
|
322
|
+
switch (schema.model.type) {
|
|
323
|
+
case 'tf':
|
|
324
|
+
break
|
|
325
|
+
case 'py':
|
|
326
|
+
data.inputs.forEach(input => {
|
|
327
|
+
this.pyodide.globals.set(input.name, input.value);
|
|
328
|
+
})
|
|
329
|
+
this.pyodide.runPythonAsync(this.pymodel, () => {})
|
|
330
|
+
.then((res) => {
|
|
331
|
+
if (schema.outputs && schema.outputs.length) {
|
|
332
|
+
const resultObj = {}
|
|
333
|
+
schema.outputs.forEach(output => {
|
|
334
|
+
resultObj[output.name] = this.pyodide.globals.get(output.name).toJs()
|
|
335
|
+
})
|
|
336
|
+
this.output(resultObj)
|
|
337
|
+
} else {
|
|
338
|
+
this.output(res)
|
|
339
|
+
}
|
|
340
|
+
})
|
|
341
|
+
.catch((err) => {
|
|
342
|
+
log(err)
|
|
343
|
+
window['M'].toast({html: 'Error in code'})
|
|
344
|
+
})
|
|
345
|
+
break
|
|
346
|
+
|
|
347
|
+
case 'class':
|
|
348
|
+
case 'function':
|
|
349
|
+
case 'async-init':
|
|
350
|
+
case 'async-function':
|
|
351
|
+
case 'get':
|
|
352
|
+
if (this.schema.model.worker) {
|
|
353
|
+
this.worker.postMessage(inputValues)
|
|
354
|
+
} else {
|
|
355
|
+
// Run in main window
|
|
356
|
+
var res
|
|
357
|
+
if (this.schema.model.container === 'args') {
|
|
358
|
+
res = this.modelFunc.apply(null, inputValues)
|
|
359
|
+
} else {
|
|
360
|
+
log('Applying inputs as object')
|
|
361
|
+
res = this.modelFunc(inputValues)
|
|
362
|
+
}
|
|
363
|
+
log('modelFunc results:', res)
|
|
364
|
+
Promise.resolve(res).then(r => { this.output(r) })
|
|
365
|
+
}
|
|
366
|
+
break
|
|
367
|
+
case 'api':
|
|
368
|
+
break
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
output (res) {
|
|
373
|
+
// TODO: Think about all edge cases
|
|
374
|
+
// * No output field, but reactivity
|
|
375
|
+
this.overlay.hide()
|
|
376
|
+
|
|
377
|
+
if (typeof res === 'undefined') {
|
|
378
|
+
return
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
log('Got output results of type:', typeof res)
|
|
382
|
+
|
|
383
|
+
// Process results (res)
|
|
384
|
+
const inputNames = this.schema.inputs.map(i => i.name)
|
|
385
|
+
if (isObject(res) && Object.keys(res).every(key => inputNames.includes(key))) {
|
|
386
|
+
// Update inputs from results
|
|
387
|
+
log('Updating inputs:', Object.keys(res))
|
|
388
|
+
this.data.inputs.forEach((input, i) => {
|
|
389
|
+
if (input.name && (typeof res[input.name] !== 'undefined')) {
|
|
390
|
+
log('Updating input: ', input.name, 'with data:', res[input.name])
|
|
391
|
+
const r = res[input.name]
|
|
392
|
+
if (typeof r === 'object') {
|
|
393
|
+
Object.keys(r).forEach(k => {
|
|
394
|
+
input[k] = r[k]
|
|
395
|
+
})
|
|
396
|
+
} else {
|
|
397
|
+
input.value = r
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
})
|
|
401
|
+
} else if (this.renderFunc) {
|
|
402
|
+
// Pass results to a custom render function
|
|
403
|
+
log('Calling a render function...')
|
|
404
|
+
this.renderFunc(res)
|
|
405
|
+
} else if (Array.isArray(res) && res.length) {
|
|
406
|
+
// Result is array
|
|
407
|
+
if (this.data.outputs && this.data.outputs.length) {
|
|
408
|
+
// We have outputs defined
|
|
409
|
+
if (this.data.outputs.length === res.length) {
|
|
410
|
+
// Same length
|
|
411
|
+
this.data.outputs.forEach((output, i) => {
|
|
412
|
+
output.value = res[i]
|
|
413
|
+
})
|
|
414
|
+
} else {
|
|
415
|
+
// Different length
|
|
416
|
+
this.data.outputs[0].value = res
|
|
417
|
+
}
|
|
418
|
+
} else {
|
|
419
|
+
// Outputs are not defined
|
|
420
|
+
this.data.outputs = [{
|
|
421
|
+
'type': 'array',
|
|
422
|
+
'value': res
|
|
423
|
+
}]
|
|
424
|
+
}
|
|
425
|
+
} else if (typeof res === 'object') {
|
|
426
|
+
if (this.data.outputs && this.data.outputs.length) {
|
|
427
|
+
this.data.outputs.forEach((output, i) => {
|
|
428
|
+
if (output.name && (typeof res[output.name] !== 'undefined')) {
|
|
429
|
+
log('Updating output: ', output.name)
|
|
430
|
+
output.value = res[output.name]
|
|
431
|
+
}
|
|
432
|
+
})
|
|
433
|
+
} else {
|
|
434
|
+
this.data.outputs = [{
|
|
435
|
+
'type': 'object',
|
|
436
|
+
'value': res
|
|
437
|
+
}]
|
|
438
|
+
}
|
|
439
|
+
} else if (this.schema.outputs && this.schema.outputs.length === 1) {
|
|
440
|
+
// One output value passed as raw js object
|
|
441
|
+
this.data.outputs[0].value = res
|
|
442
|
+
} else {
|
|
443
|
+
this.data.outputs = [{
|
|
444
|
+
'type': typeof res,
|
|
445
|
+
'value': res
|
|
446
|
+
}]
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jseeio/jsee",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "dist/jsee.js",
|
|
6
|
+
"private": false,
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build-dev": "webpack --mode=development --progress",
|
|
9
|
+
"build": "webpack --mode=production --progress && npx webpack --mode=production --progress --env RUNTIME",
|
|
10
|
+
"watch": "nodemon --watch . --ignore dist --ext vue,js,css,html --exec 'npm run build-dev'",
|
|
11
|
+
"prepublishOnly": "npm run build",
|
|
12
|
+
"test": "tape test.js | faucet"
|
|
13
|
+
},
|
|
14
|
+
"author": "Anton Zemlyansky",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@mdi/font": "^6.5.95",
|
|
18
|
+
"bulma": "^0.9.3",
|
|
19
|
+
"csv-parse": "^4.6.1",
|
|
20
|
+
"file-saver": "^2.0.2",
|
|
21
|
+
"filtrex": "^2.2.3",
|
|
22
|
+
"notyf": "^3.10.0",
|
|
23
|
+
"vue": "^3.2.23",
|
|
24
|
+
"vue-style-loader": "^4.1.3",
|
|
25
|
+
"vue3-json-viewer": "^1.0.4",
|
|
26
|
+
"vuex": "^4.0.2"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@babel/core": "^7.16.5",
|
|
30
|
+
"@babel/plugin-transform-runtime": "^7.4.4",
|
|
31
|
+
"@babel/preset-env": "^7.16.5",
|
|
32
|
+
"babel-loader": "^8.2.3",
|
|
33
|
+
"css-loader": "^6.5.1",
|
|
34
|
+
"node-sass": "^7.0.0",
|
|
35
|
+
"nodemon": "^2.0.15",
|
|
36
|
+
"puppeteer": "^1.12.2",
|
|
37
|
+
"sass-loader": "^12.4.0",
|
|
38
|
+
"style-loader": "^3.3.1",
|
|
39
|
+
"tape": "^4.9.1",
|
|
40
|
+
"terser-webpack-plugin": "^5.3.0",
|
|
41
|
+
"uglify-es": "^3.3.9",
|
|
42
|
+
"vue-loader": "^17.0.0",
|
|
43
|
+
"vue-template-compiler": "^2.6.14",
|
|
44
|
+
"webpack": "^5.65.0",
|
|
45
|
+
"webpack-cli": "^4.9.1",
|
|
46
|
+
"worker-loader": "^3.0.8"
|
|
47
|
+
},
|
|
48
|
+
"resolutions": {
|
|
49
|
+
"ansi-regex": "5.0.1"
|
|
50
|
+
}
|
|
51
|
+
}
|