@symbo.ls/brender 3.14.663 → 3.14.665
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/CHANGELOG.md +46 -0
- package/README.md +106 -23
- package/dist/esm/env.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/load.js +2 -1
- package/dist/esm/prefetch.js +1 -1
- package/dist/esm/render.js +33 -51
- package/dist/esm/shell.js +9 -8
- package/env.js +8 -2
- package/index.js +5 -3
- package/load.js +111 -22
- package/package.json +9 -9
- package/prefetch.js +30 -62
- package/render.js +533 -658
- package/shell.js +74 -12
package/prefetch.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SSR data prefetching for brender.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* executes them against the configured DB adapter,
|
|
6
|
-
* and returns the fetched data keyed by element path + `as` field.
|
|
4
|
+
* `fetchSSRTranslations` loads a project's table/RPC labels before a render.
|
|
7
5
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* `prefetchPageData` walks a page definition tree, collects `fetch`
|
|
7
|
+
* declarations, executes them against the configured DB adapter, and returns
|
|
8
|
+
* the fetched data keyed by element path + `as` field. render() does NOT use
|
|
9
|
+
* it: the fetch plugin loads a page's data during the render, with the real
|
|
10
|
+
* element (a `transform` here gets no element). Kept for direct callers.
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
13
|
const isFunction = (v) => typeof v === 'function'
|
|
@@ -192,6 +193,10 @@ const executeSingle = async (adapter, config) => {
|
|
|
192
193
|
/**
|
|
193
194
|
* Prefetch all data for a page route.
|
|
194
195
|
*
|
|
196
|
+
* @deprecated render() and renderPage() no longer use it: the fetch plugin
|
|
197
|
+
* loads a page's data during the render, with the real element (a `transform`
|
|
198
|
+
* here gets none). The `prefetch` render option does not call it. Kept for
|
|
199
|
+
* direct callers; to be removed.
|
|
195
200
|
* @param {object} data - Full project data (from loadProject)
|
|
196
201
|
* @param {string} route - Route to prefetch for (e.g. '/', '/blog')
|
|
197
202
|
* @param {object} [options]
|
|
@@ -235,13 +240,6 @@ export const prefetchPageData = async (data, route = '/', options = {}) => {
|
|
|
235
240
|
return stateUpdates
|
|
236
241
|
}
|
|
237
242
|
|
|
238
|
-
/**
|
|
239
|
-
* Inject prefetched data into a page definition's state objects.
|
|
240
|
-
* Mutates the definition in place (caller should deep-clone first).
|
|
241
|
-
*
|
|
242
|
-
* @param {object} pageDef - Page definition (will be mutated)
|
|
243
|
-
* @param {Map<string, object>} stateUpdates - Map from prefetchPageData
|
|
244
|
-
*/
|
|
245
243
|
/**
|
|
246
244
|
* Fetch polyglot translations from the DB for SSR use.
|
|
247
245
|
* Returns a map of { [lang]: { key: text, ... } } for all configured languages.
|
|
@@ -254,6 +252,14 @@ export const fetchSSRTranslations = async (data) => {
|
|
|
254
252
|
const config = data.config || {}
|
|
255
253
|
const polyglot = config.polyglot || data.polyglot
|
|
256
254
|
if (!polyglot?.fetch) return null
|
|
255
|
+
// A FUNCTION is the project's own loader — `(lang, version, el) => …`,
|
|
256
|
+
// called by the polyglot plugin. It runs inside the render, with the real
|
|
257
|
+
// root element (its el.call / el.getDB), and render() reads its labels back
|
|
258
|
+
// from the root state. This used to fall through to the RPC branch below
|
|
259
|
+
// with brender's default name, `get_translations_if_changed`: one request
|
|
260
|
+
// per language per route that the project never serves — 44 answered 404
|
|
261
|
+
// in one build (xma.info report, brender build item 11).
|
|
262
|
+
if (typeof polyglot.fetch === 'function') return null
|
|
257
263
|
|
|
258
264
|
const dbConfig = config.fetch || data.fetch || config.db || data.db
|
|
259
265
|
if (!dbConfig) return null
|
|
@@ -291,53 +297,19 @@ export const fetchSSRTranslations = async (data) => {
|
|
|
291
297
|
}
|
|
292
298
|
|
|
293
299
|
/**
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
300
|
+
* Merge prefetched data into a page definition's element states. Mutates the
|
|
301
|
+
* definition in place (the caller deep-clones first).
|
|
302
|
+
*
|
|
303
|
+
* @deprecated render() no longer uses it (the fetch plugin loads a page's data
|
|
304
|
+
* during the render); kept for callers of prefetchPageData, to be removed.
|
|
305
|
+
*
|
|
306
|
+
* It used to go on and evaluate every `children` FUNCTION under the target
|
|
307
|
+
* with a stand-in element — whose call() answered 'ka' for any language and
|
|
308
|
+
* returned the enclosing arrow function's `arguments[1]` for a label — and
|
|
309
|
+
* freeze the result into a static array the real data could never replace
|
|
310
|
+
* (xma.info report, brender build items 5 and 13). A children function stays
|
|
311
|
+
* a function now: the render runs it with the real element.
|
|
299
312
|
*/
|
|
300
|
-
const preEvaluateChildren = (def, inheritedState) => {
|
|
301
|
-
if (!def || typeof def !== 'object') return
|
|
302
|
-
for (const key in def) {
|
|
303
|
-
if (key === 'state' || key === 'fetch' || key === 'props' ||
|
|
304
|
-
key === 'attr' || key === 'on' || key === 'define' ||
|
|
305
|
-
key === 'childExtends' || key === 'childProps' || key === 'childrenAs') continue
|
|
306
|
-
if (key.charAt(0) >= 'A' && key.charAt(0) <= 'Z' && isObject(def[key])) {
|
|
307
|
-
const child = def[key]
|
|
308
|
-
// Determine effective state for this element (own state or inherited)
|
|
309
|
-
const effectiveState = child.state && typeof child.state === 'object'
|
|
310
|
-
? { ...inheritedState, ...child.state }
|
|
311
|
-
: inheritedState
|
|
312
|
-
|
|
313
|
-
// Pre-evaluate children function
|
|
314
|
-
if (isFunction(child.children)) {
|
|
315
|
-
try {
|
|
316
|
-
const mockEl = {
|
|
317
|
-
state: effectiveState,
|
|
318
|
-
call: (fn) => {
|
|
319
|
-
if (fn === 'getActiveLang' || fn === 'getLang') return effectiveState?.lang || 'ka'
|
|
320
|
-
if (fn === 'polyglot') return arguments[1] || ''
|
|
321
|
-
return undefined
|
|
322
|
-
},
|
|
323
|
-
__ref: {}
|
|
324
|
-
}
|
|
325
|
-
const result = child.children(mockEl, effectiveState)
|
|
326
|
-
if (isArray(result) && result.length > 0) {
|
|
327
|
-
// Replace children function with static array
|
|
328
|
-
child.children = result
|
|
329
|
-
}
|
|
330
|
-
} catch {
|
|
331
|
-
// If evaluation fails, leave the function as-is
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// Recurse deeper
|
|
336
|
-
preEvaluateChildren(child, effectiveState)
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
313
|
export const injectPrefetchedState = (pageDef, stateUpdates) => {
|
|
342
314
|
if (!stateUpdates || !stateUpdates.size) return
|
|
343
315
|
|
|
@@ -358,10 +330,6 @@ export const injectPrefetchedState = (pageDef, stateUpdates) => {
|
|
|
358
330
|
target.state = {}
|
|
359
331
|
}
|
|
360
332
|
Object.assign(target.state, data)
|
|
361
|
-
|
|
362
|
-
// Pre-evaluate children functions with the injected state
|
|
363
|
-
// so DOMQL gets static element definitions instead of functions
|
|
364
|
-
preEvaluateChildren(target, target.state)
|
|
365
333
|
}
|
|
366
334
|
}
|
|
367
335
|
}
|