@rip-lang/server 1.3.67 → 1.3.69
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/middleware.rip +54 -33
- package/package.json +2 -2
package/middleware.rip
CHANGED
|
@@ -473,20 +473,28 @@ pre{margin:0;white-space:pre-wrap;word-break:break-word}
|
|
|
473
473
|
# Hot-reload SSE is handled by rip-server; this middleware registers watch dirs.
|
|
474
474
|
#
|
|
475
475
|
# Options:
|
|
476
|
-
# dir: string
|
|
477
|
-
# routes: string
|
|
478
|
-
#
|
|
479
|
-
#
|
|
480
|
-
#
|
|
481
|
-
#
|
|
482
|
-
#
|
|
476
|
+
# dir: string — app directory on disk (default: '.')
|
|
477
|
+
# routes: string — page components directory, relative to dir (default: 'routes')
|
|
478
|
+
# bundle: string[]|object — directories for bundle endpoint(s) (default: ['components'])
|
|
479
|
+
# Array: single bundle at {prefix}/bundle (legacy)
|
|
480
|
+
# Object: named bundles — { ui: [...], app: [...] } → {prefix}/ui, {prefix}/app
|
|
481
|
+
# app: string — URL mount point (default: '')
|
|
482
|
+
# title: string — document title
|
|
483
|
+
# state: object — initial app state passed via bundle
|
|
484
|
+
# watch: boolean — enable hot-reload (registers watch dirs with rip-server)
|
|
483
485
|
#
|
|
484
486
|
|
|
485
487
|
export serve = (opts = {}) ->
|
|
486
488
|
prefix = opts.app or ''
|
|
487
489
|
appDir = opts.dir or '.'
|
|
488
490
|
routesDir = "#{appDir}/#{opts.routes or 'routes'}"
|
|
489
|
-
|
|
491
|
+
rawBundle = opts.bundle or opts.components or ['components']
|
|
492
|
+
bundles = new Map()
|
|
493
|
+
if Array.isArray(rawBundle)
|
|
494
|
+
bundles.set 'bundle', rawBundle.map (d) -> "#{appDir}/#{d}"
|
|
495
|
+
else if typeof rawBundle is 'object'
|
|
496
|
+
for name, dirs of rawBundle
|
|
497
|
+
bundles.set name, dirs.map (d) -> "#{appDir}/#{d}"
|
|
490
498
|
enableWatch = if opts.watch? then opts.watch else process.env.SOCKET_PREFIX?
|
|
491
499
|
appState = opts.state or null
|
|
492
500
|
appTitle = opts.title or null
|
|
@@ -524,43 +532,56 @@ export serve = (opts = {}) ->
|
|
|
524
532
|
return unless path.startsWith(appDirResolved)
|
|
525
533
|
@send path, 'text/x-rip; charset=UTF-8' if existsSync(path)
|
|
526
534
|
|
|
527
|
-
#
|
|
528
|
-
|
|
535
|
+
# Routes: {prefix}/{name} — per-bundle JSON endpoints (cached + Brotli)
|
|
536
|
+
# Built once per worker on first request, then served from memory with ETag/304.
|
|
537
|
+
bundleCaches = new Map()
|
|
529
538
|
|
|
530
|
-
|
|
539
|
+
buildNamedBundle = (name, dirs, includeRoutes = false) ->
|
|
531
540
|
{ brotliCompressSync } = require 'zlib'
|
|
532
541
|
glob = new Bun.Glob("**/*.rip")
|
|
533
542
|
components = {}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
543
|
+
if includeRoutes
|
|
544
|
+
for path in Array.from(glob.scanSync(routesDir)).sort()
|
|
545
|
+
components["components/#{path}"] = Bun.file("#{routesDir}/#{path}").text!
|
|
546
|
+
for dir in dirs
|
|
537
547
|
for path in Array.from(glob.scanSync(dir)).sort()
|
|
538
548
|
continue if path is 'index.rip' or path.endsWith('/index.rip')
|
|
539
549
|
key = "components/_lib/#{path}"
|
|
540
550
|
components[key] = Bun.file("#{dir}/#{path}").text! unless components[key]
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
data
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
551
|
+
bundle = { components }
|
|
552
|
+
if includeRoutes
|
|
553
|
+
data = {}
|
|
554
|
+
data.title = appTitle if appTitle
|
|
555
|
+
data.watch = enableWatch
|
|
556
|
+
if appState
|
|
557
|
+
data[k] = v for k, v of appState
|
|
558
|
+
bundle.data = data
|
|
559
|
+
cache = { json: null, br: null, etag: null }
|
|
560
|
+
cache.json = JSON.stringify(bundle)
|
|
561
|
+
cache.br = brotliCompressSync(cache.json)
|
|
562
|
+
cache.etag = "W/\"#{Bun.hash(cache.json).toString(36)}\""
|
|
563
|
+
bundleCaches.set name, cache
|
|
564
|
+
|
|
565
|
+
for [name, dirs] as bundles
|
|
566
|
+
get "#{prefix}/#{name}", (c) ->
|
|
567
|
+
cache = bundleCaches.get(name)
|
|
568
|
+
buildNamedBundle(name, dirs, (name is 'app') or (bundles.size is 1)) unless cache
|
|
569
|
+
cache = bundleCaches.get(name)
|
|
570
|
+
if c.req.header('if-none-match') is cache.etag
|
|
571
|
+
return new Response(null, { status: 304, headers: { 'ETag': cache.etag, 'Cache-Control': 'no-cache' } })
|
|
572
|
+
useBr = (c.req.header('accept-encoding') or '').includes('br')
|
|
573
|
+
headers = { 'Content-Type': 'application/json', 'Cache-Control': 'no-cache', 'ETag': cache.etag }
|
|
574
|
+
headers['Content-Encoding'] = 'br' if useBr
|
|
575
|
+
new Response (if useBr then cache.br else cache.json), { headers }
|
|
558
576
|
|
|
559
577
|
# Register watch directories with rip-server via control socket
|
|
560
578
|
if enableWatch and process.env.SOCKET_PREFIX
|
|
561
579
|
ctl = "/tmp/#{process.env.SOCKET_PREFIX}.ctl.sock"
|
|
562
|
-
|
|
563
|
-
|
|
580
|
+
watchDirs = [appDir]
|
|
581
|
+
for [_, bdirs] as bundles
|
|
582
|
+
watchDirs.push(...bdirs)
|
|
583
|
+
watchDirs = watchDirs.filter existsSync
|
|
584
|
+
body = JSON.stringify({ op: 'watch', prefix, dirs: watchDirs })
|
|
564
585
|
fetch('http://localhost/watch', { method: 'POST', body, headers: { 'content-type': 'application/json' }, unix: ctl }).catch (e) ->
|
|
565
586
|
console.warn "[Rip] Watch registration failed: #{e.message}"
|
|
566
587
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rip-lang/server",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.69",
|
|
4
4
|
"description": "Pure Rip web framework and application server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "api.rip",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"author": "Steve Shreeve <steve.shreeve@gmail.com>",
|
|
46
46
|
"license": "MIT",
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"rip-lang": ">=3.13.
|
|
48
|
+
"rip-lang": ">=3.13.85"
|
|
49
49
|
},
|
|
50
50
|
"files": [
|
|
51
51
|
"api.rip",
|