@bagelink/blox 1.15.629 → 1.15.631

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.
Files changed (30) hide show
  1. package/dist/{PreviewApp-DcD_Cjzn.js → PreviewApp-DQ5p-pJu.js} +1 -1
  2. package/dist/{PreviewApp-5XGQVrnd.cjs → PreviewApp-j062gN6d.cjs} +1 -1
  3. package/dist/{PreviewApp.vue_vue_type_style_index_0_lang-OZtgkMXq.cjs → PreviewApp.vue_vue_type_style_index_0_lang-B9_7wgnw.cjs} +1 -1
  4. package/dist/{PreviewApp.vue_vue_type_style_index_0_lang-m2TIr6Wk.js → PreviewApp.vue_vue_type_style_index_0_lang-DCYf0VuH.js} +1 -1
  5. package/dist/api/index.d.ts +2 -0
  6. package/dist/api/index.d.ts.map +1 -1
  7. package/dist/{appRuntime-BqvP0NaP.cjs → appRuntime-BWlOTcQo.cjs} +13 -210
  8. package/dist/{appRuntime-FphnGcV2.js → appRuntime-DEeCouh7.js} +38 -235
  9. package/dist/{client-XQnL-B6N.js → client-Ce9fRCGH.js} +2 -2
  10. package/dist/index.cjs +23 -19
  11. package/dist/index.d.ts +1 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.mjs +52 -47
  14. package/dist/pageTitle-DyJ9r6xJ.cjs +268 -0
  15. package/dist/pageTitle-tOzMNilm.js +269 -0
  16. package/dist/{shard-runner-CinJMC5z.cjs → shard-runner-BJ7J4qF3.cjs} +2 -2
  17. package/dist/{shard-runner-C7_xAkA1.js → shard-runner-BSUEe9p3.js} +2 -2
  18. package/dist/ssg/cli.cjs +8 -2
  19. package/dist/ssg/cli.mjs +8 -2
  20. package/dist/ssg/client.mjs +2 -2
  21. package/dist/ssg/cms-routes.d.ts +19 -0
  22. package/dist/ssg/cms-routes.d.ts.map +1 -1
  23. package/dist/ssg/createSSREntry.d.ts.map +1 -1
  24. package/dist/ssg/index.cjs +7 -5
  25. package/dist/ssg/index.mjs +22 -20
  26. package/dist/{validate-output-e0E998g_.js → validate-output-CRv_cnji.js} +44 -24
  27. package/dist/{validate-output-DQTw64Rc.cjs → validate-output-oVFDwKIA.cjs} +24 -4
  28. package/package.json +1 -1
  29. package/dist/pageTitle-BOTMH-D8.js +0 -56
  30. package/dist/pageTitle-nIl1cDfD.cjs +0 -55
