@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.
Files changed (3) hide show
  1. package/package.json +1 -1
  2. package/serve.rip +30 -35
  3. package/ui.rip +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rip-lang/ui",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "Zero-build reactive web framework — rip.js + ui.rip + launch(url)",
5
5
  "type": "module",
6
6
  "main": "ui.rip",
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 and auto-generated app bundles.
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 bundle cache invalidation on file changes (default: false)
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 (for hot-reload)
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
- if bundleDirty or not bundleCache
72
- glob = new Bun.Glob("**/*.rip")
73
- components = {}
74
- paths = Array.from(glob.scanSync(componentsDir))
75
- for path in paths
76
- components["components/#{path}"] = Bun.file("#{componentsDir}/#{path}").text!
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
- # Merge external include directories into components/_lib/
79
- for dir in includeDirs
80
- incPaths = Array.from(glob.scanSync(dir))
81
- for path in incPaths
82
- key = "components/_lib/#{path}"
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
- data = {}
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
- bundleCache = JSON.stringify({ components, data })
92
- bundleDirty = false
80
+ # ----------------------------------------------------------------------------
81
+ # Register watch directories with rip-server via control socket
82
+ # ----------------------------------------------------------------------------
93
83
 
94
- new Response bundleCache, headers: { 'Content-Type': 'application/json' }
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 '/watch'
909
+ connectWatch "#{appBase}/watch"
910
910
 
911
911
  # Expose for console and dev tools
912
912
  if typeof window isnt 'undefined'