@jxsuite/server 0.10.2 → 0.11.0
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/README.md +80 -0
- package/package.json +1 -1
- package/src/server.js +2 -0
- package/src/studio-api.js +1 -3
- package/src/watch.js +8 -2
package/README.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# `@jxsuite/server`
|
|
2
|
+
|
|
3
|
+
> Bun-native development server for Jx projects with live reload, proxy resolution, and Studio API.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`@jxsuite/server` provides a single `createDevServer()` call that covers live reload, `$src`/`$prototype` proxy resolution (Node.js-side), `timing: "server"` function execution, a Studio filesystem API, and OXC-powered code services.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
bun add @jxsuite/server
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
import { createDevServer } from "@jxsuite/server";
|
|
19
|
+
|
|
20
|
+
await createDevServer({
|
|
21
|
+
root: "./my-project",
|
|
22
|
+
port: 3000,
|
|
23
|
+
builds: [{ entrypoints: ["./index.html"], outdir: "./dist", label: "app" }],
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Endpoints
|
|
28
|
+
|
|
29
|
+
### Live reload — `GET /__reload`
|
|
30
|
+
|
|
31
|
+
SSE endpoint. `chokidar` watches the project root and pushes change events to connected browsers, triggering automatic page reload.
|
|
32
|
+
|
|
33
|
+
### `$prototype`/`$src` proxy — `POST /__jx_resolve__`
|
|
34
|
+
|
|
35
|
+
Resolves external `$prototype` data sources server-side. Supports `.js` modules and `.class.json` schemas. Avoids browser CORS issues and enables Node.js-only dependencies (`fs`, `glob`, etc.).
|
|
36
|
+
|
|
37
|
+
### Server functions — `POST /__jx_server__`
|
|
38
|
+
|
|
39
|
+
Executes `timing: "server"` function entries during development. The runtime sends `{ $src, $export, arguments }` and receives the return value as JSON.
|
|
40
|
+
|
|
41
|
+
### Studio filesystem API — `/__studio/*`
|
|
42
|
+
|
|
43
|
+
REST API for the Studio visual builder:
|
|
44
|
+
|
|
45
|
+
| Method | Path | Description |
|
|
46
|
+
| -------------- | ----------------------- | -------------------------- |
|
|
47
|
+
| GET | `/__studio/project` | Project metadata |
|
|
48
|
+
| GET | `/__studio/files` | Directory listing |
|
|
49
|
+
| GET/PUT/DELETE | `/__studio/file` | Read / write / delete file |
|
|
50
|
+
| POST | `/__studio/file/rename` | Rename or move file |
|
|
51
|
+
| GET | `/__studio/components` | Discover custom elements |
|
|
52
|
+
| GET | `/__studio/search` | Search file contents |
|
|
53
|
+
|
|
54
|
+
All file operations are constrained to the project root (path traversal is rejected).
|
|
55
|
+
|
|
56
|
+
### Code services — `/__studio/code/*`
|
|
57
|
+
|
|
58
|
+
OXC-powered tools for the Studio function body editor:
|
|
59
|
+
|
|
60
|
+
| Endpoint | Tool | Description |
|
|
61
|
+
| ---------------------------- | ---------------- | ------------------- |
|
|
62
|
+
| `POST /__studio/code/format` | oxfmt | Format a JS snippet |
|
|
63
|
+
| `POST /__studio/code/minify` | `Bun.Transpiler` | Minify a JS snippet |
|
|
64
|
+
| `POST /__studio/code/lint` | oxlint | Lint a JS snippet |
|
|
65
|
+
|
|
66
|
+
## Build pipeline
|
|
67
|
+
|
|
68
|
+
`buildAll(options)` uses `Bun.build` to bundle entrypoints. Incremental rebuilds (`rebuild(changedPath)`) are triggered by the file watcher and reprocess only affected entrypoints.
|
|
69
|
+
|
|
70
|
+
## Dependencies
|
|
71
|
+
|
|
72
|
+
| Package | Purpose |
|
|
73
|
+
| ---------- | ----------------------------- |
|
|
74
|
+
| `chokidar` | File watching for live reload |
|
|
75
|
+
|
|
76
|
+
Bun built-ins used: `Bun.serve`, `Bun.build`, `Bun.Transpiler`.
|
|
77
|
+
|
|
78
|
+
## License
|
|
79
|
+
|
|
80
|
+
MIT
|
package/package.json
CHANGED
package/src/server.js
CHANGED
package/src/studio-api.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { resolve, relative, basename, dirname, isAbsolute } from "node:path";
|
|
11
11
|
import { readdir, stat, readFile, writeFile, rename, unlink, mkdir } from "node:fs/promises";
|
|
12
12
|
import { readFileSync, existsSync } from "node:fs";
|
|
13
|
+
import { transpileJxMarkdown } from "@jxsuite/parser/transpile";
|
|
13
14
|
|
|
14
15
|
/** Normalise a path to forward slashes (Windows `path` module returns backslashes). */
|
|
15
16
|
const fwd = (/** @type {string} */ p) => p.replaceAll("\\", "/");
|
|
@@ -325,13 +326,10 @@ export async function handleStudioApi(req, url, root, activeProjectRoot = null)
|
|
|
325
326
|
/** @type {any} */
|
|
326
327
|
let content;
|
|
327
328
|
if (match.endsWith(".md")) {
|
|
328
|
-
// Parse YAML frontmatter to check for Jx component
|
|
329
329
|
const source = await readFile(fp, "utf8");
|
|
330
330
|
const fmMatch = source.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
331
331
|
if (!fmMatch) continue;
|
|
332
|
-
// Quick check: must have tagName with hyphen
|
|
333
332
|
if (!/^tagName:\s*.+-.+/m.test(fmMatch[1])) continue;
|
|
334
|
-
const { transpileJxMarkdown } = await import("@jxsuite/parser/transpile");
|
|
335
333
|
content = transpileJxMarkdown(source);
|
|
336
334
|
} else {
|
|
337
335
|
content = JSON.parse(await readFile(fp, "utf8"));
|
package/src/watch.js
CHANGED
|
@@ -40,6 +40,8 @@ function shouldIgnore(pathname, ignore) {
|
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
export { shouldIgnore };
|
|
44
|
+
|
|
43
45
|
export const SSE_SCRIPT = `\n<script>new EventSource('/__reload').onmessage=()=>location.reload()</script>`;
|
|
44
46
|
|
|
45
47
|
/** @param {string} html */
|
|
@@ -55,7 +57,11 @@ export function injectSSE(html) {
|
|
|
55
57
|
* @param {string} root - Absolute path to watch
|
|
56
58
|
* @param {any[]} builds - Build entries (for selective rebuild)
|
|
57
59
|
* @param {{ ignore?: string[]; debounce?: number; reloadOnAnyChange?: boolean }} [opts]
|
|
58
|
-
* @returns {{
|
|
60
|
+
* @returns {{
|
|
61
|
+
* broadcast: () => void;
|
|
62
|
+
* handleSSE: () => Response;
|
|
63
|
+
* watcher: import("chokidar").FSWatcher;
|
|
64
|
+
* }}
|
|
59
65
|
*/
|
|
60
66
|
export function createWatcher(root, builds, opts = {}) {
|
|
61
67
|
const ignore = opts.ignore ?? DEFAULT_IGNORE;
|
|
@@ -132,5 +138,5 @@ export function createWatcher(root, builds, opts = {}) {
|
|
|
132
138
|
}, debounceMs);
|
|
133
139
|
});
|
|
134
140
|
|
|
135
|
-
return { broadcast, handleSSE };
|
|
141
|
+
return { broadcast, handleSSE, watcher };
|
|
136
142
|
}
|