@@ -0,0 +1,268 @@
1
+ "use strict";
2
+ const vue = require("vue");
3
+ const ssg_client = require("./client-AoDTJJXJ.cjs");
4
+ let BASE = "/api";
5
+ let _websiteName = "";
6
+ let _store = "";
7
+ let _websiteId = null;
8
+ let _origin = "";
9
+ let _collectionResolver = null;
10
+ const BLOX_API_KEY = Symbol("blox:api");
11
+ function configureApi(websiteName, store) {
12
+ _websiteName = websiteName;
13
+ _store = store;
14
+ _websiteId = null;
15
+ }
16
+ function setApiOrigin(base) {
17
+ if (!base) return;
18
+ try {
19
+ const u = new URL(base);
20
+ _origin = u.origin;
21
+ BASE = u.pathname && u.pathname !== "/" ? u.pathname.replace(/\/$/, "") : "";
22
+ } catch {
23
+ }
24
+ }
25
+ function setCollectionResolver(resolver) {
26
+ _collectionResolver = resolver;
27
+ }
28
+ function getCollectionResolver() {
29
+ return _collectionResolver;
30
+ }
31
+ function apiBase(base = "/api", origin = "") {
32
+ if (!origin) return { base, origin };
33
+ try {
34
+ const url = new URL(origin);
35
+ return {
36
+ origin: url.origin,
37
+ base: url.pathname && url.pathname !== "/" ? url.pathname.replace(/\/$/, "") : ""
38
+ };
39
+ } catch {
40
+ return { base, origin: "" };
41
+ }
42
+ }
43
+ function createBloxApi(options) {
44
+ const configured = apiBase("/api", options.origin);
45
+ let websiteId = null;
46
+ async function scopedRequest(path, { locale, params, ...opts } = {}) {
47
+ const origin = configured.origin || (typeof window !== "undefined" ? window.location.origin : "");
48
+ const url = new URL(`${configured.base}${path}`, origin || void 0);
49
+ if (locale) url.searchParams.set("locale", locale);
50
+ if (params) {
51
+ for (const [key, value] of Object.entries(params)) url.searchParams.set(key, String(value));
52
+ }
53
+ const response = await fetch(url.toString(), opts);
54
+ if (!response.ok) throw new Error(`API ${response.status}: ${path}`);
55
+ if (response.status === 204) return null;
56
+ return response.json();
57
+ }
58
+ function getWebsiteIdSync2() {
59
+ var _a;
60
+ if (websiteId) return websiteId;
61
+ return ((_a = ssg_client.readBloxHydration()) == null ? void 0 : _a.websiteId) ?? null;
62
+ }
63
+ async function getWebsiteId2() {
64
+ const existing = getWebsiteIdSync2();
65
+ if (existing) {
66
+ websiteId = existing;
67
+ return existing;
68
+ }
69
+ try {
70
+ const website = await scopedRequest(
71
+ `/blox/sites/${encodeURIComponent(options.websiteName)}`
72
+ );
73
+ websiteId = website.id;
74
+ return website.id;
75
+ } catch {
76
+ throw new Error(`Website "${options.websiteName}" not found. Run: npm run seed`);
77
+ }
78
+ }
79
+ async function listItems2(collection, { locale, q, offset = 0, limit = 100 } = {}) {
80
+ const resolver = options.collectionResolver ?? _collectionResolver;
81
+ if (resolver) {
82
+ return await resolver(collection, {
83
+ locale,
84
+ q,
85
+ offset,
86
+ limit
87
+ });
88
+ }
89
+ return scopedRequest(`/datastore/${options.store}/collections/${collection}`, {
90
+ locale,
91
+ params: { ...q ? { q } : {}, offset, limit }
92
+ });
93
+ }
94
+ return {
95
+ getWebsiteIdSync: getWebsiteIdSync2,
96
+ getWebsiteId: getWebsiteId2,
97
+ resolvePath: async (path, locale) => {
98
+ const id = await getWebsiteId2();
99
+ return scopedRequest(`/blox/websites/${id}/resolve-path`, {
100
+ locale,
101
+ params: { path }
102
+ });
103
+ },
104
+ listItems: listItems2,
105
+ getItemBySlug: async (collection, slug, locale) => {
106
+ const result = await listItems2(collection, { locale, limit: 1e3 });
107
+ const items = Array.isArray(result) ? result : (result == null ? void 0 : result.items) ?? [];
108
+ return items.find((item) => String((item == null ? void 0 : item.slug) ?? "") === slug) ?? null;
109
+ },
110
+ getItemById: async (collection, id, locale) => {
111
+ const result = await listItems2(collection, { locale, limit: 1e3 });
112
+ const items = Array.isArray(result) ? result : (result == null ? void 0 : result.items) ?? [];
113
+ return items.find((item) => {
114
+ const record = item;
115
+ return String((record == null ? void 0 : record.id) ?? (record == null ? void 0 : record._id) ?? "") === id;
116
+ }) ?? null;
117
+ }
118
+ };
119
+ }
120
+ function provideBloxApi(app, options) {
121
+ const client = createBloxApi(options);
122
+ app.provide(BLOX_API_KEY, client);
123
+ return client;
124
+ }
125
+ function useBloxApi() {
126
+ return vue.getCurrentInstance() ? vue.inject(BLOX_API_KEY, null) : null;
127
+ }
128
+ async function request(path, { locale, params, ...opts } = {}) {
129
+ const origin = _origin || (typeof window !== "undefined" ? window.location.origin : "");
130
+ const url = new URL(`${BASE}${path}`, origin || void 0);
131
+ if (locale) url.searchParams.set("locale", locale);
132
+ if (params) {
133
+ for (const [k, v] of Object.entries(params)) url.searchParams.set(k, String(v));
134
+ }
135
+ const res = await fetch(url.toString(), opts);
136
+ if (!res.ok) throw new Error(`API ${res.status}: ${path}`);
137
+ if (res.status === 204) return null;
138
+ return res.json();
139
+ }
140
+ function getWebsiteIdSync() {
141
+ if (_websiteId) return _websiteId;
142
+ if (typeof window !== "undefined") {
143
+ const embedded = window[ssg_client.BLOX_WEBSITE_ID_WINDOW_KEY];
144
+ if (typeof embedded === "string" && embedded !== "") return embedded;
145
+ }
146
+ return null;
147
+ }
148
+ async function getWebsiteId() {
149
+ if (_websiteId) return _websiteId;
150
+ if (typeof window !== "undefined") {
151
+ const embedded = window[ssg_client.BLOX_WEBSITE_ID_WINDOW_KEY];
152
+ if (typeof embedded === "string" && embedded !== "") {
153
+ _websiteId = embedded;
154
+ return _websiteId;
155
+ }
156
+ }
157
+ let website;
158
+ try {
159
+ website = await request(
160
+ `/blox/sites/${encodeURIComponent(_websiteName)}`
161
+ );
162
+ } catch {
163
+ throw new Error(`Website "${_websiteName}" not found. Run: npm run seed`);
164
+ }
165
+ _websiteId = website.id;
166
+ return website.id;
167
+ }
168
+ async function resolvePath(path, locale) {
169
+ const websiteId = await getWebsiteId();
170
+ return request(`/blox/websites/${websiteId}/resolve-path`, {
171
+ locale,
172
+ params: { path }
173
+ });
174
+ }
175
+ async function listItems(collection, { locale, q, offset = 0, limit = 100 } = {}) {
176
+ if (_collectionResolver) {
177
+ return await _collectionResolver(collection, { locale, q, offset, limit });
178
+ }
179
+ return request(`/datastore/${_store}/collections/${collection}`, {
180
+ locale,
181
+ params: { ...q ? { q } : {}, offset, limit }
182
+ });
183
+ }
184
+ async function getItemBySlug(collection, slug, locale) {
185
+ const res = await listItemsFromActiveApi(collection, { locale, limit: 1e3 });
186
+ const items = Array.isArray(res) ? res : (res == null ? void 0 : res.items) ?? [];
187
+ return items.find((item) => String((item == null ? void 0 : item.slug) ?? "") === slug) ?? null;
188
+ }
189
+ async function getItemById(collection, id, locale) {
190
+ const res = await listItemsFromActiveApi(collection, { locale, limit: 1e3 });
191
+ const items = Array.isArray(res) ? res : (res == null ? void 0 : res.items) ?? [];
192
+ return items.find((item) => {
193
+ const record = item;
194
+ return String((record == null ? void 0 : record.id) ?? (record == null ? void 0 : record._id) ?? "") === id;
195
+ }) ?? null;
196
+ }
197
+ function listItemsFromActiveApi(collection, options = {}) {
198
+ var _a;
199
+ return ((_a = useBloxApi()) == null ? void 0 : _a.listItems(collection, options)) ?? listItems(collection, options);
200
+ }
201
+ const PREFERRED_CONTEXT_KEYS = ["$page", "$post", "$item", "$article", "$product", "$event", "$author"];
202
+ const TITLE_FIELDS = ["meta_title", "metaTitle", "title", "name", "productName", "displayName"];
203
+ function primaryPageContext(contexts) {
204
+ if (!contexts) return null;
205
+ const keys = [
206
+ ...PREFERRED_CONTEXT_KEYS.filter((key) => key in contexts),
207
+ ...Object.keys(contexts).filter((key) => key !== "$website" && !PREFERRED_CONTEXT_KEYS.includes(key)).sort()
208
+ ];
209
+ for (const key of keys) {
210
+ const ctx = contexts[key];
211
+ if (ctx != null && typeof ctx === "object") return { key, ctx };
212
+ }
213
+ return null;
214
+ }
215
+ function contextPageTitle(context) {
216
+ if (!context) return null;
217
+ for (const field of TITLE_FIELDS) {
218
+ const value = context[field];
219
+ if (typeof value === "string" && value.trim()) return value.trim();
220
+ }
221
+ return null;
222
+ }
223
+ function siteNameFromContexts(contexts) {
224
+ const website = contexts == null ? void 0 : contexts.$website;
225
+ const seo = website == null ? void 0 : website.seo;
226
+ const siteName = seo && typeof seo === "object" ? seo.site_name : website == null ? void 0 : website.site_name;
227
+ return typeof siteName === "string" && siteName.trim() ? siteName.trim() : null;
228
+ }
229
+ function withSiteName(title, siteName) {
230
+ if (!siteName || title.includes(siteName)) return title;
231
+ return `${title} · ${siteName}`;
232
+ }
233
+ function resolvePageTitle(resolved, options = {}) {
234
+ var _a, _b, _c, _d, _e, _f, _g;
235
+ const hasBinding = !!((_a = resolved.page) == null ? void 0 : _a.data_bindings) && Object.keys(resolved.page.data_bindings).length > 0;
236
+ const contextTitle = hasBinding ? contextPageTitle((_b = primaryPageContext(resolved.contexts)) == null ? void 0 : _b.ctx) : null;
237
+ const dynamicTitle = ((_c = options.override) == null ? void 0 : _c.trim()) || contextTitle;
238
+ if (dynamicTitle) return withSiteName(dynamicTitle, options.siteName);
239
+ if ((_e = (_d = resolved.page) == null ? void 0 : _d.meta_title) == null ? void 0 : _e.trim()) return resolved.page.meta_title.trim();
240
+ if ((_g = (_f = resolved.page) == null ? void 0 : _f.title) == null ? void 0 : _g.trim()) return withSiteName(resolved.page.title.trim(), options.siteName);
241
+ return null;
242
+ }
243
+ function preserveCurrentSiteSuffix(title, currentTitle) {
244
+ const separator = " · ";
245
+ const suffixIndex = currentTitle.lastIndexOf(separator);
246
+ if (suffixIndex < 0) return title;
247
+ const siteName = currentTitle.slice(suffixIndex + separator.length).trim();
248
+ return withSiteName(title, siteName);
249
+ }
250
+ exports.configureApi = configureApi;
251
+ exports.contextPageTitle = contextPageTitle;
252
+ exports.createBloxApi = createBloxApi;
253
+ exports.getCollectionResolver = getCollectionResolver;
254
+ exports.getItemById = getItemById;
255
+ exports.getItemBySlug = getItemBySlug;
256
+ exports.getWebsiteId = getWebsiteId;
257
+ exports.getWebsiteIdSync = getWebsiteIdSync;
258
+ exports.listItems = listItems;
259
+ exports.listItemsFromActiveApi = listItemsFromActiveApi;
260
+ exports.preserveCurrentSiteSuffix = preserveCurrentSiteSuffix;
261
+ exports.primaryPageContext = primaryPageContext;
262
+ exports.provideBloxApi = provideBloxApi;
263
+ exports.resolvePageTitle = resolvePageTitle;
264
+ exports.resolvePath = resolvePath;
265
+ exports.setApiOrigin = setApiOrigin;
266
+ exports.setCollectionResolver = setCollectionResolver;
267
+ exports.siteNameFromContexts = siteNameFromContexts;
268
+ exports.useBloxApi = useBloxApi;
@@ -0,0 +1,269 @@
1
+ import { getCurrentInstance, inject } from "vue";
2
+ import { B as BLOX_WEBSITE_ID_WINDOW_KEY, r as readBloxHydration } from "./client-Ce9fRCGH.js";
3
+ let BASE = "/api";
4
+ let _websiteName = "";
5
+ let _store = "";
6
+ let _websiteId = null;
7
+ let _origin = "";
8
+ let _collectionResolver = null;
9
+ const BLOX_API_KEY = Symbol("blox:api");
10
+ function configureApi(websiteName, store) {
11
+ _websiteName = websiteName;
12
+ _store = store;
13
+ _websiteId = null;
14
+ }
15
+ function setApiOrigin(base) {
16
+ if (!base) return;
17
+ try {
18
+ const u = new URL(base);
19
+ _origin = u.origin;
20
+ BASE = u.pathname && u.pathname !== "/" ? u.pathname.replace(/\/$/, "") : "";
21
+ } catch {
22
+ }
23
+ }
24
+ function setCollectionResolver(resolver) {
25
+ _collectionResolver = resolver;
26
+ }
27
+ function getCollectionResolver() {
28
+ return _collectionResolver;
29
+ }
30
+ function apiBase(base = "/api", origin = "") {
31
+ if (!origin) return { base, origin };
32
+ try {
33
+ const url = new URL(origin);
34
+ return {
35
+ origin: url.origin,
36
+ base: url.pathname && url.pathname !== "/" ? url.pathname.replace(/\/$/, "") : ""
37
+ };
38
+ } catch {
39
+ return { base, origin: "" };
40
+ }
41
+ }
42
+ function createBloxApi(options) {
43
+ const configured = apiBase("/api", options.origin);
44
+ let websiteId = null;
45
+ async function scopedRequest(path, { locale, params, ...opts } = {}) {
46
+ const origin = configured.origin || (typeof window !== "undefined" ? window.location.origin : "");
47
+ const url = new URL(`${configured.base}${path}`, origin || void 0);
48
+ if (locale) url.searchParams.set("locale", locale);
49
+ if (params) {
50
+ for (const [key, value] of Object.entries(params)) url.searchParams.set(key, String(value));
51
+ }
52
+ const response = await fetch(url.toString(), opts);
53
+ if (!response.ok) throw new Error(`API ${response.status}: ${path}`);
54
+ if (response.status === 204) return null;
55
+ return response.json();
56
+ }
57
+ function getWebsiteIdSync2() {
58
+ var _a;
59
+ if (websiteId) return websiteId;
60
+ return ((_a = readBloxHydration()) == null ? void 0 : _a.websiteId) ?? null;
61
+ }
62
+ async function getWebsiteId2() {
63
+ const existing = getWebsiteIdSync2();
64
+ if (existing) {
65
+ websiteId = existing;
66
+ return existing;
67
+ }
68
+ try {
69
+ const website = await scopedRequest(
70
+ `/blox/sites/${encodeURIComponent(options.websiteName)}`
71
+ );
72
+ websiteId = website.id;
73
+ return website.id;
74
+ } catch {
75
+ throw new Error(`Website "${options.websiteName}" not found. Run: npm run seed`);
76
+ }
77
+ }
78
+ async function listItems2(collection, { locale, q, offset = 0, limit = 100 } = {}) {
79
+ const resolver = options.collectionResolver ?? _collectionResolver;
80
+ if (resolver) {
81
+ return await resolver(collection, {
82
+ locale,
83
+ q,
84
+ offset,
85
+ limit
86
+ });
87
+ }
88
+ return scopedRequest(`/datastore/${options.store}/collections/${collection}`, {
89
+ locale,
90
+ params: { ...q ? { q } : {}, offset, limit }
91
+ });
92
+ }
93
+ return {
94
+ getWebsiteIdSync: getWebsiteIdSync2,
95
+ getWebsiteId: getWebsiteId2,
96
+ resolvePath: async (path, locale) => {
97
+ const id = await getWebsiteId2();
98
+ return scopedRequest(`/blox/websites/${id}/resolve-path`, {
99
+ locale,
100
+ params: { path }
101
+ });
102
+ },
103
+ listItems: listItems2,
104
+ getItemBySlug: async (collection, slug, locale) => {
105
+ const result = await listItems2(collection, { locale, limit: 1e3 });
106
+ const items = Array.isArray(result) ? result : (result == null ? void 0 : result.items) ?? [];
107
+ return items.find((item) => String((item == null ? void 0 : item.slug) ?? "") === slug) ?? null;
108
+ },
109
+ getItemById: async (collection, id, locale) => {
110
+ const result = await listItems2(collection, { locale, limit: 1e3 });
111
+ const items = Array.isArray(result) ? result : (result == null ? void 0 : result.items) ?? [];
112
+ return items.find((item) => {
113
+ const record = item;
114
+ return String((record == null ? void 0 : record.id) ?? (record == null ? void 0 : record._id) ?? "") === id;
115
+ }) ?? null;
116
+ }
117
+ };
118
+ }
119
+ function provideBloxApi(app, options) {
120
+ const client = createBloxApi(options);
121
+ app.provide(BLOX_API_KEY, client);
122
+ return client;
123
+ }
124
+ function useBloxApi() {
125
+ return getCurrentInstance() ? inject(BLOX_API_KEY, null) : null;
126
+ }
127
+ async function request(path, { locale, params, ...opts } = {}) {
128
+ const origin = _origin || (typeof window !== "undefined" ? window.location.origin : "");
129
+ const url = new URL(`${BASE}${path}`, origin || void 0);
130
+ if (locale) url.searchParams.set("locale", locale);
131
+ if (params) {
132
+ for (const [k, v] of Object.entries(params)) url.searchParams.set(k, String(v));
133
+ }
134
+ const res = await fetch(url.toString(), opts);
135
+ if (!res.ok) throw new Error(`API ${res.status}: ${path}`);
136
+ if (res.status === 204) return null;
137
+ return res.json();
138
+ }
139
+ function getWebsiteIdSync() {
140
+ if (_websiteId) return _websiteId;
141
+ if (typeof window !== "undefined") {
142
+ const embedded = window[BLOX_WEBSITE_ID_WINDOW_KEY];
143
+ if (typeof embedded === "string" && embedded !== "") return embedded;
144
+ }
145
+ return null;
146
+ }
147
+ async function getWebsiteId() {
148
+ if (_websiteId) return _websiteId;
149
+ if (typeof window !== "undefined") {
150
+ const embedded = window[BLOX_WEBSITE_ID_WINDOW_KEY];
151
+ if (typeof embedded === "string" && embedded !== "") {
152
+ _websiteId = embedded;
153
+ return _websiteId;
154
+ }
155
+ }
156
+ let website;
157
+ try {
158
+ website = await request(
159
+ `/blox/sites/${encodeURIComponent(_websiteName)}`
160
+ );
161
+ } catch {
162
+ throw new Error(`Website "${_websiteName}" not found. Run: npm run seed`);
163
+ }
164
+ _websiteId = website.id;
165
+ return website.id;
166
+ }
167
+ async function resolvePath(path, locale) {
168
+ const websiteId = await getWebsiteId();
169
+ return request(`/blox/websites/${websiteId}/resolve-path`, {
170
+ locale,
171
+ params: { path }
172
+ });
173
+ }
174
+ async function listItems(collection, { locale, q, offset = 0, limit = 100 } = {}) {
175
+ if (_collectionResolver) {
176
+ return await _collectionResolver(collection, { locale, q, offset, limit });
177
+ }
178
+ return request(`/datastore/${_store}/collections/${collection}`, {
179
+ locale,
180
+ params: { ...q ? { q } : {}, offset, limit }
181
+ });
182
+ }
183
+ async function getItemBySlug(collection, slug, locale) {
184
+ const res = await listItemsFromActiveApi(collection, { locale, limit: 1e3 });
185
+ const items = Array.isArray(res) ? res : (res == null ? void 0 : res.items) ?? [];
186
+ return items.find((item) => String((item == null ? void 0 : item.slug) ?? "") === slug) ?? null;
187
+ }
188
+ async function getItemById(collection, id, locale) {
189
+ const res = await listItemsFromActiveApi(collection, { locale, limit: 1e3 });
190
+ const items = Array.isArray(res) ? res : (res == null ? void 0 : res.items) ?? [];
191
+ return items.find((item) => {
192
+ const record = item;
193
+ return String((record == null ? void 0 : record.id) ?? (record == null ? void 0 : record._id) ?? "") === id;
194
+ }) ?? null;
195
+ }
196
+ function listItemsFromActiveApi(collection, options = {}) {
197
+ var _a;
198
+ return ((_a = useBloxApi()) == null ? void 0 : _a.listItems(collection, options)) ?? listItems(collection, options);
199
+ }
200
+ const PREFERRED_CONTEXT_KEYS = ["$page", "$post", "$item", "$article", "$product", "$event", "$author"];
201
+ const TITLE_FIELDS = ["meta_title", "metaTitle", "title", "name", "productName", "displayName"];
202
+ function primaryPageContext(contexts) {
203
+ if (!contexts) return null;
204
+ const keys = [
205
+ ...PREFERRED_CONTEXT_KEYS.filter((key) => key in contexts),
206
+ ...Object.keys(contexts).filter((key) => key !== "$website" && !PREFERRED_CONTEXT_KEYS.includes(key)).sort()
207
+ ];
208
+ for (const key of keys) {
209
+ const ctx = contexts[key];
210
+ if (ctx != null && typeof ctx === "object") return { key, ctx };
211
+ }
212
+ return null;
213
+ }
214
+ function contextPageTitle(context) {
215
+ if (!context) return null;
216
+ for (const field of TITLE_FIELDS) {
217
+ const value = context[field];
218
+ if (typeof value === "string" && value.trim()) return value.trim();
219
+ }
220
+ return null;
221
+ }
222
+ function siteNameFromContexts(contexts) {
223
+ const website = contexts == null ? void 0 : contexts.$website;
224
+ const seo = website == null ? void 0 : website.seo;
225
+ const siteName = seo && typeof seo === "object" ? seo.site_name : website == null ? void 0 : website.site_name;
226
+ return typeof siteName === "string" && siteName.trim() ? siteName.trim() : null;
227
+ }
228
+ function withSiteName(title, siteName) {
229
+ if (!siteName || title.includes(siteName)) return title;
230
+ return `${title} · ${siteName}`;
231
+ }
232
+ function resolvePageTitle(resolved, options = {}) {
233
+ var _a, _b, _c, _d, _e, _f, _g;
234
+ const hasBinding = !!((_a = resolved.page) == null ? void 0 : _a.data_bindings) && Object.keys(resolved.page.data_bindings).length > 0;
235
+ const contextTitle = hasBinding ? contextPageTitle((_b = primaryPageContext(resolved.contexts)) == null ? void 0 : _b.ctx) : null;
236
+ const dynamicTitle = ((_c = options.override) == null ? void 0 : _c.trim()) || contextTitle;
237
+ if (dynamicTitle) return withSiteName(dynamicTitle, options.siteName);
238
+ if ((_e = (_d = resolved.page) == null ? void 0 : _d.meta_title) == null ? void 0 : _e.trim()) return resolved.page.meta_title.trim();
239
+ if ((_g = (_f = resolved.page) == null ? void 0 : _f.title) == null ? void 0 : _g.trim()) return withSiteName(resolved.page.title.trim(), options.siteName);
240
+ return null;
241
+ }
242
+ function preserveCurrentSiteSuffix(title, currentTitle) {
243
+ const separator = " · ";
244
+ const suffixIndex = currentTitle.lastIndexOf(separator);
245
+ if (suffixIndex < 0) return title;
246
+ const siteName = currentTitle.slice(suffixIndex + separator.length).trim();
247
+ return withSiteName(title, siteName);
248
+ }
249
+ export {
250
+ primaryPageContext as a,
251
+ getItemBySlug as b,
252
+ contextPageTitle as c,
253
+ getItemById as d,
254
+ configureApi as e,
255
+ createBloxApi as f,
256
+ getCollectionResolver as g,
257
+ getWebsiteId as h,
258
+ getWebsiteIdSync as i,
259
+ resolvePath as j,
260
+ setApiOrigin as k,
261
+ listItems as l,
262
+ siteNameFromContexts as m,
263
+ preserveCurrentSiteSuffix as n,
264
+ listItemsFromActiveApi as o,
265
+ provideBloxApi as p,
266
+ resolvePageTitle as r,
267
+ setCollectionResolver as s,
268
+ useBloxApi as u
269
+ };
@@ -26,7 +26,7 @@ const node_child_process = require("node:child_process");
26
26
  const os = require("node:os");
