@jseeio/jsee 0.4.2 → 0.8.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/CHANGELOG.md +96 -0
- package/LICENSE +21 -0
- package/README.md +583 -55
- package/dist/2b3e1faf89f94a483539.png +0 -0
- package/dist/416d91365b44e4b4f477.png +0 -0
- package/dist/8f2c4d11474275fbc161.png +0 -0
- package/dist/jsee.core.js +1 -0
- package/dist/jsee.full.js +1 -0
- package/dist/jsee.runtime.js +2 -1
- package/package.json +84 -18
- package/src/app.js +127 -32
- package/src/browser-bundle-node.js +9 -0
- package/src/cli.js +479 -67
- package/src/extended-imports.js +11 -0
- package/src/main.js +232 -44
- package/src/overlay.js +26 -1
- package/src/utils.js +386 -16
- package/templates/common-inputs.js +88 -0
- package/templates/common-outputs.js +340 -4
- package/templates/minimal-app.vue +367 -0
- package/templates/minimal-input.vue +573 -0
- package/templates/minimal-output.vue +426 -0
- package/templates/virtual-table.vue +194 -0
- package/.claude/settings.local.json +0 -15
- package/.eslintrc.js +0 -38
- package/AGENTS.md +0 -65
- package/CLAUDE.md +0 -5
- package/CNAME +0 -1
- package/_config.yml +0 -26
- package/dist/jsee.js +0 -1
- package/dump.sh +0 -23
- package/jest-puppeteer.config.js +0 -14
- package/jest.config.js +0 -8
- package/jest.unit.config.js +0 -8
- package/jsee.dump.txt +0 -5459
- package/load/index.html +0 -52
- package/templates/bulma-app.vue +0 -242
- package/templates/bulma-input.vue +0 -125
- package/templates/bulma-output.vue +0 -101
- package/test/arrow-main.html +0 -18
- package/test/arrow-worker.html +0 -18
- package/test/class.html +0 -22
- package/test/code.html +0 -25
- package/test/codew.html +0 -25
- package/test/example-class.js +0 -8
- package/test/example-sum.js +0 -3
- package/test/fixtures/lodash-like.js +0 -15
- package/test/fixtures/upload-sample.csv +0 -3
- package/test/importw.html +0 -28
- package/test/minimal.html +0 -14
- package/test/minimal1.html +0 -13
- package/test/minimal2.html +0 -15
- package/test/minimal3.html +0 -10
- package/test/minimal4.html +0 -22
- package/test/pipeline.html +0 -52
- package/test/python.html +0 -41
- package/test/runtime-arrow.html +0 -18
- package/test/string.html +0 -26
- package/test/stringw.html +0 -29
- package/test/sum.schema.json +0 -17
- package/test/sumw.schema.json +0 -15
- package/test/test-basic.test.js +0 -630
- package/test/test-python.test.js +0 -23
- package/test/unit/cli-fetch.test.js +0 -229
- package/test/unit/utils.test.js +0 -908
- package/webpack.config.js +0 -101
package/README.md
CHANGED
|
@@ -1,45 +1,128 @@
|
|
|
1
|
-
# JSEE
|
|
1
|
+
# JSEE
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Portable, schema-driven web apps for local computation.
|
|
4
|
+
|
|
5
|
+
JSEE turns a model function plus a small JSON schema into a reactive browser app, CLI-served tool, offline HTML bundle and API surface. It is meant for computations that should be easy to share, inspect, rerun and keep on the user's machine.
|
|
6
|
+
|
|
7
|
+
Use JSEE when you want:
|
|
8
|
+
|
|
9
|
+
- a self-contained UI around a JavaScript, Python, API, or WASM computation
|
|
10
|
+
- typed inputs, output rendering, file/folder handling, progress, and cancellation without writing app plumbing
|
|
11
|
+
- browser-first execution with optional Worker isolation and offline bundling
|
|
12
|
+
- the same computation exposed to humans through a UI and to tools through HTTP/API routes
|
|
13
|
+
|
|
14
|
+
Smallest browser example:
|
|
4
15
|
|
|
5
|
-
Minimal example:
|
|
6
16
|
```html
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
</script>
|
|
16
|
-
</html>
|
|
17
|
+
<div id="jsee-container"></div>
|
|
18
|
+
<script src="https://cdn.jsdelivr.net/npm/@jseeio/jsee@latest/dist/jsee.core.js"></script>
|
|
19
|
+
<script>
|
|
20
|
+
function multiply (a, b) {
|
|
21
|
+
return a * b
|
|
22
|
+
}
|
|
23
|
+
new JSEE(multiply, '#jsee-container')
|
|
24
|
+
</script>
|
|
17
25
|
```
|
|
18
26
|
|
|
19
27
|
↳ [Result](https://jsee.org/test/minimal1.html)
|
|
20
28
|
|
|
21
29
|
## Installation
|
|
22
30
|
|
|
23
|
-
**Browser
|
|
31
|
+
**Browser CDN:**
|
|
32
|
+
|
|
24
33
|
```html
|
|
25
|
-
<script src="https://cdn.jsdelivr.net/npm/@jseeio/jsee@latest/dist/jsee.
|
|
34
|
+
<script src="https://cdn.jsdelivr.net/npm/@jseeio/jsee@latest/dist/jsee.core.js"></script>
|
|
26
35
|
```
|
|
27
36
|
|
|
28
|
-
|
|
37
|
+
Pin a version for production, for example `@jseeio/jsee@0.8.1`.
|
|
38
|
+
|
|
39
|
+
**npm CLI/dev server:**
|
|
40
|
+
|
|
29
41
|
```bash
|
|
30
42
|
npm install @jseeio/jsee
|
|
31
43
|
```
|
|
32
44
|
|
|
33
|
-
|
|
45
|
+
Run from npm without installing globally:
|
|
46
|
+
|
|
34
47
|
```bash
|
|
35
48
|
npx @jseeio/jsee schema.json -o app.html
|
|
36
49
|
```
|
|
37
50
|
|
|
38
|
-
Run `jsee --help` for all CLI options.
|
|
51
|
+
Run `npx @jseeio/jsee --help` for all CLI options.
|
|
52
|
+
|
|
53
|
+
## Runtime Bundles
|
|
54
|
+
|
|
55
|
+
| Bundle | Use when | Includes |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| `dist/jsee.core.js` | Most apps, direct `<script>` tags, generated HTML | runtime, inputs, core outputs, native PDF viewer |
|
|
58
|
+
| `dist/jsee.full.js` | Apps that need `chart`, `3d`, or `map` without extra imports | core + Observable Plot + Three.js + Leaflet |
|
|
59
|
+
| `@jseeio/jsee` package entry | CLI/server-side tooling | Node CLI module |
|
|
60
|
+
|
|
61
|
+
Full bundle CDN:
|
|
62
|
+
|
|
63
|
+
```html
|
|
64
|
+
<script src="https://cdn.jsdelivr.net/npm/@jseeio/jsee@latest/dist/jsee.full.js"></script>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The core bundle can still render `chart`, `3d`, and `map` if the app loads the required library through schema `imports`. The `pdf` output uses the browser's native PDF viewer and is available in the core bundle. The CLI and Python server choose the required runtime bundle from the schema output types.
|
|
68
|
+
|
|
69
|
+
## Quick start
|
|
70
|
+
|
|
71
|
+
Scaffold a project:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npx @jseeio/jsee init # minimal: schema.json + model.js + README.md
|
|
75
|
+
npx @jseeio/jsee init chat # chat template
|
|
76
|
+
npx @jseeio/jsee init --html # single index.html with CDN script
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Python:
|
|
80
|
+
```bash
|
|
81
|
+
jsee init # schema.json + model.py + README.md
|
|
82
|
+
jsee init chat # chat template
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Or create the two files yourself:
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"model": { "url": "model.js", "worker": true },
|
|
90
|
+
"inputs": [
|
|
91
|
+
{ "name": "n", "type": "slider", "min": 10, "max": 1000, "default": 100 }
|
|
92
|
+
],
|
|
93
|
+
"outputs": [
|
|
94
|
+
{ "name": "summary", "type": "number", "label": "Rows" },
|
|
95
|
+
{ "name": "rows", "type": "table" }
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
function model ({ n }, ctx) {
|
|
102
|
+
ctx.progress(10)
|
|
103
|
+
const rows = Array.from({ length: n }, (_, i) => ({ i, y: Math.sin(i / 10) }))
|
|
104
|
+
ctx.progress(100)
|
|
105
|
+
return { summary: n, rows }
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Start the dev server:
|
|
39
110
|
|
|
40
|
-
|
|
111
|
+
```bash
|
|
112
|
+
npx @jseeio/jsee schema.json # Node (auto server-side execution)
|
|
113
|
+
jsee schema.json # Python
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Generate a standalone HTML file:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
npx @jseeio/jsee schema.json -o app.html
|
|
120
|
+
npx @jseeio/jsee schema.json -o app.html --fetch # inline runtime + imports for offline use
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## When JSEE Fits
|
|
41
124
|
|
|
42
|
-
JSEE works best
|
|
125
|
+
JSEE works best for computations with a clear flow from inputs to processing to outputs. Pipelines, input updates, streaming files, custom renderers, and chat-style interfaces are supported, but JSEE is intentionally not a general application framework. If the UI needs deep bidirectional state, many custom screens, routing, or complex collaborative editing, use a normal frontend app and call JSEE-style computation modules from it.
|
|
43
126
|
|
|
44
127
|
## How it works
|
|
45
128
|
|
|
@@ -78,8 +161,8 @@ JSEE turns a JSON schema into a working web app. Instead of writing HTML, event
|
|
|
78
161
|
|
|
79
162
|
- **Run**: user clicks Run (or autorun/reactive triggers it). Inputs are collected and sent to the model
|
|
80
163
|
- **Pipeline**: when `model` is an array, models execute sequentially — each receives the merged output of the previous one. Return `{ stop: true }` to halt early
|
|
81
|
-
- **
|
|
82
|
-
- **Cancellation**: `jsee.cancelCurrentRun()` or the Stop button
|
|
164
|
+
- **Runtime context**: object-container models receive a second argument (`ctx`) with `ctx.log()`, `ctx.progress(value)` (0–100 or `null` for indeterminate), and `ctx.isCancelled()` for cooperative cancellation
|
|
165
|
+
- **Cancellation**: `jsee.cancelCurrentRun()` or the Stop button rejects the active run, signals workers, and marks stale results so they are ignored. Worker-backed models can be terminated. Main-thread models should check `ctx.isCancelled()` inside long async loops because JavaScript cannot preempt synchronous CPU-bound code on the main thread
|
|
83
166
|
- **Output**: results flow to the output cards — JSON trees, HTML, SVG, code blocks, or custom render functions
|
|
84
167
|
|
|
85
168
|
### Offline & bundling
|
|
@@ -121,6 +204,92 @@ Extra blocks can be provided for further customization:
|
|
|
121
204
|
|
|
122
205
|
- [Codepen](https://codepen.io/jseeio/pen/NWayjJe)
|
|
123
206
|
|
|
207
|
+
## Examples
|
|
208
|
+
|
|
209
|
+
### Full schema
|
|
210
|
+
|
|
211
|
+
A complete schema with multiple inputs, outputs, theming, and a worker model:
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{
|
|
215
|
+
"model": { "url": "model.js", "worker": true },
|
|
216
|
+
"design": { "primary": "#2a7ae2", "grid": [4, 8] },
|
|
217
|
+
"inputs": [
|
|
218
|
+
{ "name": "count", "type": "slider", "min": 10, "max": 1000, "default": 100 },
|
|
219
|
+
{ "name": "method", "type": "select", "options": ["linear", "quadratic"], "default": "linear" }
|
|
220
|
+
],
|
|
221
|
+
"outputs": [
|
|
222
|
+
{ "name": "summary", "type": "number", "prefix": "n = " },
|
|
223
|
+
{ "name": "data", "type": "chart", "mark": "dot", "x": "x", "y": "y" },
|
|
224
|
+
{ "name": "raw", "type": "table" }
|
|
225
|
+
],
|
|
226
|
+
"autorun": true
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Chart output
|
|
231
|
+
|
|
232
|
+
Model returns array of objects or column-oriented data:
|
|
233
|
+
|
|
234
|
+
```javascript
|
|
235
|
+
function model ({ count }) {
|
|
236
|
+
const data = Array.from({ length: count }, (_, i) => ({
|
|
237
|
+
x: i, y: Math.sin(i / 10) + Math.random() * 0.2
|
|
238
|
+
}))
|
|
239
|
+
return { chart: data }
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Schema: `{ "name": "chart", "type": "chart", "mark": "line", "x": "x", "y": "y" }`
|
|
244
|
+
|
|
245
|
+
### Map output
|
|
246
|
+
|
|
247
|
+
Model returns markers array:
|
|
248
|
+
|
|
249
|
+
```javascript
|
|
250
|
+
function model () {
|
|
251
|
+
return {
|
|
252
|
+
map: [
|
|
253
|
+
{ lat: 51.505, lng: -0.09, popup: 'London' },
|
|
254
|
+
{ lat: 48.857, lng: 2.352, popup: 'Paris' },
|
|
255
|
+
{ lat: 52.52, lng: 13.405, popup: 'Berlin' }
|
|
256
|
+
]
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Pipeline
|
|
262
|
+
|
|
263
|
+
Sequential models pass merged results forward:
|
|
264
|
+
|
|
265
|
+
```json
|
|
266
|
+
{
|
|
267
|
+
"model": [
|
|
268
|
+
{ "url": "preprocess.js", "worker": true },
|
|
269
|
+
{ "url": "analyze.js", "worker": false }
|
|
270
|
+
]
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
First model returns `{ cleaned: [...] }`, second receives `{ cleaned: [...], ...originalInputs }`. Return `{ stop: true }` from any model to halt early.
|
|
275
|
+
|
|
276
|
+
### Multi-column layout
|
|
277
|
+
|
|
278
|
+
Use `columns` on inputs/outputs for dashboard-style layouts:
|
|
279
|
+
|
|
280
|
+
```json
|
|
281
|
+
{
|
|
282
|
+
"inputs": [
|
|
283
|
+
{ "name": "a", "type": "slider", "min": 0, "max": 100, "columns": 6 },
|
|
284
|
+
{ "name": "b", "type": "slider", "min": 0, "max": 100, "columns": 6 }
|
|
285
|
+
],
|
|
286
|
+
"outputs": [
|
|
287
|
+
{ "name": "total", "type": "number", "columns": 4 },
|
|
288
|
+
{ "name": "chart", "type": "chart", "columns": 8 }
|
|
289
|
+
]
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
124
293
|
## Schema
|
|
125
294
|
|
|
126
295
|
- `model` — Contains main parameters of the model/script
|
|
@@ -139,8 +308,8 @@ Extra blocks can be provided for further customization:
|
|
|
139
308
|
- `container` (string) — How input values are passed to the function/method:
|
|
140
309
|
- `object` (default) — Pass inputs wrapped in an object, i.e. `{'x': 1, 'y': 2}`
|
|
141
310
|
- `args` — Pass inputs as separate arguments
|
|
311
|
+
- In `object` mode, JavaScript models receive the runtime context as a second argument: `function model(inputs, ctx) { ... }`
|
|
142
312
|
- `worker` (boolean) — If `true`, JSEE initializes a Web Worker to run the script
|
|
143
|
-
- For `container: 'object'`, model functions receive a second runtime context argument (`ctx`)
|
|
144
313
|
- `ctx.log(...args)` — Write runtime logs
|
|
145
314
|
- `ctx.progress(value)` — Report progress (`0..100` or `null` for indeterminate)
|
|
146
315
|
- `ctx.isCancelled()` — Check cooperative cancellation state (useful in long loops/streams)
|
|
@@ -149,39 +318,127 @@ Extra blocks can be provided for further customization:
|
|
|
149
318
|
- `model` can also be an **array of model objects** to create a pipeline. Models execute sequentially — each receives the merged output of the previous one. First model defaults to `worker: true`, others to `worker: false`. Return `{ stop: true }` from any model to halt the pipeline early
|
|
150
319
|
- `render` — Custom rendering script. Instead of relying on JSEE for output visualization, you can provide a custom script that visualizes the results. That can be useful if you rely on custom libs for plotting
|
|
151
320
|
- `design` — Design parameters
|
|
152
|
-
- `layout` — Layout for the model/input/output blocks. If it's empty and the JSEE container is not, JSEE uses inner HTML as a template. If the container is empty too, it uses the default `blocks` template
|
|
153
|
-
- `framework` — Design framework to use. If a JavaScript object with the same name is present in a global context, JSEE loads it too (using Vue's `use` method)
|
|
321
|
+
- `layout` — Layout for the model/input/output blocks. If it's empty and the JSEE container is not, JSEE uses inner HTML as a template. If the container is empty too, it uses the default `blocks` template. Set `'sidebar'` for a fixed-width (280px) sticky input panel — inputs stay visible while scrolling outputs. Collapses to single column on mobile
|
|
322
|
+
- `framework` — Design framework to use (`'minimal'` by default). If a JavaScript object with the same name is present in a global context, JSEE loads it too (using Vue's `use` method)
|
|
323
|
+
- `theme` — Color theme. Set `'dark'` for dark mode
|
|
324
|
+
- `primary` — Accent color (buttons, toggles, gradient). Hex string, e.g. `'#e74c3c'`
|
|
325
|
+
- `secondary` — Second gradient color. Defaults to a darker shade of `primary`
|
|
326
|
+
- `bg` — Background color. Derives card, input, and border colors automatically
|
|
327
|
+
- `fg` — Text color. Derives secondary text color automatically
|
|
328
|
+
- `font` — Font family string, e.g. `'Georgia, serif'`
|
|
329
|
+
- `radius` — Border radius in pixels (number) or CSS value (string)
|
|
330
|
+
- `grid` (array) — 12-column grid split for input/output sections. E.g. `[4, 8]` (default), `[6, 6]` (equal), `[3, 9]`. Values are `fr` units
|
|
331
|
+
- All components use CSS custom properties that can be overridden via CSS: `--jsee-primary`, `--jsee-bg`, `--jsee-text`, `--jsee-text-secondary`, `--jsee-border`, `--jsee-input-bg`, `--jsee-input-border`, `--jsee-focus-border`, `--jsee-focus-ring`, `--jsee-card-bg`, `--jsee-bg-secondary`, `--jsee-label-bg`, `--jsee-error`, `--jsee-radius`
|
|
154
332
|
- `inputs` — Inputs definition
|
|
155
333
|
- `name`* — Name of the input
|
|
156
334
|
- `type`* — Type. Possible types:
|
|
157
335
|
- `int`, `float` or `number` — Number
|
|
158
|
-
- `string` — String
|
|
159
|
-
- `
|
|
336
|
+
- `string` — String (text input)
|
|
337
|
+
- `color` — Color picker (HTML5 `<input type="color">`)
|
|
338
|
+
- `text` — Textarea (auto-resizes to fit content, up to 400px)
|
|
160
339
|
- `checkbox` or `bool` — Checkbox
|
|
161
340
|
- `select` or `categorical` — Select (one of many `options`)
|
|
341
|
+
- `slider` — Range slider (`min`, `max`, `step`)
|
|
342
|
+
- `range` — Dual-handle range slider, returns `[min, max]` array
|
|
343
|
+
- `radio` — Radio button group (one of many `options`)
|
|
344
|
+
- `toggle` — Toggle switch (boolean)
|
|
345
|
+
- `date` — Date picker
|
|
346
|
+
- `multi-select` — Checkbox group, returns array of selected `options`
|
|
347
|
+
- `group` — Group of inputs. Use `elements` array for child inputs. Supports three display styles via `style` property:
|
|
348
|
+
- `blocks` (default) — flat list of child inputs
|
|
349
|
+
- `accordion` — collapsible section (also triggered by `collapsed` or `label` props)
|
|
350
|
+
- `tabs` — tabbed view where each child element becomes a tab (child groups use their `name`/`label` as tab label)
|
|
162
351
|
- `file` — File Input
|
|
352
|
+
- `folder` — Directory input. Shows a file listing with optional selection. In the browser, uses `<input webkitdirectory>` or drag-drop. On the server, reads from a directory path. Returns array of `{name, path, size, type, selected}` objects. Props:
|
|
353
|
+
- `select` (boolean) — Show checkboxes for file selection (default: all files passed)
|
|
354
|
+
- `reactive` (boolean) — Trigger model run on selection change
|
|
163
355
|
- `action` or `button` — Button (its `name` will be passed as a `caller` to the model)
|
|
164
356
|
- `default` — Default value
|
|
165
357
|
- `alias` (string or array of strings) — Alternative names for URL parameter matching. E.g. `"alias": ["f", "file"]` allows `?f=value` or `?file=value` to set this input
|
|
166
358
|
- `display` (string) — Filtrex expression to conditionally show/hide this input. Evaluated against current input values. E.g. `"display": "mode == 'advanced'"` shows the input only when `mode` is `"advanced"`. Supports `len()` for string length
|
|
359
|
+
- `reactive` (boolean) — Trigger a model run when this input changes (see **Execution triggers** below)
|
|
167
360
|
- `disabled` (boolean) — Disables the input in the UI. When combined with `reactive: true`, triggers an initial model run on page load (useful for server-populated values)
|
|
361
|
+
- `enter` (boolean) — If `true` on a `string` input, pressing Enter triggers a model run (useful for chat or search inputs)
|
|
168
362
|
- `raw` (boolean, file input only) — If `true`, pass the raw source to the model instead of reading text in the UI (`File` object for disk files or `{ kind: 'url', url: '...' }` for URL input)
|
|
169
363
|
- `stream` (boolean, file input only) — If `true`, pass an async iterable `ChunkedReader` to the model instead of raw source handles. Supports `for await (const chunk of reader)`, `await reader.text()`, `await reader.bytes()`, and `for await (const line of reader.lines())`. Works in both main-thread and worker execution. Reader metadata (`reader.name`, `reader.size`, `reader.type`) is preserved and remains available in downstream pipeline models
|
|
364
|
+
- `validate` (string) — Filtrex expression for input validation. The variable `value` holds the current input value. Expression must return truthy for valid input. E.g. `"validate": "value >= 0 and value <= 150"`. Runs on every input change (debounced). Invalid inputs show an error message and block model execution
|
|
365
|
+
- `required` (boolean) — Shorthand validation: rejects empty strings, null, undefined, and empty arrays
|
|
366
|
+
- `error` (string) — Custom error message for `validate` or `required` failures (default: `"Invalid value"` / `"Required"`)
|
|
367
|
+
- `columns` (number, 1-12) — Grid column span for this input. When any input has `columns`, the inputs section switches to a 12-column CSS grid. E.g. `"columns": 6` makes the input take half width
|
|
170
368
|
- URL params for file inputs (e.g. `?file=https://...`) auto-load on init, so bookmarkable links run without an extra Load click
|
|
171
|
-
- `outputs` — Outputs definition. Outputs also support `alias` (string) for matching model result keys by alternative names
|
|
369
|
+
- `outputs` — Outputs definition. Outputs also support `alias` (string) for matching model result keys by alternative names. Per-output `columns` (number, 1-12) sets grid column span, same as inputs
|
|
172
370
|
- `name`* — Name of the output
|
|
173
371
|
- `type`* — Type. Possible types:
|
|
174
372
|
- `file` — File output (not displayer, but downloaded)
|
|
175
373
|
- `object` — JavaScript Object
|
|
176
374
|
- `html` or `svg` — SVG element
|
|
177
375
|
- `code` — Code block
|
|
376
|
+
- `markdown` — Rendered Markdown (supports tables, headings, lists, etc.)
|
|
377
|
+
- `image` — Image (`<img>` tag from data URL or URL)
|
|
378
|
+
- `audio` — Audio player (`<audio>` from URL or data URL)
|
|
379
|
+
- `video` — Video player (`<video>` from URL or data URL)
|
|
380
|
+
- `table` — Virtualized table with scrolling
|
|
381
|
+
- `chat` — Chat message list. Accumulates `{role, content}` messages across runs instead of replacing. Renders user/assistant bubbles with Markdown support, auto-scrolls to latest message. See **Chat mode** below
|
|
382
|
+
- `group` — Group of outputs. Use `elements` array for child outputs. Supports `style: 'tabs'` for tabbed display or default blocks (stacked). Child outputs are matched by name against model results
|
|
383
|
+
- `chart` — SVG chart via [Observable Plot](https://observablehq.com/plot/). Model returns array of objects, column-oriented data, or a full Plot config. Schema props: `mark` (line/dot/bar/area/etc.), `x`, `y`, `color`, `width`, `height`. Included in full bundle or load Plot via `imports`
|
|
384
|
+
- `3d` — 3D model viewer via [Three.js](https://threejs.org/). Model returns a URL (GLTF/GLB), data URL, or geometry object `{vertices, faces}`. Schema props: `width`, `height`. Included in full bundle or load Three.js via `imports`
|
|
385
|
+
- `map` — Interactive map via [Leaflet](https://leafletjs.com/). Model returns markers `[{lat, lng, popup}]`, `{center, markers, zoom}`, or GeoJSON. Schema props: `height`, `zoom`, `center`, `tiles`. Included in full bundle or load Leaflet via `imports`
|
|
386
|
+
- `pdf` — Browser-native PDF viewer. Model returns a URL, data URL, Blob, ArrayBuffer, or Uint8Array. Schema prop: `height`. Included in the core bundle
|
|
387
|
+
- `gallery` — CSS grid of images. Model returns array of URLs/data URLs. Click to expand lightbox. Schema props: `columns` (default 3), `gap` (default 8px). Zero-cost, included in core bundle
|
|
388
|
+
- `highlight` — Highlighted text with labels. Model returns `[{text, label, color}]` segments. Unlabeled segments render as plain text. Zero-cost, included in core bundle
|
|
389
|
+
- `gauge` — Semicircle gauge. Model returns a number or `{value, label}`. Schema props: `min` (default 0), `max` (default 100), `label`, `color`. Zero-cost, included in core bundle
|
|
390
|
+
- `number` — Large KPI number display. Model returns a number or `{value, delta, label}`. Delta shown with colored up/down arrow. Schema props: `label`, `prefix` (e.g. `"$"`), `suffix` (e.g. `"%"`), `precision`
|
|
391
|
+
- `alert` — Colored status banner with left accent border. Model returns a string or `{message, type}`. Four variants: `info` (blue, default), `success` (green), `warning` (amber), `error` (red). Schema prop: `alertType` (default type when value is a string)
|
|
392
|
+
- `viewer` — Intelligent media viewer. Model returns a URL string. Auto-detects content type from extension: images (png, jpg, gif, svg, webp), audio (mp3, wav, ogg, flac), video (mp4, webm, mov), or iframe (fallback). Useful with `folder` input for file preview
|
|
178
393
|
- `function` — Render function. Rather than returning a value, a model returns a function that JSEE will call passing the container element
|
|
179
|
-
- `blank` —
|
|
394
|
+
- `blank` — Empty container for custom rendering via `function` output or external code
|
|
180
395
|
- `examples` — List of examples
|
|
181
|
-
-
|
|
182
|
-
- `
|
|
183
|
-
- `
|
|
184
|
-
-
|
|
396
|
+
- **Execution triggers** — by default the model only runs when the user clicks Run. Three schema-level options change this:
|
|
397
|
+
- `autorun` (boolean, default: `false`) — run the model once on first load, then wait for manual Run clicks
|
|
398
|
+
- `reactive` (boolean, default: `false`) — re-run the model on **any** input change (debounced 300ms). Useful for lightweight models where instant feedback is desired
|
|
399
|
+
- `interval` (number, default: `0`) — repeat execution every N milliseconds. `0` means no repetition
|
|
400
|
+
- Per-input `reactive` — set `reactive: true` on an **individual input** to trigger a model run only when that specific input changes (fires immediately, not debounced). Other inputs still require a manual Run click. Useful when one input is interactive (e.g. a slider) but others are expensive to recompute
|
|
401
|
+
|
|
402
|
+
| Option | Scope | When it runs | Debounced |
|
|
403
|
+
|--------|-------|-------------|-----------|
|
|
404
|
+
| `autorun: true` | schema | once on load | no |
|
|
405
|
+
| `reactive: true` | schema | every input change | yes (300ms) |
|
|
406
|
+
| `reactive: true` | input | that input changes | no |
|
|
407
|
+
| `interval: N` | schema | every N ms | no |
|
|
408
|
+
- **Chat mode** — declare an output with `"type": "chat"` to enable conversational UI. The runtime manages state:
|
|
409
|
+
1. User types a message in a text input and presses Run (or Enter if the input has `"enter": true`)
|
|
410
|
+
2. The runtime injects `history` (array of `{role, content}` dicts) into the model payload alongside the user's `message`
|
|
411
|
+
3. The model returns `{chat: "response string"}` (or `{chat: {role, content}}`)
|
|
412
|
+
4. The runtime appends both the user message and assistant response to the chat output's internal `_messages` array, clears the input, and auto-scrolls
|
|
413
|
+
5. Messages render with Markdown support (code blocks, bold, links, tables)
|
|
414
|
+
|
|
415
|
+
Works with both Workers (postMessage) and server POST — no special execution mode needed. Python shorthand: `jsee.serve(fn, chat=True)` auto-generates the schema from `fn(message, history) -> str`
|
|
416
|
+
|
|
417
|
+
- **Input persistence** — by default, JSEE saves input values to `localStorage` and restores them on page refresh. Priority: URL params > localStorage > schema defaults. Set `persist: false` in the schema to disable. Clicking Reset clears saved values
|
|
418
|
+
- **Notifications** — set `notify: true` in the schema to show a browser notification when a run completes while the tab is hidden. JSEE requests permission on first load and fires `new Notification()` after successful runs only
|
|
419
|
+
- **Streaming outputs (SSE)** — set `model.stream: true` to enable Server-Sent Events streaming. The POST handler reads `text/event-stream` responses and calls `output()` on each `data:` line for progressive results. Python generators are auto-detected:
|
|
420
|
+
```python
|
|
421
|
+
def stream_count(n: int = 5):
|
|
422
|
+
for i in range(n):
|
|
423
|
+
yield {'count': i}
|
|
424
|
+
jsee.serve(stream_count, stream=True)
|
|
425
|
+
```
|
|
426
|
+
- **Efficient binary outputs** — large base64 image data URLs (>50KB) in `image` outputs are automatically converted to `URL.createObjectURL()` blob URLs, reducing memory usage by ~33%. Previous blob URLs are revoked on each update
|
|
427
|
+
- **Typed array passing** — declare `arrayBuffer: true` on an input to convert JS arrays to typed arrays before passing to workers/WASM. Set `dtype` to control the type (`float32`, `float64`, `uint8`, `int32`, etc., default: `float64`). Typed arrays are transferred with zero-copy semantics via `postMessage` transferables
|
|
428
|
+
```json
|
|
429
|
+
"inputs": [{ "name": "data", "type": "string", "arrayBuffer": true, "dtype": "float32" }]
|
|
430
|
+
```
|
|
431
|
+
- Runtime cancellation: call `jsee.cancelCurrentRun()` on the JSEE instance to request stop of the active run. Long-running models should check `ctx.isCancelled()` and return early:
|
|
432
|
+
```javascript
|
|
433
|
+
async function model (inputs, ctx) {
|
|
434
|
+
for (let i = 0; i < inputs.steps; i++) {
|
|
435
|
+
if (ctx.isCancelled()) throw new Error('Cancelled')
|
|
436
|
+
await doStep(i)
|
|
437
|
+
ctx.progress(Math.round(100 * (i + 1) / inputs.steps))
|
|
438
|
+
}
|
|
439
|
+
return { done: true }
|
|
440
|
+
}
|
|
441
|
+
```
|
|
185
442
|
- Schema validation — JSEE validates schema structure during initialization and logs warnings for non-critical issues (e.g. unknown input types, malformed aliases)
|
|
186
443
|
- `jsee.download(title)` — Downloads a self-contained HTML file that works offline. All external scripts are inlined and the schema/model/imports are cached. `title` defaults to `'output'`
|
|
187
444
|
- `page` (CLI only) — Page metadata for generated HTML:
|
|
@@ -191,35 +448,306 @@ Extra blocks can be provided for further customization:
|
|
|
191
448
|
- `social` (object) — Social media links: `twitter`, `github`, `facebook`, `linkedin`, `instagram`, `youtube` (values are usernames/handles)
|
|
192
449
|
- `org` (object) — Organization footer: `name`, `url`, `description`
|
|
193
450
|
|
|
194
|
-
|
|
451
|
+
## Smart output auto-detection
|
|
452
|
+
|
|
453
|
+
When outputs are not explicitly defined in the schema, or when a model returns keys that don't match any named output, JSEE infers the output type from the value:
|
|
454
|
+
|
|
455
|
+
| Value | Inferred type |
|
|
456
|
+
|---|---|
|
|
457
|
+
| Array of objects | `table` |
|
|
458
|
+
| Array of image URL strings (`.png`, `.jpg`, `.gif`, `.svg`, `.webp`) | `gallery` |
|
|
459
|
+
| Other arrays | `object` |
|
|
460
|
+
| `data:image/*` string | `image` |
|
|
461
|
+
| `data:audio/*` string | `audio` |
|
|
462
|
+
| `data:video/*` string | `video` |
|
|
463
|
+
| `data:application/pdf` string | `pdf` |
|
|
464
|
+
| String ending in `.png`, `.jpg`, `.gif`, `.svg`, `.webp` | `image` |
|
|
465
|
+
| String ending in `.mp3`, `.wav`, `.ogg`, `.flac` | `audio` |
|
|
466
|
+
| String ending in `.mp4`, `.webm`, `.mov` | `video` |
|
|
467
|
+
| String ending in `.pdf` | `pdf` |
|
|
468
|
+
| String ending in `.md` | `markdown` |
|
|
469
|
+
| String with newlines and > 200 characters | `code` |
|
|
470
|
+
| Other strings | `string` |
|
|
471
|
+
| Numbers, booleans | `string` |
|
|
472
|
+
| Objects | `object` |
|
|
473
|
+
|
|
474
|
+
## JSEE instance API
|
|
475
|
+
|
|
476
|
+
After creating an instance with `new JSEE({schema, container})`, these methods are available:
|
|
477
|
+
|
|
478
|
+
| Method | Description |
|
|
479
|
+
|---|---|
|
|
480
|
+
| `jsee.run(caller)` | Execute the model pipeline. `caller` can be `'run'`, `'autorun'`, `'reactive'`, or a custom button name |
|
|
481
|
+
| `jsee.output(result)` | Process and render results to output cards |
|
|
482
|
+
| `jsee.cancelCurrentRun()` | Stop the active run. Rejects the current run promise, sets cancellation state, and signals/terminates workers |
|
|
483
|
+
| `jsee.isCancelled()` | Returns `true` if cancellation was requested |
|
|
484
|
+
| `jsee.progress(value)` | Set progress bar: `0`-`100` for determinate, `null` for indeterminate |
|
|
485
|
+
| `jsee.download(title)` | Export current app as a self-contained offline HTML file |
|
|
486
|
+
| `jsee.destroy()` | Cleanup: cancel runs, terminate workers, unmount Vue app, revoke blob URLs |
|
|
487
|
+
| `jsee.notify(text)` | Show a success toast notification |
|
|
488
|
+
| `jsee.log(...args)` | Log to browser console and optional `#log` DOM element |
|
|
489
|
+
|
|
490
|
+
JSEE is part of the [StatSim](https://statsim.com) ecosystem. The schema/runtime contract is the public surface; lower-level packaging and renderer internals may continue to evolve.
|
|
491
|
+
|
|
492
|
+
## CLI — Node.js
|
|
195
493
|
|
|
196
|
-
|
|
494
|
+
```
|
|
495
|
+
jsee [schema.json] [data...] [options]
|
|
496
|
+
jsee init [template] [--html]
|
|
497
|
+
```
|
|
197
498
|
|
|
198
|
-
|
|
199
|
-
- `--outputs`, `-o` — Output file path(s), comma-separated (HTML, JSON, or both)
|
|
200
|
-
- `--description`, `-d` — Markdown file to include as app description
|
|
201
|
-
- `--port`, `-p` — Dev server port (default: `3000`)
|
|
202
|
-
- `--version`, `-v` — JSEE runtime version (`latest`, `dev`, or semver)
|
|
203
|
-
- `--fetch`, `-f` — Bundle everything into a single offline HTML: fetches the JSEE runtime, reads `model`/`view`/`render` code from disk, and resolves imports. Local files are detected by checking the filesystem (so bare paths like `dist/core.js` work alongside `./relative.js`); anything not found locally is fetched from CDN. All code is stored in hidden `<script data-src="...">` elements
|
|
204
|
-
- `--runtime`, `-r` — Select runtime source for generated HTML:
|
|
205
|
-
- `auto` (default): `inline` when `--fetch` is used, otherwise `cdn` for file output and `local` for dev server mode
|
|
206
|
-
- `local`: use `http://localhost:<port>/dist/...`
|
|
207
|
-
- `cdn`: use jsdelivr runtime URL
|
|
208
|
-
- `inline`: embed runtime code directly in HTML
|
|
209
|
-
- Any other value is used as a custom `<script src="...">` path/URL (e.g. `./node_modules/@jseeio/jsee/dist/jsee.js`)
|
|
210
|
-
- `--cdn`, `-c` — Rewrite model URLs for CDN deployment (can be a base URL string or boolean to infer from `package.json`)
|
|
211
|
-
- `--execute`, `-e` — Run models server-side (see below)
|
|
212
|
-
- `--verbose` — Enable verbose logging
|
|
213
|
-
- `--help`, `-h` — Show usage info
|
|
499
|
+
### Commands
|
|
214
500
|
|
|
215
|
-
|
|
501
|
+
#### `jsee init [template]`
|
|
216
502
|
|
|
217
|
-
|
|
503
|
+
Scaffold a new project. Templates: `minimal` (default), `chat`.
|
|
218
504
|
|
|
219
505
|
```bash
|
|
220
|
-
jsee schema.json
|
|
506
|
+
jsee init # schema.json + model.js + README.md
|
|
507
|
+
jsee init chat # chat template
|
|
508
|
+
jsee init --html # single index.html with CDN script
|
|
221
509
|
```
|
|
222
510
|
|
|
223
|
-
|
|
511
|
+
#### `jsee <schema> [data...]`
|
|
512
|
+
|
|
513
|
+
Start a dev server or generate a static HTML file from a schema.
|
|
514
|
+
|
|
515
|
+
```bash
|
|
516
|
+
jsee schema.json # dev server on port 3000
|
|
517
|
+
jsee schema.json -o app.html # generate static HTML
|
|
518
|
+
jsee schema.json -o app.html -f # self-contained HTML with bundled runtime
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### Options
|
|
522
|
+
|
|
523
|
+
| Flag | Description |
|
|
524
|
+
|---|---|
|
|
525
|
+
| `-i, --inputs <file>` | Input schema JSON file (default: `schema.json`) |
|
|
526
|
+
| `-o, --outputs <file>` | Output file path(s), comma-separated (HTML, JSON) |
|
|
527
|
+
| `-d, --description <file>` | Markdown file to include as app description |
|
|
528
|
+
| `-p, --port <number>` | Dev server port (default: `3000`) |
|
|
529
|
+
| `-v, --version <version>` | JSEE runtime version (`latest`, `dev`, or semver) |
|
|
530
|
+
| `-f, --fetch` | Bundle runtime + all deps into a single offline HTML |
|
|
531
|
+
| `-e, --execute` | Run models server-side (auto-enabled when serving local .js models) |
|
|
532
|
+
| `--client` | Force client-side execution (disable auto server-side) |
|
|
533
|
+
| `-c, --cdn <url\|bool>` | Rewrite model URLs for CDN deployment |
|
|
534
|
+
| `-r, --runtime <mode>` | Runtime source: `auto\|local\|cdn\|inline` or a custom URL/path |
|
|
535
|
+
| `--verbose` | Enable verbose logging |
|
|
536
|
+
| `--help, -h` | Show usage info |
|
|
537
|
+
|
|
538
|
+
#### `--fetch`
|
|
539
|
+
|
|
540
|
+
Bundles everything into a single offline HTML: the JSEE runtime, model/view/render code, and all imports are stored in hidden `<script data-src="...">` elements. Local files are detected by checking the filesystem (so bare paths like `dist/core.js` work alongside `./relative.js`); anything not found locally is fetched from CDN.
|
|
541
|
+
|
|
542
|
+
#### `--runtime`
|
|
543
|
+
|
|
544
|
+
Select the runtime source for generated HTML:
|
|
545
|
+
- `auto` (default): `inline` when `--fetch`, otherwise `cdn` for file output and `local` for dev server
|
|
546
|
+
- `local`: `http://localhost:<port>/dist/...`
|
|
547
|
+
- `cdn`: jsdelivr CDN URL
|
|
548
|
+
- `inline`: embed runtime code directly in HTML
|
|
549
|
+
- Any other value is used as a custom `<script src="...">` path/URL
|
|
550
|
+
|
|
551
|
+
### Data inputs
|
|
552
|
+
|
|
553
|
+
Positional arguments after the schema file and named `--key=value` arguments are mapped to schema inputs. Values are auto-detected:
|
|
554
|
+
|
|
555
|
+
| Value | Detected as |
|
|
556
|
+
|---|---|
|
|
557
|
+
| `42`, `3.14` | Number |
|
|
558
|
+
| `'[1,2,3]'`, `'{"a":1}'` | JSON (array or object) |
|
|
559
|
+
| `data.csv` (existing file) | File path |
|
|
560
|
+
| `hello` | String |
|
|
561
|
+
|
|
562
|
+
Inputs set from the CLI are locked (non-editable) in the GUI and used as defaults for server-side execution.
|
|
563
|
+
|
|
564
|
+
```bash
|
|
565
|
+
# Positional — mapped to inputs in schema order
|
|
566
|
+
jsee schema.json 42 hello
|
|
567
|
+
|
|
568
|
+
# Named — matched by input name
|
|
569
|
+
jsee schema.json --a=100 --b=200
|
|
570
|
+
|
|
571
|
+
# File path
|
|
572
|
+
jsee schema.json data.csv
|
|
573
|
+
|
|
574
|
+
# Mixed
|
|
575
|
+
jsee schema.json data.csv --format=json
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### Server-side execution
|
|
579
|
+
|
|
580
|
+
When serving (no `-o` flag), JSEE automatically enables server-side execution if all models point to local `.js` files. Use `--client` to force browser execution.
|
|
581
|
+
|
|
582
|
+
```bash
|
|
583
|
+
jsee schema.json # auto server-side (local .js models)
|
|
584
|
+
jsee schema.json --client # force browser execution
|
|
585
|
+
jsee schema.json -e -p 3000 # explicit server-side on port 3000
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
### File and folder serving
|
|
589
|
+
|
|
590
|
+
JSEE can serve individual files or entire folders without a schema or model:
|
|
591
|
+
|
|
592
|
+
```bash
|
|
593
|
+
jsee report.pdf # serve PDF with viewer
|
|
594
|
+
jsee photo.png # serve image
|
|
595
|
+
jsee data.csv # serve CSV as table
|
|
596
|
+
jsee data/ # serve folder with file browser
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
For single files, JSEE auto-detects the output type from the file extension (image, pdf, audio, video, table, markdown, code). For folders, JSEE creates a file browser with selection checkboxes, stats summary, and a preview of the selected file.
|
|
600
|
+
|
|
601
|
+
Output type auto-detection also works for model results — if a model returns a string ending in `.png`, it renders as an image automatically.
|
|
602
|
+
|
|
603
|
+
### Serve bar
|
|
604
|
+
|
|
605
|
+
When serving, a top bar appears with the server address, a Save HTML button, and (when server-side execution is active) a Browser/Server toggle to switch execution mode. Input values are preserved across the switch via localStorage. The serve bar is not included in generated output files or saved bundles.
|
|
606
|
+
|
|
607
|
+
## CLI — Python
|
|
608
|
+
|
|
609
|
+
```
|
|
610
|
+
jsee <target> [function] [data...] [options]
|
|
611
|
+
jsee init [template]
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
### Commands
|
|
615
|
+
|
|
616
|
+
#### `jsee init [template]`
|
|
617
|
+
|
|
618
|
+
Scaffold a new project. Templates: `minimal` (default), `chat`. Generates `schema.json` + `model.py` + `README.md`.
|
|
619
|
+
|
|
620
|
+
```bash
|
|
621
|
+
jsee init # minimal template
|
|
622
|
+
jsee init chat # chat template
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
#### `jsee <file.py> <function> [data...]`
|
|
626
|
+
|
|
627
|
+
Serve a Python function as a web app with auto-generated GUI and REST API.
|
|
628
|
+
|
|
629
|
+
```bash
|
|
630
|
+
jsee example.py greet # serve function
|
|
631
|
+
jsee example.py greet --port=8080 # custom port
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
#### `jsee <schema.json>`
|
|
635
|
+
|
|
636
|
+
Serve from a pre-built schema file.
|
|
637
|
+
|
|
638
|
+
```bash
|
|
639
|
+
jsee schema.json
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
### Options
|
|
643
|
+
|
|
644
|
+
| Flag | Description |
|
|
645
|
+
|---|---|
|
|
646
|
+
| `--host <addr>` | Host to bind to (default: `0.0.0.0`) |
|
|
647
|
+
| `--port <number>` | Port to listen on (default: `5050`) |
|
|
648
|
+
|
|
649
|
+
### Data inputs
|
|
650
|
+
|
|
651
|
+
Same as Node.js — positional args after the function name and `--key=value` args are mapped to function parameters. Values are auto-detected (numbers, JSON, file paths, strings). Inputs set from the CLI are locked in the GUI.
|
|
652
|
+
|
|
653
|
+
```bash
|
|
654
|
+
jsee example.py greet Alice 5 # positional data
|
|
655
|
+
jsee example.py greet --name=Alice # named data
|
|
656
|
+
jsee schema.json 42 hello # positional data with schema
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
### API endpoints
|
|
660
|
+
|
|
661
|
+
Every server (both Node.js with `--execute` and Python) exposes these endpoints:
|
|
662
|
+
|
|
663
|
+
| Route | Method | Description |
|
|
664
|
+
|---|---|---|
|
|
665
|
+
| `/` | GET | Interactive GUI |
|
|
666
|
+
| `/api` | GET | Schema and endpoint discovery |
|
|
667
|
+
| `/api/openapi.json` | GET | Auto-generated OpenAPI 3.1 spec |
|
|
668
|
+
| `/{modelName}` | POST | Execute model with JSON or multipart input |
|
|
669
|
+
|
|
670
|
+
Both servers support `application/json` and `multipart/form-data` POST bodies, CORS (`Access-Control-Allow-Origin: *`), and return consistent JSON errors for 404/400/500.
|
|
671
|
+
|
|
672
|
+
```bash
|
|
673
|
+
# Run the model via API (JSON)
|
|
674
|
+
curl -X POST http://localhost:3000/modelName \
|
|
675
|
+
-H 'Content-Type: application/json' \
|
|
676
|
+
-d '{"x": 3, "y": 4}'
|
|
677
|
+
|
|
678
|
+
# Run with file upload (multipart)
|
|
679
|
+
curl -X POST http://localhost:3000/modelName \
|
|
680
|
+
-F 'text=hello' \
|
|
681
|
+
-F 'file=@image.png'
|
|
682
|
+
|
|
683
|
+
# Get OpenAPI spec
|
|
684
|
+
curl http://localhost:3000/api/openapi.json
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
#### Return value serialization
|
|
688
|
+
|
|
689
|
+
Both servers normalize model return values consistently:
|
|
690
|
+
|
|
691
|
+
| Return type | JSON response |
|
|
692
|
+
|---|---|
|
|
693
|
+
| Object/dict | returned as-is |
|
|
694
|
+
| Primitive (number, string, bool) | `{"result": value}` |
|
|
695
|
+
| Tuple/list (Python) | `{"result": [a, b]}` |
|
|
696
|
+
| Buffer/bytes | `{"result": "data:image/png;base64,..."}` |
|
|
697
|
+
| PIL Image (Python) | `{"result": "data:image/png;base64,..."}` |
|
|
698
|
+
| list[dict] (Python) | `{"result": {"columns": [...], "rows": [...]}}` |
|
|
699
|
+
|
|
700
|
+
## Python
|
|
701
|
+
|
|
702
|
+
JSEE also ships a Python package (`py/`) that turns Python functions into web apps with the same GUI and API. Zero dependencies beyond Python stdlib.
|
|
703
|
+
|
|
704
|
+
```bash
|
|
705
|
+
cd py && pip install -e .
|
|
706
|
+
jsee example.py sum
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
Or programmatically:
|
|
710
|
+
```python
|
|
711
|
+
from typing import Annotated, Literal
|
|
712
|
+
import jsee
|
|
713
|
+
|
|
714
|
+
def calculator(
|
|
715
|
+
num1: float,
|
|
716
|
+
op: Literal['add', 'subtract', 'multiply', 'divide'],
|
|
717
|
+
num2: float,
|
|
718
|
+
precision: Annotated[int, jsee.Slider(0, 10)] = 2
|
|
719
|
+
) -> dict:
|
|
720
|
+
"""A simple calculator"""
|
|
721
|
+
ops = {'add': num1 + num2, 'subtract': num1 - num2,
|
|
722
|
+
'multiply': num1 * num2, 'divide': num1 / num2 if num2 else 0}
|
|
723
|
+
return {'result': round(ops[op], precision)}
|
|
724
|
+
|
|
725
|
+
jsee.serve(calculator, port=5050)
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
Python type hints are auto-mapped to GUI widgets: `Literal` → dropdown, `Annotated[float, jsee.Slider()]` → slider, `bool` → checkbox, `Enum` → dropdown. See [`py/README.md`](py/README.md) for full Python documentation.
|
|
729
|
+
|
|
730
|
+
### WSGI deployment
|
|
731
|
+
|
|
732
|
+
For production deployment, use `create_app()` to get a standard WSGI application:
|
|
733
|
+
|
|
734
|
+
```python
|
|
735
|
+
# app.py
|
|
736
|
+
import jsee
|
|
737
|
+
|
|
738
|
+
def multiply(x: float = 5) -> dict:
|
|
739
|
+
return {'result': x * 2}
|
|
740
|
+
|
|
741
|
+
app = jsee.create_app(multiply)
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
Deploy with gunicorn, uWSGI, or any WSGI server:
|
|
745
|
+
```bash
|
|
746
|
+
gunicorn app:app
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
`create_app()` accepts the same arguments as `serve()` — functions, dicts, or schema.json paths. Note: SSE streaming is not supported in basic WSGI.
|
|
750
|
+
|
|
751
|
+
## Changelog
|
|
224
752
|
|
|
225
753
|
See `CHANGELOG.md`.
|