@uniweb/runtime 0.16.0 → 0.17.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/src/prefetch.js CHANGED
@@ -10,12 +10,12 @@
10
10
  * compute that itself: resolve the configs, issue the requests, unwrap the responses in the
11
11
  * shape the datastore expects — a copy of the runtime's logic, in another repo, drifting
12
12
  * (the records envelope went silently unread that way on 2026-09-02). [Diego, 2026-09-03]:
13
- * *the backend sets `config.records`; the fetch comes from the runtime.* The host now calls
13
+ * *the backend sets the records service; the fetch comes from the runtime.* The host now calls
14
14
  * this and carries no copy. Hosting agreed to exactly that shape the same day.
15
15
  *
16
16
  * ⛔ Contract with the host, deliberately small:
17
17
  * - `content` the render payload (`site-content.json` / `__DATA__`), config included —
18
- * `config.records` and `config.base` are read from it.
18
+ * `config.services` and `config.base` are read from it.
19
19
  * - `route` the page to prefetch for; a `[slug]` template resolves through the same
20
20
  * matcher the SPA uses, so `/blog/post-1` finds `/blog/:slug`.
21
21
  * - `fetch` how to dispatch a request. The runtime composes the address; the host
@@ -46,8 +46,8 @@
46
46
  * is a different cache decision (hosting, 2026-09-03).
47
47
  *
48
48
  * It resolves nothing the host owns and models no host route layout: every address is
49
- * `{base}/…` from the payload, or the question door the host itself published at
50
- * `config.records.query`.
49
+ * `{base}/…` from the payload, or the records service the host itself
50
+ * published at `config.services.records`.
51
51
  */
52
52
  import { resolveFetchConfigs } from '@uniweb/core/fetch-config'
53
53
  import { deriveCacheKey } from '@uniweb/core/datastore'
@@ -118,7 +118,7 @@ export function resolvePageFetchConfigs(content, route, { locale = null } = {})
118
118
  locale,
119
119
  defaultLocale: resolveDefaultLocale(content?.config) ?? null,
120
120
  queries: content?.config?.queries ?? null,
121
- records: content?.config?.records ?? null,
121
+ services: content?.config?.services ?? null,
122
122
  variables: binding?.variables ?? null,
123
123
  }
124
124
  const out = new Map()
@@ -163,7 +163,7 @@ export function resolvePageFetchConfigs(content, route, { locale = null } = {})
163
163
  * @param {Object[]} configs resolved configs (from `resolvePageFetchConfigs` or the host's own
164
164
  * call to `resolveFetchConfigs`)
165
165
  * @param {Object} opts
166
- * @param {Object} opts.content the payload — `config.base`, `config.records`
166
+ * @param {Object} opts.content the payload — `config.base`, `config.services`
167
167
  * @param {Function} [opts.fetch] the transport; defaults to the global `fetch`
168
168
  * @param {boolean} [opts.dev]
169
169
  * @returns {Promise<Array<{ config: Object, outcome: 'fetched'|'failed'|'skipped', data: any, error?: string }>>}
@@ -178,7 +178,7 @@ export async function executeFetchConfigs(configs, { content, fetch = null, dev
178
178
  fetch,
179
179
  })
180
180
  const ctx = { website: null }
181
- // Dispatched together, not one after another: a question door batches the
181
+ // Dispatched together, not one after another: the records service batches the
182
182
  // requests issued in one tick into one POST, and a page's configs are
183
183
  // independent of each other. Order is preserved in the result.
184
184
  return Promise.all((configs || []).filter(Boolean).map(async (config) => {
@@ -18,6 +18,7 @@ import React from 'react'
18
18
  import { renderToString } from 'react-dom/server'
19
19
  import { createUniweb, resolveDefaultLocale } from '@uniweb/core'
20
20
  import { sectionDomId } from '@uniweb/core/section-id'
21
+ import { siteUrl, withOpacity } from './background-shared.js'
21
22
  import { routePatternToRegex } from '@uniweb/core/route-match'
22
23
  import { DEFAULT_ICON_BASE, iconUrl } from '@uniweb/core/icon-corpus'
23
24
  import { buildSectionOverrides, FONT_LINKS_MARKER } from '@uniweb/theming'
@@ -86,37 +87,6 @@ export function getWrapperProps(block) {
86
87
  return { id: sectionDomId(block), style, className, background }
87
88
  }
88
89
 
89
- /**
90
- * Convert hex/rgb color to rgba with opacity.
91
- * Mirrors withOpacity() in Background.jsx.
92
- */
93
- function withOpacity(color, opacity) {
94
- if (color.startsWith('#')) {
95
- const r = parseInt(color.slice(1, 3), 16)
96
- const g = parseInt(color.slice(3, 5), 16)
97
- const b = parseInt(color.slice(5, 7), 16)
98
- return `rgba(${r}, ${g}, ${b}, ${opacity})`
99
- }
100
- if (color.startsWith('rgb')) {
101
- const match = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/)
102
- if (match) {
103
- return `rgba(${match[1]}, ${match[2]}, ${match[3]}, ${opacity})`
104
- }
105
- }
106
- return color
107
- }
108
-
109
- /**
110
- * Resolve a URL against the site's base path.
111
- * Mirrors resolveUrl() in Background.jsx.
112
- */
113
- function resolveUrl(url) {
114
- if (!url || !url.startsWith('/')) return url
115
- const basePath = globalThis.uniweb?.activeWebsite?.basePath || ''
116
- if (!basePath) return url
117
- if (url.startsWith(basePath + '/') || url === basePath) return url
118
- return basePath + url
119
- }
120
90
 
121
91
  /**
122
92
  * Render a background element for SSR.
@@ -189,7 +159,7 @@ export function renderBackground(background) {
189
159
  style: {
190
160
  position: 'absolute',
191
161
  inset: '0',
192
- backgroundImage: `url(${resolveUrl(img.src)})`,
162
+ backgroundImage: `url(${siteUrl(img.src)})`,
193
163
  backgroundPosition: img.position || 'center',
194
164
  backgroundSize: img.size || 'cover',
195
165
  backgroundRepeat: 'no-repeat',
package/src/ssr.js CHANGED
@@ -58,7 +58,7 @@ export {
58
58
 
59
59
  // Server-side prefetch — the runtime executing a page's fetches for a host, so an isolate
60
60
  // receives `fetchedData` computed by our fetcher and the host carries no copy of it.
61
- // [Diego, 2026-09-03]: the backend sets config.records; the fetch comes from the runtime.
61
+ // [Diego, 2026-09-03]: the backend sets the records service; the fetch comes from the runtime.
62
62
  export {
63
63
  findPageForRoute,
64
64
  resolvePageFetchConfigs,
@@ -72,6 +72,13 @@ export {
72
72
  // what it deliberately leaves to the host.
73
73
  export { createPageRenderer, prefetchAndHydrate } from './page-renderer.js'
74
74
 
75
+ // The whole corpus, rather than one page — for a host that indexes a site or
76
+ // derives something over every record its queries return. It asks through the
77
+ // same client and the same composition a page render uses, which is the point:
78
+ // an index that composed its own questions could offer a result whose page then
79
+ // renders empty. The host supplies only the transport.
80
+ export { collectSiteRecords } from './collect-records.js'
81
+
75
82
  // Appearance. injectPageContent() already emits this for every prerendered
76
83
  // page; exported for lanes that assemble a shell without a per-page render.
77
84
  export { renderAppearanceBootScript } from './appearance.js'