27
27
  const path = require("node:path");
28
28
  const process = require("node:process");
29
- const llmArtifacts = require("./validate-output-DQTw64Rc.cjs");
29
+ const llmArtifacts = require("./validate-output-oVFDwKIA.cjs");
30
30
  const AUTO_SHARD_CAP = Number(process.env.BLOX_SSG_SHARD_CAP) || 6;
31
31
  const PREFETCH_BUDGET = Number(process.env.BLOX_SSG_PREFETCH_BUDGET) || 24;
32
32
  const SEQUENTIAL_SHARDS = process.env.BLOX_SSG_SEQUENTIAL === "1";
@@ -166,7 +166,7 @@ async function runSharded(opts) {
166
166
  }
167
167
  if (process.env.BLOX_SSG_LLM !== "0") {
168
168
  try {
169
- const { mergeLlmParts } = await Promise.resolve().then(() => require("./validate-output-DQTw64Rc.cjs")).then((n) => n.llmArtifacts);
169
+ const { mergeLlmParts } = await Promise.resolve().then(() => require("./validate-output-oVFDwKIA.cjs")).then((n) => n.llmArtifacts);
170
170
  const mergeWebsite = website;
171
171
  const partFiles = Array.from({ length: total }, (_, i) => path.join(llmPartsDir, `part.${i}.json`));
172
172
  const { pages } = await mergeLlmParts({
@@ -2,7 +2,7 @@ import { spawn } from "node:child_process";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
4
  import process from "node:process";
5
- import { f as fetchCmsSiteData, g as generateSitemapArtifacts } from "./validate-output-e0E998g_.js";
5
+ import { f as fetchCmsSiteData, g as generateSitemapArtifacts } from "./validate-output-CRv_cnji.js";
6
6
  const AUTO_SHARD_CAP = Number(process.env.BLOX_SSG_SHARD_CAP) || 6;
7
7
  const PREFETCH_BUDGET = Number(process.env.BLOX_SSG_PREFETCH_BUDGET) || 24;
8
8
  const SEQUENTIAL_SHARDS = process.env.BLOX_SSG_SEQUENTIAL === "1";
@@ -142,7 +142,7 @@ async function runSharded(opts) {
142
142
  }
143
143
  if (process.env.BLOX_SSG_LLM !== "0") {
144
144
  try {
145
- const { mergeLlmParts } = await import("./validate-output-e0E998g_.js").then((n) => n.z);
145
+ const { mergeLlmParts } = await import("./validate-output-CRv_cnji.js").then((n) => n.A);
146
146
  const mergeWebsite = website;
147
147
  const partFiles = Array.from({ length: total }, (_, i) => path.join(llmPartsDir, `part.${i}.json`));
148
148
  const { pages } = await mergeLlmParts({
package/dist/ssg/cli.cjs CHANGED
@@ -3,7 +3,8 @@
3
3
  const process = require("node:process");
4
4
  const fs = require("node:fs/promises");
5
5
  const ssg_buildGrant = require("./build-grant.cjs");
6
- const llmArtifacts = require("../validate-output-DQTw64Rc.cjs");
6
+ const llmArtifacts = require("../validate-output-oVFDwKIA.cjs");
7
+ const pageTitle = require("../pageTitle-DyJ9r6xJ.cjs");
7
8
  function installFetchTimeout() {
8
9
  const ms = Number(process.env.BLOX_SSG_FETCH_TIMEOUT_MS) || 2e4;
9
10
  const original = globalThis.fetch;
@@ -141,7 +142,7 @@ Environment:
141
142
  if (shardsOpt !== null || routesCmd) {
142
143
  const { apiBase: apiBase2, websiteName: configWebsiteName2 } = await resolveApiBase(mode);
143
144
  const websiteName2 = process.env.WEBSITE_NAME ?? configWebsiteName2 ?? "default";
144
- const { runSharded } = await Promise.resolve().then(() => require("../shard-runner-CinJMC5z.cjs"));
145
+ const { runSharded } = await Promise.resolve().then(() => require("../shard-runner-BJ7J4qF3.cjs"));
145
146
  const code = await runSharded({
146
147
  shards: shardsOpt ?? "auto",
147
148
  mode,
@@ -175,6 +176,7 @@ Environment:
175
176
  let redirects = [];
176
177
  let cmsPathSet = /* @__PURE__ */ new Set();
177
178
  let cachedAppPaths = [];
179
+ let collectionItems;
178
180
  const productionBuild = process.env.NODE_ENV === "production" || mode === "production";
179
181
  try {
180
182
  const siteData = siteDataFile ? JSON.parse(await fs.readFile(siteDataFile, "utf8")) : await llmArtifacts.fetchCmsSiteData(apiBase, websiteName, buildRequest);
@@ -184,6 +186,7 @@ Environment:
184
186
  website = siteData.website;
185
187
  websiteId = siteData.websiteId;
186
188
  redirects = siteData.redirects;
189
+ collectionItems = siteData.collectionItems;
187
190
  if (!siteDataFile) {
188
191
  console.log(` Found ${paths.length} CMS routes`);
189
192
  if (redirects.length > 0) console.log(` Found ${redirects.length} redirects`);
@@ -193,6 +196,9 @@ Environment:
193
196
  if (productionBuild) throw err;
194
197
  paths = ["/"];
195
198
  }
199
+ if (collectionItems && Object.keys(collectionItems).length > 0) {
200
+ pageTitle.setCollectionResolver(llmArtifacts.buildCollectionResolver(collectionItems));
201
+ }
196
202
  for (const p of extraPaths) {
197
203
  if (!paths.includes(p)) paths.push(p);
198
204
  }
package/dist/ssg/cli.mjs CHANGED
@@ -2,7 +2,8 @@
2
2
  import process from "node:process";
3
3
  import fs from "node:fs/promises";
4
4
  import { resolveBloxBuildGrant } from "./build-grant.mjs";
5
- import { v as validateSsgOutput, u as uploadBloxManifest, p as polyfillBloxSsgGlobals, f as fetchCmsSiteData, a as prerender } from "../validate-output-e0E998g_.js";
5
+ import { v as validateSsgOutput, u as uploadBloxManifest, p as polyfillBloxSsgGlobals, f as fetchCmsSiteData, a as prerender, b as buildCollectionResolver } from "../validate-output-CRv_cnji.js";
6
+ import { s as setCollectionResolver } from "../pageTitle-tOzMNilm.js";
6
7
  function installFetchTimeout() {
7
8
  const ms = Number(process.env.BLOX_SSG_FETCH_TIMEOUT_MS) || 2e4;
8
9
  const original = globalThis.fetch;
@@ -140,7 +141,7 @@ Environment:
140
141
  if (shardsOpt !== null || routesCmd) {
141
142
  const { apiBase: apiBase2, websiteName: configWebsiteName2 } = await resolveApiBase(mode);
142
143
  const websiteName2 = process.env.WEBSITE_NAME ?? configWebsiteName2 ?? "default";
143
- const { runSharded } = await import("../shard-runner-C7_xAkA1.js");
144
+ const { runSharded } = await import("../shard-runner-BSUEe9p3.js");
144
145
  const code = await runSharded({
145
146
  shards: shardsOpt ?? "auto",
146
147
  mode,
@@ -174,6 +175,7 @@ Environment:
174
175
  let redirects = [];
175
176
  let cmsPathSet = /* @__PURE__ */ new Set();
176
177
  let cachedAppPaths = [];
178
+ let collectionItems;
177
179
  const productionBuild = process.env.NODE_ENV === "production" || mode === "production";
178
180
  try {
179
181
  const siteData = siteDataFile ? JSON.parse(await fs.readFile(siteDataFile, "utf8")) : await fetchCmsSiteData(apiBase, websiteName, buildRequest);
@@ -183,6 +185,7 @@ Environment:
183
185
  website = siteData.website;
184
186
  websiteId = siteData.websiteId;
185
187
  redirects = siteData.redirects;
188
+ collectionItems = siteData.collectionItems;
186
189
  if (!siteDataFile) {
187
190
  console.log(` Found ${paths.length} CMS routes`);
188
191
  if (redirects.length > 0) console.log(` Found ${redirects.length} redirects`);
@@ -192,6 +195,9 @@ Environment:
192
195
  if (productionBuild) throw err;
193
196
  paths = ["/"];
194
197
  }
198
+ if (collectionItems && Object.keys(collectionItems).length > 0) {
199
+ setCollectionResolver(buildCollectionResolver(collectionItems));
200
+ }
195
201
  for (const p of extraPaths) {
196
202
  if (!paths.includes(p)) paths.push(p);
197
203
  }
@@ -1,5 +1,5 @@
1
- import { B, r } from "../client-XQnL-B6N.js";
1
+ import { a, r } from "../client-Ce9fRCGH.js";
2
2
  export {
3
- B as BLOX_HYDRATION_WINDOW_KEY,
3
+ a as BLOX_HYDRATION_WINDOW_KEY,
4
4
  r as readBloxHydration
5
5
  };