@rip-lang/ui 0.3.3 → 0.3.5
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/package.json +1 -1
- package/serve.rip +30 -35
- package/ui.rip +1 -1
package/package.json
CHANGED
package/serve.rip
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
# @rip-lang/ui/serve — Rip UI Server Middleware
|
|
3
3
|
# ==============================================================================
|
|
4
4
|
#
|
|
5
|
-
# Serves the Rip UI runtime
|
|
5
|
+
# Serves the Rip UI runtime, auto-generated app bundles, and component files.
|
|
6
|
+
# Hot-reload SSE is handled by rip-server; this middleware registers watch dirs.
|
|
6
7
|
#
|
|
7
8
|
# Usage:
|
|
8
9
|
# import { ripUI } from '@rip-lang/ui/serve'
|
|
@@ -13,14 +14,13 @@
|
|
|
13
14
|
# dir: string — app directory on disk (default: '.')
|
|
14
15
|
# components: string — directory for page components, relative to dir (default: 'components')
|
|
15
16
|
# includes: array — directories for shared components, relative to dir (default: [])
|
|
16
|
-
# watch: boolean — enable
|
|
17
|
+
# watch: boolean — enable hot-reload (registers watch dirs with rip-server)
|
|
17
18
|
# state: object — initial app state passed via bundle
|
|
18
19
|
# title: string — document title
|
|
19
20
|
#
|
|
20
21
|
# ==============================================================================
|
|
21
22
|
|
|
22
23
|
import { get } from '@rip-lang/api'
|
|
23
|
-
import { watch as fsWatch } from 'node:fs'
|
|
24
24
|
|
|
25
25
|
export ripUI = (opts = {}) ->
|
|
26
26
|
prefix = opts.app or ''
|
|
@@ -48,7 +48,7 @@ export ripUI = (opts = {}) ->
|
|
|
48
48
|
ripUI._registered = true
|
|
49
49
|
|
|
50
50
|
# ----------------------------------------------------------------------------
|
|
51
|
-
# Route: {prefix}/components/* — individual .rip component files
|
|
51
|
+
# Route: {prefix}/components/* — individual .rip component files
|
|
52
52
|
# Route: {prefix}/bundle — app bundle (components + data as JSON)
|
|
53
53
|
# ----------------------------------------------------------------------------
|
|
54
54
|
|
|
@@ -56,42 +56,37 @@ export ripUI = (opts = {}) ->
|
|
|
56
56
|
name = c.req.path.slice("#{prefix}/components/".length)
|
|
57
57
|
c.send "#{componentsDir}/#{name}", 'text/plain; charset=UTF-8'
|
|
58
58
|
|
|
59
|
-
bundleCache = null
|
|
60
|
-
bundleDirty = true
|
|
61
|
-
|
|
62
|
-
# Invalidate bundle cache when components change
|
|
63
|
-
if enableWatch
|
|
64
|
-
fsWatch componentsDir, { recursive: true }, (event, filename) ->
|
|
65
|
-
bundleDirty = true if filename?.endsWith('.rip')
|
|
66
|
-
for incDir in includeDirs
|
|
67
|
-
fsWatch incDir, { recursive: true }, (event, filename) ->
|
|
68
|
-
bundleDirty = true if filename?.endsWith('.rip')
|
|
69
|
-
|
|
70
59
|
get "#{prefix}/bundle", (c) ->
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
60
|
+
glob = new Bun.Glob("**/*.rip")
|
|
61
|
+
components = {}
|
|
62
|
+
paths = Array.from(glob.scanSync(componentsDir))
|
|
63
|
+
for path in paths
|
|
64
|
+
components["components/#{path}"] = Bun.file("#{componentsDir}/#{path}").text!
|
|
65
|
+
|
|
66
|
+
for dir in includeDirs
|
|
67
|
+
incPaths = Array.from(glob.scanSync(dir))
|
|
68
|
+
for path in incPaths
|
|
69
|
+
key = "components/_lib/#{path}"
|
|
70
|
+
components[key] = Bun.file("#{dir}/#{path}").text! unless components[key]
|
|
77
71
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
components[key] = Bun.file("#{dir}/#{path}").text! unless components[key]
|
|
72
|
+
data = {}
|
|
73
|
+
data.title = appTitle if appTitle
|
|
74
|
+
data.watch = enableWatch
|
|
75
|
+
if appState
|
|
76
|
+
data[k] = v for k, v of appState
|
|
84
77
|
|
|
85
|
-
|
|
86
|
-
data.title = appTitle if appTitle
|
|
87
|
-
data.watch = enableWatch
|
|
88
|
-
if appState
|
|
89
|
-
data[k] = v for k, v of appState
|
|
78
|
+
new Response JSON.stringify({ components, data }), headers: { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' }
|
|
90
79
|
|
|
91
|
-
|
|
92
|
-
|
|
80
|
+
# ----------------------------------------------------------------------------
|
|
81
|
+
# Register watch directories with rip-server via control socket
|
|
82
|
+
# ----------------------------------------------------------------------------
|
|
93
83
|
|
|
94
|
-
|
|
84
|
+
if enableWatch and process.env.SOCKET_PREFIX
|
|
85
|
+
ctl = "/tmp/#{process.env.SOCKET_PREFIX}.ctl.sock"
|
|
86
|
+
dirs = [componentsDir, ...includeDirs]
|
|
87
|
+
body = JSON.stringify({ op: 'watch', prefix, dirs })
|
|
88
|
+
fetch('http://localhost/watch', { method: 'POST', body, headers: { 'content-type': 'application/json' }, unix: ctl }).catch (e) ->
|
|
89
|
+
console.warn "rip-ui: watch registration failed: #{e.message}"
|
|
95
90
|
|
|
96
91
|
# Return pass-through middleware
|
|
97
92
|
(c, next) -> next!()
|
package/ui.rip
CHANGED
|
@@ -906,7 +906,7 @@ export launch = (appBase = '', opts = {}) ->
|
|
|
906
906
|
|
|
907
907
|
# Connect SSE watch if enabled
|
|
908
908
|
if bundle.data?.watch
|
|
909
|
-
connectWatch
|
|
909
|
+
connectWatch "#{appBase}/watch"
|
|
910
910
|
|
|
911
911
|
# Expose for console and dev tools
|
|
912
912
|
if typeof window isnt 'undefined'
|