@uniweb/runtime 0.23.0 → 0.24.0

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/dist/ssr.js CHANGED
@@ -919,7 +919,7 @@ function createDefaultFetcher({ basePath = "", dev = false, fetch: fetchImpl = n
919
919
  if (transform && data !== null && data !== void 0) {
920
920
  data = getNestedValue(data, transform);
921
921
  }
922
- data = applyOperators(data, request, { dev });
922
+ data = applyOperators(data, request, { dev, locale: sortLocale(request, ctx) });
923
923
  const whole = typeof request.whole === "boolean" ? request.whole : void 0;
924
924
  return whole === void 0 ? { data: data ?? [] } : { data: data ?? [], meta: { whole } };
925
925
  } catch (error) {
@@ -985,58 +985,47 @@ async function flushAsked(url, queue, doFetch) {
985
985
  return;
986
986
  }
987
987
  const data = parsed && typeof parsed.data === "object" && parsed.data ? parsed.data : {};
988
- const errors = parsed && typeof parsed.errors === "object" && parsed.errors ? parsed.errors : {};
989
988
  const wholes = parsed && typeof parsed.whole === "object" && parsed.whole ? parsed.whole : {};
990
989
  const cursors = parsed && typeof parsed.cursors === "object" && parsed.cursors ? parsed.cursors : {};
991
- const limits = parsed && typeof parsed.limits === "object" && parsed.limits ? parsed.limits : {};
990
+ const degraded = parsed && typeof parsed.partial === "object" && parsed.partial ? parsed.partial : {};
992
991
  queue.forEach((entry, i) => {
993
992
  const key = keys[i];
994
993
  const held = Array.isArray(entry.collected) && entry.collected.length ? entry.collected : null;
995
- if (key in errors) {
996
- const e = errors[key];
997
- const detail = typeof e === "string" ? e : e?.detail || e?.message || JSON.stringify(e);
998
- const out = held ? { data: held, error: detail, meta: withMeta({ partial: true, pages: entry.page }) } : { data: null, error: detail };
999
- if (e && typeof e === "object" && typeof e.code === "string") out.code = e.code;
1000
- entry.resolve(out);
1001
- return;
1002
- }
1003
994
  if (!(key in data)) {
1004
- entry.resolve({ data: null, error: `the records service answered without the key "${key}"` });
995
+ const error = `the records service answered without the key "${key}"`;
996
+ entry.resolve(held ? { data: held, error, meta: withMeta({ partial: true, pages: entry.page }) } : { data: null, error });
1005
997
  return;
1006
998
  }
1007
999
  const whole = typeof wholes[key] === "boolean" ? wholes[key] : typeof entry.request.whole === "boolean" ? entry.request.whole : void 0;
1008
1000
  const cursor = typeof cursors[key] === "string" && cursors[key] ? cursors[key] : null;
1009
- const bound = typeof limits[key] === "number" ? limits[key] : void 0;
1010
1001
  const rows = Array.isArray(data[key]) ? data[key] : data[key];
1011
1002
  if (cursor && entry.request.exhaustive && Array.isArray(rows)) {
1012
1003
  const acc = entry.collected ? entry.collected.concat(rows) : rows.slice();
1013
1004
  const page = (entry.page || 1) + 1;
1014
1005
  const cap = typeof entry.request.maxPages === "number" && entry.request.maxPages > 0 ? entry.request.maxPages : DEFAULT_MAX_PAGES;
1015
1006
  if (page <= cap) {
1016
- pending.set(entry, { cursor, collected: acc, page, whole, bound });
1007
+ pending.set(entry, { cursor, collected: acc, page, whole });
1017
1008
  return;
1018
1009
  }
1019
- entry.resolve({ data: acc, meta: withMeta({ whole, bound, partial: true, pages: cap }) });
1010
+ entry.resolve({ data: acc, meta: withMeta({ whole, partial: true, pages: cap }) });
1020
1011
  return;
1021
1012
  }
1022
1013
  const collected = entry.collected ? entry.collected.concat(Array.isArray(rows) ? rows : []) : rows;
1023
1014
  const meta = withMeta({
1024
1015
  whole,
1025
- bound,
1026
1016
  // ⭐ ONE FLAG, MEANING **NOT THE WHOLE POPULATION** — asked for by name, so
1027
- // a caller has one boolean to branch on rather than three signals to
1017
+ // a caller has one boolean to branch on rather than several signals to
1028
1018
  // combine. It is set in every case that means it:
1029
1019
  // · a cursor came back and this caller does not page (a page render);
1030
1020
  // · a cursor came back and the caller's `maxPages` stopped the walk;
1031
1021
  // · the walk failed or aborted with pages already in hand;
1032
- // · the service reported it BOUNDED the answer and offered no cursor.
1033
- // ⚠️ The last is why `limits` is read at all: a cursor is the signal for a
1034
- // query that declared no `limit`, and `limits` is the signal for one whose
1035
- // author limit was clamped (the records contract §5). Neither alone covers
1036
- // both. ⛔ Named `truncated` when it shipped in 0.17.0 this morning; renamed
1037
- // the same day, before any consumer adopted it, because "truncated" says
1038
- // something was cut and this also means "there is more you did not ask for".
1039
- partial: cursor || bound !== void 0 ? true : void 0,
1022
+ // · a source of the key did not answer (`partial[key]`), and `unavailable`
1023
+ // carries the service's own account of which one.
1024
+ // ⛔ Named `truncated` when it shipped in 0.17.0; renamed the same day, before
1025
+ // any consumer adopted it, because "truncated" says something was cut and this
1026
+ // also means "there is more you did not ask for".
1027
+ partial: cursor || key in degraded ? true : void 0,
1028
+ unavailable: key in degraded ? degraded[key] : void 0,
1040
1029
  pages: entry.page && entry.page > 1 ? entry.page : void 0
1041
1030
  });
1042
1031
  entry.resolve(meta ? { data: collected, meta } : { data: collected });
@@ -1076,19 +1065,25 @@ function withMeta(fields) {
1076
1065
  for (const [k, v] of Object.entries(fields)) if (v !== void 0) out[k] = v;
1077
1066
  return Object.keys(out).length ? out : void 0;
1078
1067
  }
1079
- function applyOperators(data, request, { dev = false } = {}) {
1068
+ function sortLocale(request, ctx) {
1069
+ if (typeof request?.locale === "string" && request.locale) return request.locale;
1070
+ if (typeof ctx?.locale === "string" && ctx.locale) return ctx.locale;
1071
+ const active = ctx?.website?.getActiveLocale?.();
1072
+ return typeof active === "string" && active ? active : null;
1073
+ }
1074
+ function applyOperators(data, request, { dev = false, locale = null } = {}) {
1080
1075
  if (!Array.isArray(data)) return data;
1081
1076
  let result = data;
1082
1077
  if (typeof request.scope === "string" && request.scope) result = applyScope(result, request.scope);
1083
1078
  if (request.where) result = matchWhere(request.where, result);
1084
- if (request.sort) result = applySort(result, request.sort, dev);
1079
+ if (request.sort) result = applySort(result, request.sort, dev, locale);
1085
1080
  if (typeof request.limit === "number" && request.limit > 0) result = result.slice(0, request.limit);
1086
1081
  return result;
1087
1082
  }
1088
1083
  const warnedBadSorts = /* @__PURE__ */ new Set();
1089
- function applySort(items, sortExpr, dev) {
1084
+ function applySort(items, sortExpr, dev, locale) {
1090
1085
  try {
1091
- return sortRecords(items, sortExpr);
1086
+ return sortRecords(items, sortExpr, { locale });
1092
1087
  } catch (err) {
1093
1088
  if (dev) throw err;
1094
1089
  const key = String(sortExpr);
@@ -1194,7 +1189,7 @@ function resolvePageFetchConfigs(content, route, { locale = null } = {}) {
1194
1189
  for (const s of layoutSectionsFor(content, page)) add([s.fetch ?? null, siteFetch]);
1195
1190
  return [...out.values()];
1196
1191
  }
1197
- async function executeFetchConfigs(configs, { content, fetch: fetch2 = null, dev = false, prerender = "always" } = {}) {
1192
+ async function executeFetchConfigs(configs, { content, fetch: fetch2 = null, dev = false, prerender = "always", locale = null } = {}) {
1198
1193
  if (prerender !== "author" && prerender !== "always") {
1199
1194
  throw new Error(`executeFetchConfigs: prerender must be 'author' or 'always', got ${JSON.stringify(prerender)}`);
1200
1195
  }
@@ -1203,7 +1198,7 @@ async function executeFetchConfigs(configs, { content, fetch: fetch2 = null, dev
1203
1198
  dev,
1204
1199
  fetch: fetch2
1205
1200
  });
1206
- const ctx = { website: null };
1201
+ const ctx = { website: null, locale: locale ?? content?.config?.activeLocale ?? resolveDefaultLocale$1(content?.config) ?? null };
1207
1202
  return Promise.all((configs || []).filter(Boolean).map(async (config) => {
1208
1203
  if (prerender === "author" && config.prerender === false) {
1209
1204
  return { config, outcome: "skipped", data: null };
@@ -1215,7 +1210,7 @@ async function executeFetchConfigs(configs, { content, fetch: fetch2 = null, dev
1215
1210
  }
1216
1211
  async function prefetchPageData({ content, route, locale = null, fetch: fetch2 = null, dev = false, prerender = "always" }) {
1217
1212
  const configs = resolvePageFetchConfigs(content, route, { locale });
1218
- return executeFetchConfigs(configs, { content, fetch: fetch2, dev, prerender });
1213
+ return executeFetchConfigs(configs, { content, fetch: fetch2, dev, prerender, locale });
1219
1214
  }
1220
1215
  function createPageRenderer({ website, shell }) {
1221
1216
  if (!website) throw new Error("createPageRenderer: `website` is required");