@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/prefetch.js CHANGED
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * SSR data prefetching for brender.
3
3
  *
4
- * Walks a page definition tree, collects `fetch` declarations,
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
- * This allows brender to inject fetched data into element state
9
- * before rendering, so the SSR output matches the client-side SPA.
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
- * Pre-evaluate children functions and replace them with static results.
295
- * During SSR, DOMQL's runtime state cascading and async re-render cycle
296
- * may not work correctly (trackSourcemapDeep stack overflows, etc.).
297
- * By pre-evaluating the children functions, we produce static element
298
- * definitions that DOMQL can render directly.
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
  }