@bagelink/blox 1.15.535 → 1.15.543

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.
@@ -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-2iH8f9ql.cjs");
29
+ const llmArtifacts = require("./validate-output-Dku8tCir.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
  function resolveShardCount(shards) {
@@ -95,7 +95,11 @@ async function runSharded(opts) {
95
95
  }
96
96
  console.log(`[blox-ssg] routes-cmd enumerated ${enumerated.length} route(s)`);
97
97
  }
98
- const siteData = await llmArtifacts.fetchCmsSiteData(opts.apiBase, opts.websiteName);
98
+ const siteData = await llmArtifacts.fetchCmsSiteData(
99
+ opts.apiBase,
100
+ opts.websiteName,
101
+ opts.buildRequest
102
+ );
99
103
  for (const p of siteData.paths) if (!paths.includes(p)) paths.push(p);
100
104
  const cmsPathSet = new Set(siteData.paths);
101
105
  const routerPaths = appPaths.filter((path2) => !cmsPathSet.has(path2));
@@ -133,7 +137,7 @@ async function runSharded(opts) {
133
137
  }
134
138
  if (process.env.BLOX_SSG_LLM !== "0") {
135
139
  try {
136
- const { mergeLlmParts } = await Promise.resolve().then(() => require("./validate-output-2iH8f9ql.cjs")).then((n) => n.llmArtifacts);
140
+ const { mergeLlmParts } = await Promise.resolve().then(() => require("./validate-output-Dku8tCir.cjs")).then((n) => n.llmArtifacts);
137
141
  const mergeWebsite = website;
138
142
  const partFiles = Array.from({ length: total }, (_, i) => path.join(llmPartsDir, `part.${i}.json`));
139
143
  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-CfHo6w9k.js";
5
+ import { f as fetchCmsSiteData, g as generateSitemapArtifacts } from "./validate-output-XdxaXjgE.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
  function resolveShardCount(shards) {
@@ -71,7 +71,11 @@ async function runSharded(opts) {
71
71
  }
72
72
  console.log(`[blox-ssg] routes-cmd enumerated ${enumerated.length} route(s)`);
73
73
  }
74
- const siteData = await fetchCmsSiteData(opts.apiBase, opts.websiteName);
74
+ const siteData = await fetchCmsSiteData(
75
+ opts.apiBase,
76
+ opts.websiteName,
77
+ opts.buildRequest
78
+ );
75
79
  for (const p of siteData.paths) if (!paths.includes(p)) paths.push(p);
76
80
  const cmsPathSet = new Set(siteData.paths);
77
81
  const routerPaths = appPaths.filter((path2) => !cmsPathSet.has(path2));
@@ -109,7 +113,7 @@ async function runSharded(opts) {
109
113
  }
110
114
  if (process.env.BLOX_SSG_LLM !== "0") {
111
115
  try {
112
- const { mergeLlmParts } = await import("./validate-output-CfHo6w9k.js").then((n) => n.A);
116
+ const { mergeLlmParts } = await import("./validate-output-XdxaXjgE.js").then((n) => n.A);
113
117
  const mergeWebsite = website;
114
118
  const partFiles = Array.from({ length: total }, (_, i) => path.join(llmPartsDir, `part.${i}.json`));
115
119
  const { pages } = await mergeLlmParts({
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const process = require("node:process");
4
+ const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
5
+ const PAYLOAD_FIELDS = /* @__PURE__ */ new Set(["version", "source", "website_id", "grant"]);
6
+ function parseJsonObject(value) {
7
+ let parsed;
8
+ try {
9
+ parsed = JSON.parse(value);
10
+ } catch {
11
+ throw new Error("Invalid Blox build hook payload");
12
+ }
13
+ if (parsed === null || Array.isArray(parsed) || typeof parsed !== "object") {
14
+ throw new Error("Invalid Blox build hook payload");
15
+ }
16
+ return parsed;
17
+ }
18
+ function parseBloxBuildGrantBody(body) {
19
+ const trimmed = body.trim();
20
+ if (!trimmed) throw new Error("Missing Blox build hook payload");
21
+ let payload;
22
+ try {
23
+ payload = parseJsonObject(trimmed);
24
+ } catch {
25
+ let decoded;
26
+ try {
27
+ decoded = decodeURIComponent(trimmed);
28
+ } catch {
29
+ throw new Error("Invalid Blox build hook payload");
30
+ }
31
+ payload = parseJsonObject(decoded);
32
+ }
33
+ if (Object.keys(payload).some((field) => !PAYLOAD_FIELDS.has(field))) {
34
+ throw new Error("Invalid Blox build hook payload fields");
35
+ }
36
+ if (payload.version !== 1 || payload.source !== "blox" || typeof payload.website_id !== "string" || !UUID_PATTERN.test(payload.website_id) || typeof payload.grant !== "string" || payload.grant.trim() === "") {
37
+ throw new Error("Invalid Blox build hook payload");
38
+ }
39
+ return {
40
+ version: 1,
41
+ source: "blox",
42
+ websiteId: payload.website_id,
43
+ grant: payload.grant
44
+ };
45
+ }
46
+ function isLocalOrTest(mode, env) {
47
+ return mode === "localhost" || mode === "development" || mode === "test" || env.NODE_ENV === "development" || env.NODE_ENV === "test";
48
+ }
49
+ function resolveBloxBuildGrant(options = {}) {
50
+ var _a, _b, _c, _d, _e;
51
+ const env = options.env ?? process.env;
52
+ if (isLocalOrTest(options.mode, env)) {
53
+ const websiteId = (_a = env.BLOX_WEBSITE_ID) == null ? void 0 : _a.trim();
54
+ const grant2 = (_b = env.BLOX_BUILD_TOKEN) == null ? void 0 : _b.trim();
55
+ if (!websiteId && !grant2) return void 0;
56
+ if (!websiteId || !UUID_PATTERN.test(websiteId) || !grant2) {
57
+ throw new Error("Local Blox build overrides require a valid BLOX_WEBSITE_ID and BLOX_BUILD_TOKEN");
58
+ }
59
+ return { version: 1, source: "blox", websiteId, grant: grant2 };
60
+ }
61
+ if (!((_c = env.INCOMING_HOOK_URL) == null ? void 0 : _c.trim()) || !((_d = env.INCOMING_HOOK_TITLE) == null ? void 0 : _d.trim())) {
62
+ throw new Error("Blox production builds require Netlify incoming hook metadata");
63
+ }
64
+ const body = env.INCOMING_HOOK_BODY;
65
+ if (body == null) throw new Error("Blox production builds require a hook payload");
66
+ const grant = parseBloxBuildGrantBody(body);
67
+ const configuredWebsiteId = (_e = env.BLOX_WEBSITE_ID) == null ? void 0 : _e.trim();
68
+ if (configuredWebsiteId && configuredWebsiteId !== grant.websiteId) {
69
+ throw new Error("Blox build hook website does not match the configured website");
70
+ }
71
+ return grant;
72
+ }
73
+ exports.parseBloxBuildGrantBody = parseBloxBuildGrantBody;
74
+ exports.resolveBloxBuildGrant = resolveBloxBuildGrant;
@@ -0,0 +1,18 @@
1
+ export interface BloxBuildGrant {
2
+ version: 1;
3
+ source: 'blox';
4
+ websiteId: string;
5
+ grant: string;
6
+ }
7
+ export interface ResolveBloxBuildGrantOptions {
8
+ mode?: string;
9
+ env?: NodeJS.ProcessEnv;
10
+ }
11
+ /** Parse a Netlify hook body as direct JSON or exactly one URL-decoded JSON value. */
12
+ export declare function parseBloxBuildGrantBody(body: string): BloxBuildGrant;
13
+ /**
14
+ * Resolve ephemeral build authority. Non-local builds only trust Netlify hook
15
+ * metadata and never fall back to long-lived environment credentials.
16
+ */
17
+ export declare function resolveBloxBuildGrant(options?: ResolveBloxBuildGrantOptions): BloxBuildGrant | undefined;
18
+ //# sourceMappingURL=build-grant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-grant.d.ts","sourceRoot":"","sources":["../../src/ssg/build-grant.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC9B,OAAO,EAAE,CAAC,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,4BAA4B;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;CACvB;AAkBD,sFAAsF;AACtF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAqCpE;AAUD;;;GAGG;AACH,wBAAgB,qBAAqB,CACpC,OAAO,GAAE,4BAAiC,GACxC,cAAc,GAAG,SAAS,CAuB5B"}
@@ -0,0 +1,74 @@
1
+ import process from "node:process";
2
+ const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
3
+ const PAYLOAD_FIELDS = /* @__PURE__ */ new Set(["version", "source", "website_id", "grant"]);
4
+ function parseJsonObject(value) {
5
+ let parsed;
6
+ try {
7
+ parsed = JSON.parse(value);
8
+ } catch {
9
+ throw new Error("Invalid Blox build hook payload");
10
+ }
11
+ if (parsed === null || Array.isArray(parsed) || typeof parsed !== "object") {
12
+ throw new Error("Invalid Blox build hook payload");
13
+ }
14
+ return parsed;
15
+ }
16
+ function parseBloxBuildGrantBody(body) {
17
+ const trimmed = body.trim();
18
+ if (!trimmed) throw new Error("Missing Blox build hook payload");
19
+ let payload;
20
+ try {
21
+ payload = parseJsonObject(trimmed);
22
+ } catch {
23
+ let decoded;
24
+ try {
25
+ decoded = decodeURIComponent(trimmed);
26
+ } catch {
27
+ throw new Error("Invalid Blox build hook payload");
28
+ }
29
+ payload = parseJsonObject(decoded);
30
+ }
31
+ if (Object.keys(payload).some((field) => !PAYLOAD_FIELDS.has(field))) {
32
+ throw new Error("Invalid Blox build hook payload fields");
33
+ }
34
+ if (payload.version !== 1 || payload.source !== "blox" || typeof payload.website_id !== "string" || !UUID_PATTERN.test(payload.website_id) || typeof payload.grant !== "string" || payload.grant.trim() === "") {
35
+ throw new Error("Invalid Blox build hook payload");
36
+ }
37
+ return {
38
+ version: 1,
39
+ source: "blox",
40
+ websiteId: payload.website_id,
41
+ grant: payload.grant
42
+ };
43
+ }
44
+ function isLocalOrTest(mode, env) {
45
+ return mode === "localhost" || mode === "development" || mode === "test" || env.NODE_ENV === "development" || env.NODE_ENV === "test";
46
+ }
47
+ function resolveBloxBuildGrant(options = {}) {
48
+ var _a, _b, _c, _d, _e;
49
+ const env = options.env ?? process.env;
50
+ if (isLocalOrTest(options.mode, env)) {
51
+ const websiteId = (_a = env.BLOX_WEBSITE_ID) == null ? void 0 : _a.trim();
52
+ const grant2 = (_b = env.BLOX_BUILD_TOKEN) == null ? void 0 : _b.trim();
53
+ if (!websiteId && !grant2) return void 0;
54
+ if (!websiteId || !UUID_PATTERN.test(websiteId) || !grant2) {
55
+ throw new Error("Local Blox build overrides require a valid BLOX_WEBSITE_ID and BLOX_BUILD_TOKEN");
56
+ }
57
+ return { version: 1, source: "blox", websiteId, grant: grant2 };
58
+ }
59
+ if (!((_c = env.INCOMING_HOOK_URL) == null ? void 0 : _c.trim()) || !((_d = env.INCOMING_HOOK_TITLE) == null ? void 0 : _d.trim())) {
60
+ throw new Error("Blox production builds require Netlify incoming hook metadata");
61
+ }
62
+ const body = env.INCOMING_HOOK_BODY;
63
+ if (body == null) throw new Error("Blox production builds require a hook payload");
64
+ const grant = parseBloxBuildGrantBody(body);
65
+ const configuredWebsiteId = (_e = env.BLOX_WEBSITE_ID) == null ? void 0 : _e.trim();
66
+ if (configuredWebsiteId && configuredWebsiteId !== grant.websiteId) {
67
+ throw new Error("Blox build hook website does not match the configured website");
68
+ }
69
+ return grant;
70
+ }
71
+ export {
72
+ parseBloxBuildGrantBody,
73
+ resolveBloxBuildGrant
74
+ };
@@ -1,4 +1,6 @@
1
1
  export interface BloxBuildRequestOptions {
2
+ /** Website authorized by the ephemeral build grant. */
3
+ websiteId?: string;
2
4
  /** Server-only build token. Never use a VITE_-prefixed environment variable. */
3
5
  token?: string;
4
6
  /** Header accepted by the build API/gateway. @default "Authorization" */
@@ -1 +1 @@
1
- {"version":3,"file":"build-request.d.ts","sourceRoot":"","sources":["../../src/ssg/build-request.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,uBAAuB;IACvC,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qCAAqC;IACrC,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,qBAAa,sBAAuB,SAAQ,KAAK;aAE/B,MAAM,EAAE,MAAM;aACd,GAAG,EAAE,MAAM;gBADX,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EAC3B,UAAU,EAAE,MAAM;CAKnB;AAMD,uFAAuF;AACvF,wBAAgB,0BAA0B,CACzC,SAAS,GAAE,uBAA4B,GACrC,uBAAuB,CAWzB;AAMD,gFAAgF;AAChF,wBAAsB,gBAAgB,CACrC,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,GAAE,WAAgB,EACtB,OAAO,GAAE,uBAA4B,GACnC,OAAO,CAAC,QAAQ,CAAC,CAiCnB;AAED,sEAAsE;AACtE,wBAAsB,aAAa,CAAC,CAAC,EACpC,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,GAAE,WAAgB,EACtB,OAAO,GAAE,uBAA4B,GACnC,OAAO,CAAC,CAAC,CAAC,CAQZ"}
1
+ {"version":3,"file":"build-request.d.ts","sourceRoot":"","sources":["../../src/ssg/build-request.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,uBAAuB;IACvC,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qCAAqC;IACrC,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,qBAAa,sBAAuB,SAAQ,KAAK;aAE/B,MAAM,EAAE,MAAM;aACd,GAAG,EAAE,MAAM;gBADX,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EAC3B,UAAU,EAAE,MAAM;CAKnB;AAMD,uFAAuF;AACvF,wBAAgB,0BAA0B,CACzC,SAAS,GAAE,uBAA4B,GACrC,uBAAuB,CAYzB;AAMD,gFAAgF;AAChF,wBAAsB,gBAAgB,CACrC,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,GAAE,WAAgB,EACtB,OAAO,GAAE,uBAA4B,GACnC,OAAO,CAAC,QAAQ,CAAC,CAiCnB;AAED,sEAAsE;AACtE,wBAAsB,aAAa,CAAC,CAAC,EACpC,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,GAAE,WAAgB,EACtB,OAAO,GAAE,uBAA4B,GACnC,OAAO,CAAC,CAAC,CAAC,CAQZ"}
package/dist/ssg/cli.cjs CHANGED
@@ -2,7 +2,8 @@
2
2
  "use strict";
3
3
  const process = require("node:process");
4
4
  const fs = require("node:fs/promises");
5
- const llmArtifacts = require("../validate-output-2iH8f9ql.cjs");
5
+ const ssg_buildGrant = require("./build-grant.cjs");
6
+ const llmArtifacts = require("../validate-output-Dku8tCir.cjs");
6
7
  function installFetchTimeout() {
7
8
  const ms = Number(process.env.BLOX_SSG_FETCH_TIMEOUT_MS) || 2e4;
8
9
  const original = globalThis.fetch;
@@ -131,15 +132,22 @@ Environment:
131
132
  console.log(`[blox-ssg] validated output in ${validateOutDir}`);
132
133
  return;
133
134
  }
135
+ const buildGrant = ssg_buildGrant.resolveBloxBuildGrant({ mode });
136
+ if (buildGrant) {
137
+ process.env.BLOX_WEBSITE_ID = buildGrant.websiteId;
138
+ process.env.BLOX_BUILD_TOKEN = buildGrant.grant;
139
+ }
140
+ const buildRequest = buildGrant ? { websiteId: buildGrant.websiteId, token: buildGrant.grant } : {};
134
141
  if (shardsOpt !== null || routesCmd) {
135
142
  const { apiBase: apiBase2, websiteName: configWebsiteName2 } = await resolveApiBase(mode);
136
143
  const websiteName2 = process.env.WEBSITE_NAME ?? configWebsiteName2 ?? "default";
137
- const { runSharded } = await Promise.resolve().then(() => require("../shard-runner-C-OeWaVM.cjs"));
144
+ const { runSharded } = await Promise.resolve().then(() => require("../shard-runner-DOK26Y78.cjs"));
138
145
  const code = await runSharded({
139
146
  shards: shardsOpt ?? "auto",
140
147
  mode,
141
148
  apiBase: apiBase2,
142
149
  websiteName: websiteName2,
150
+ buildRequest,
143
151
  extraPaths,
144
152
  passthroughArgs,
145
153
  routesCmd: routesCmd || void 0
@@ -147,7 +155,7 @@ Environment:
147
155
  if (code === 0 && (process.env.NODE_ENV === "production" || mode === "production")) {
148
156
  const uploadWebsiteId = (_a = process.env.BLOX_WEBSITE_ID) == null ? void 0 : _a.trim();
149
157
  if (uploadWebsiteId) {
150
- await llmArtifacts.uploadBloxManifest(apiBase2, uploadWebsiteId);
158
+ await llmArtifacts.uploadBloxManifest(apiBase2, uploadWebsiteId, buildRequest);
151
159
  console.log("Uploaded .blox-manifest.json with Git provenance");
152
160
  } else {
153
161
  console.log("Skipped Blox manifest upload (BLOX_WEBSITE_ID is not configured)");
@@ -169,7 +177,7 @@ Environment:
169
177
  let cachedAppPaths = [];
170
178
  const productionBuild = process.env.NODE_ENV === "production" || mode === "production";
171
179
  try {
172
- const siteData = siteDataFile ? JSON.parse(await fs.readFile(siteDataFile, "utf8")) : await llmArtifacts.fetchCmsSiteData(apiBase, websiteName);
180
+ const siteData = siteDataFile ? JSON.parse(await fs.readFile(siteDataFile, "utf8")) : await llmArtifacts.fetchCmsSiteData(apiBase, websiteName, buildRequest);
173
181
  paths = siteData.paths;
174
182
  cachedAppPaths = "appPaths" in siteData && Array.isArray(siteData.appPaths) ? siteData.appPaths : [];
175
183
  cmsPathSet = new Set(siteData.paths.filter((path) => !cachedAppPaths.includes(path)));
@@ -270,7 +278,7 @@ ${"=".repeat(60)}`);
270
278
  if (productionBuild && shardTotal === 1) {
271
279
  const uploadWebsiteId = ((_b = process.env.BLOX_WEBSITE_ID) == null ? void 0 : _b.trim()) || websiteId;
272
280
  if (!uploadWebsiteId) throw new Error("BLOX_WEBSITE_ID is required to upload the Blox manifest");
273
- await llmArtifacts.uploadBloxManifest(apiBase, uploadWebsiteId);
281
+ await llmArtifacts.uploadBloxManifest(apiBase, uploadWebsiteId, buildRequest);
274
282
  console.log("Uploaded .blox-manifest.json with Git provenance");
275
283
  }
276
284
  } catch (err) {
package/dist/ssg/cli.mjs CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env bun
2
2
  import process from "node:process";
3
3
  import fs from "node:fs/promises";
4
- import { v as validateSsgOutput, u as uploadBloxManifest, p as polyfillBloxSsgGlobals, f as fetchCmsSiteData, a as prerender } from "../validate-output-CfHo6w9k.js";
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-XdxaXjgE.js";
5
6
  function installFetchTimeout() {
6
7
  const ms = Number(process.env.BLOX_SSG_FETCH_TIMEOUT_MS) || 2e4;
7
8
  const original = globalThis.fetch;
@@ -130,15 +131,22 @@ Environment:
130
131
  console.log(`[blox-ssg] validated output in ${validateOutDir}`);
131
132
  return;
132
133
  }
134
+ const buildGrant = resolveBloxBuildGrant({ mode });
135
+ if (buildGrant) {
136
+ process.env.BLOX_WEBSITE_ID = buildGrant.websiteId;
137
+ process.env.BLOX_BUILD_TOKEN = buildGrant.grant;
138
+ }
139
+ const buildRequest = buildGrant ? { websiteId: buildGrant.websiteId, token: buildGrant.grant } : {};
133
140
  if (shardsOpt !== null || routesCmd) {
134
141
  const { apiBase: apiBase2, websiteName: configWebsiteName2 } = await resolveApiBase(mode);
135
142
  const websiteName2 = process.env.WEBSITE_NAME ?? configWebsiteName2 ?? "default";
136
- const { runSharded } = await import("../shard-runner-Aw77Pe6C.js");
143
+ const { runSharded } = await import("../shard-runner-Ic_t76Xj.js");
137
144
  const code = await runSharded({
138
145
  shards: shardsOpt ?? "auto",
139
146
  mode,
140
147
  apiBase: apiBase2,
141
148
  websiteName: websiteName2,
149
+ buildRequest,
142
150
  extraPaths,
143
151
  passthroughArgs,
144
152
  routesCmd: routesCmd || void 0
@@ -146,7 +154,7 @@ Environment:
146
154
  if (code === 0 && (process.env.NODE_ENV === "production" || mode === "production")) {
147
155
  const uploadWebsiteId = (_a = process.env.BLOX_WEBSITE_ID) == null ? void 0 : _a.trim();
148
156
  if (uploadWebsiteId) {
149
- await uploadBloxManifest(apiBase2, uploadWebsiteId);
157
+ await uploadBloxManifest(apiBase2, uploadWebsiteId, buildRequest);
150
158
  console.log("Uploaded .blox-manifest.json with Git provenance");
151
159
  } else {
152
160
  console.log("Skipped Blox manifest upload (BLOX_WEBSITE_ID is not configured)");
@@ -168,7 +176,7 @@ Environment:
168
176
  let cachedAppPaths = [];
169
177
  const productionBuild = process.env.NODE_ENV === "production" || mode === "production";
170
178
  try {
171
- const siteData = siteDataFile ? JSON.parse(await fs.readFile(siteDataFile, "utf8")) : await fetchCmsSiteData(apiBase, websiteName);
179
+ const siteData = siteDataFile ? JSON.parse(await fs.readFile(siteDataFile, "utf8")) : await fetchCmsSiteData(apiBase, websiteName, buildRequest);
172
180
  paths = siteData.paths;
173
181
  cachedAppPaths = "appPaths" in siteData && Array.isArray(siteData.appPaths) ? siteData.appPaths : [];
174
182
  cmsPathSet = new Set(siteData.paths.filter((path) => !cachedAppPaths.includes(path)));
@@ -269,7 +277,7 @@ ${"=".repeat(60)}`);
269
277
  if (productionBuild && shardTotal === 1) {
270
278
  const uploadWebsiteId = ((_b = process.env.BLOX_WEBSITE_ID) == null ? void 0 : _b.trim()) || websiteId;
271
279
  if (!uploadWebsiteId) throw new Error("BLOX_WEBSITE_ID is required to upload the Blox manifest");
272
- await uploadBloxManifest(apiBase, uploadWebsiteId);
280
+ await uploadBloxManifest(apiBase, uploadWebsiteId, buildRequest);
273
281
  console.log("Uploaded .blox-manifest.json with Git provenance");
274
282
  }
275
283
  } catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"cms-routes.d.ts","sourceRoot":"","sources":["../../src/ssg/cms-routes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAC1C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAoB9D,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,WAAW;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,WAAW,CAAA;IACpB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,SAAS,EAAE,aAAa,EAAE,CAAA;IAC1B,oEAAoE;IACpE,WAAW,EAAE,aAAa,EAAE,CAAA;CAC5B;AAYD;;;GAGG;AACH,wBAAgB,iBAAiB,CAChC,KAAK,EAAE,MAAM,EAAE,EACf,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,MAAM,EAAE,GACxB,MAAM,EAAE,CASV;AAMD;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,cAAc,GAAE,uBAA4B,GAC1C,OAAO,CAAC,WAAW,CAAC,CAwGtB;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC3C,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,cAAc,GAAE,uBAA4B,GAC1C,OAAO,CAAC,MAAM,EAAE,CAAC,CAGnB"}
1
+ {"version":3,"file":"cms-routes.d.ts","sourceRoot":"","sources":["../../src/ssg/cms-routes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAC1C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAoB9D,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,WAAW;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,WAAW,CAAA;IACpB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,SAAS,EAAE,aAAa,EAAE,CAAA;IAC1B,oEAAoE;IACpE,WAAW,EAAE,aAAa,EAAE,CAAA;CAC5B;AAYD;;;GAGG;AACH,wBAAgB,iBAAiB,CAChC,KAAK,EAAE,MAAM,EAAE,EACf,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,MAAM,EAAE,GACxB,MAAM,EAAE,CASV;AAMD;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,cAAc,GAAE,uBAA4B,GAC1C,OAAO,CAAC,WAAW,CAAC,CA4GtB;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC3C,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,cAAc,GAAE,uBAA4B,GAC1C,OAAO,CAAC,MAAM,EAAE,CAAC,CAGnB"}
@@ -26,6 +26,11 @@ export interface CreateBloxSSREntryOptions {
26
26
  apiBase?: string;
27
27
  /** Build-only authentication/headers. Defaults to BLOX_BUILD_TOKEN env. */
28
28
  buildRequest?: BloxBuildRequestOptions;
29
+ /**
30
+ * Resolve concrete paths through `/resolve-path` even when a build website
31
+ * ID is available. This expands dynamic templates such as `/article/:slug`.
32
+ */
33
+ resolvePublishedPaths?: boolean;
29
34
  /** Immutable build-time datastore resolver used by content routes and SEO. */
30
35
  collectionResolver?: (collection: string, options: ListItemsOptions) => Promise<Array<Record<string, unknown>>>;
31
36
  /** Default locale. @default 'en' */
@@ -50,6 +55,10 @@ export interface BloxSSREntry {
50
55
  /** Resolve a URL's page data without rendering (for batched prefetch). */
51
56
  prefetchResolve?: (url: string) => Promise<unknown>;
52
57
  }
58
+ interface PublishedPage {
59
+ slug?: string;
60
+ }
61
+ export declare function matchPublishedPage(pages: PublishedPage[], slug: string, allowTemplates?: boolean): PublishedPage | null;
53
62
  /**
54
63
  * Factory that produces the `{ render }` export for `main.server.ts`.
55
64
  *
@@ -80,4 +89,5 @@ export interface BloxSSREntry {
80
89
  * ```
81
90
  */
82
91
  export declare function createBloxSSREntry(options: CreateBloxSSREntryOptions): BloxSSREntry;
92
+ export {};
83
93
  //# sourceMappingURL=createSSREntry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createSSREntry.d.ts","sourceRoot":"","sources":["../../src/ssg/createSSREntry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,KAAK,CAAA;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG9D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAO9D,OAAO,EAAuC,KAAK,gBAAgB,EAAE,MAAM,QAAQ,CAAA;AAInF,MAAM,WAAW,yBAAyB;IACzC,oCAAoC;IACpC,aAAa,EAAE,SAAS,CAAA;IACxB;;;;OAIG;IACH,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,QAAQ,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IAC9D;;;OAGG;IACH,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IACpD,wBAAwB;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,oGAAoG;IACpG,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,uBAAuB,CAAA;IACtC,8EAA8E;IAC9E,kBAAkB,CAAC,EAAE,CACpB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,gBAAgB,KACrB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IAC5C,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,2CAA2C;IAC3C,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC3B;;;OAGG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,OAAO,KAAK,EAAE,MAAM,GAAG,CAAC,OAAO,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,CAAA;IAC5E;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAC5C,kDAAkD;IAClD,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;CAC1B;AAED,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,YAAY,CAAC,CAAA;IAClE,0EAA0E;IAC1E,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACnD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,YAAY,CAoNnF"}
1
+ {"version":3,"file":"createSSREntry.d.ts","sourceRoot":"","sources":["../../src/ssg/createSSREntry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,KAAK,CAAA;AACzC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG9D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAO9D,OAAO,EAAuC,KAAK,gBAAgB,EAAE,MAAM,QAAQ,CAAA;AAInF,MAAM,WAAW,yBAAyB;IACzC,oCAAoC;IACpC,aAAa,EAAE,SAAS,CAAA;IACxB;;;;OAIG;IACH,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,QAAQ,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IAC9D;;;OAGG;IACH,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IACpD,wBAAwB;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,oGAAoG;IACpG,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,uBAAuB,CAAA;IACtC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,8EAA8E;IAC9E,kBAAkB,CAAC,EAAE,CACpB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,gBAAgB,KACrB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IAC5C,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,2CAA2C;IAC3C,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC3B;;;OAGG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,OAAO,KAAK,EAAE,MAAM,GAAG,CAAC,OAAO,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,CAAA;IAC5E;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAC5C,kDAAkD;IAClD,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;CAC1B;AAED,MAAM,WAAW,YAAY;IAC5B,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,YAAY,CAAC,CAAA;IAClE,0EAA0E;IAC1E,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACnD;AAED,UAAU,aAAa;IACtB,IAAI,CAAC,EAAE,MAAM,CAAA;CACb;AAED,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,aAAa,EAAE,EACtB,IAAI,EAAE,MAAM,EACZ,cAAc,UAAQ,GACpB,aAAa,GAAG,IAAI,CAUtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,YAAY,CA0NnF"}
@@ -22,7 +22,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
22
22
  mod
23
23
  ));
24
24
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
25
- const llmArtifacts = require("../validate-output-2iH8f9ql.cjs");
25
+ const llmArtifacts = require("../validate-output-Dku8tCir.cjs");
26
+ const ssg_buildGrant = require("./build-grant.cjs");
26
27
  const ssg_client = require("./client.cjs");
27
28
  const pinia = require("pinia");
28
29
  const vue = require("vue");
@@ -111,6 +112,18 @@ ${jsonLd}`;
111
112
  function safeJson(value) {
112
113
  return JSON.stringify(value).replace(/</g, "\\u003c");
113
114
  }
115
+ function matchPublishedPage(pages, slug, allowTemplates = false) {
116
+ var _a;
117
+ const exact = pages.find((page) => page.slug === slug);
118
+ if (exact) return exact;
119
+ if (!allowTemplates) return null;
120
+ for (const template of pages) {
121
+ if (!((_a = template.slug) == null ? void 0 : _a.includes(":"))) continue;
122
+ const pattern = template.slug.replace(/:[a-z_]+/g, "[^/]+");
123
+ if (new RegExp(`^${pattern}$`).test(slug)) return template;
124
+ }
125
+ return null;
126
+ }
114
127
  function createBloxSSREntry(options) {
115
128
  var _a;
116
129
  const {
@@ -127,12 +140,13 @@ function createBloxSSREntry(options) {
127
140
  } = options;
128
141
  const apiBase = options.apiBase ?? (typeof process !== "undefined" ? (_a = process.env) == null ? void 0 : _a.BAGELINK_API_URL : void 0) ?? "https://api.bagel.to";
129
142
  let websiteIdCache = null;
143
+ const publishedBundleCache = /* @__PURE__ */ new Map();
130
144
  routes.setApiOrigin(apiBase);
131
145
  routes.setCollectionResolver(options.collectionResolver ?? null);
132
146
  async function getWebsiteId() {
133
- var _a2, _b;
147
+ var _a2, _b, _c;
134
148
  if (websiteIdCache) return websiteIdCache;
135
- const configuredWebsiteId = typeof process !== "undefined" ? (_b = (_a2 = process.env) == null ? void 0 : _a2.BLOX_WEBSITE_ID) == null ? void 0 : _b.trim() : void 0;
149
+ const configuredWebsiteId = ((_a2 = options.buildRequest) == null ? void 0 : _a2.websiteId) ?? (typeof process !== "undefined" ? (_c = (_b = process.env) == null ? void 0 : _b.BLOX_WEBSITE_ID) == null ? void 0 : _c.trim() : void 0);
136
150
  if (configuredWebsiteId) {
137
151
  websiteIdCache = configuredWebsiteId;
138
152
  return websiteIdCache;
@@ -156,18 +170,27 @@ function createBloxSSREntry(options) {
156
170
  return { locale, slug: urlPath || "/" };
157
171
  }
158
172
  async function fetchResolvedPage(slug, pageLocale) {
159
- var _a2, _b;
173
+ var _a2, _b, _c;
160
174
  const websiteId = await getWebsiteId();
161
- const configuredWebsiteId = typeof process !== "undefined" ? (_b = (_a2 = process.env) == null ? void 0 : _a2.BLOX_WEBSITE_ID) == null ? void 0 : _b.trim() : void 0;
175
+ const configuredWebsiteId = ((_a2 = options.buildRequest) == null ? void 0 : _a2.websiteId) ?? (typeof process !== "undefined" ? (_c = (_b = process.env) == null ? void 0 : _b.BLOX_WEBSITE_ID) == null ? void 0 : _c.trim() : void 0);
162
176
  if (configuredWebsiteId) {
163
- const bundle = await llmArtifacts.bloxBuildJson(
164
- `${apiBase}/blox-build/websites/${websiteId}/published?locale=${encodeURIComponent(pageLocale)}`,
165
- {},
166
- options.buildRequest
177
+ const cacheKey = pageLocale;
178
+ let pending = publishedBundleCache.get(cacheKey);
179
+ if (!pending) {
180
+ pending = llmArtifacts.bloxBuildJson(
181
+ `${apiBase}/blox-build/websites/${websiteId}/published?locale=${encodeURIComponent(pageLocale)}`,
182
+ {},
183
+ options.buildRequest
184
+ );
185
+ publishedBundleCache.set(cacheKey, pending);
186
+ }
187
+ const bundle = await pending;
188
+ const page = matchPublishedPage(
189
+ bundle.pages,
190
+ slug,
191
+ options.resolvePublishedPaths
167
192
  );
168
- const page = bundle.pages.find((candidate) => candidate.slug === slug);
169
- if (!page) return null;
170
- return { page, contexts: {}, warnings: [] };
193
+ return page ? { page, contexts: {}, warnings: [] } : null;
171
194
  }
172
195
  const url = `${apiBase}/blox/websites/${websiteId}/resolve-path?path=${encodeURIComponent(slug)}&locale=${pageLocale}`;
173
196
  return llmArtifacts.bloxBuildJson(url, {}, options.buildRequest);
@@ -351,6 +374,8 @@ exports.resolveManifestProvenance = llmArtifacts.resolveManifestProvenance;
351
374
  exports.splitSitemapPathsByLocale = llmArtifacts.splitSitemapPathsByLocale;
352
375
  exports.uploadBloxManifest = llmArtifacts.uploadBloxManifest;
353
376
  exports.validateSsgOutput = llmArtifacts.validateSsgOutput;
377
+ exports.parseBloxBuildGrantBody = ssg_buildGrant.parseBloxBuildGrantBody;
378
+ exports.resolveBloxBuildGrant = ssg_buildGrant.resolveBloxBuildGrant;
354
379
  exports.BLOX_COLLECTIONS_WINDOW_KEY = ssg_client.BLOX_COLLECTIONS_WINDOW_KEY;
355
380
  exports.BLOX_DATA_WINDOW_KEY = ssg_client.BLOX_DATA_WINDOW_KEY;
356
381
  exports.BLOX_PAGE_SEO_WINDOW_KEY = ssg_client.BLOX_PAGE_SEO_WINDOW_KEY;
@@ -1,6 +1,8 @@
1
1
  export { fetchCmsPrerenderPaths, fetchCmsSiteData } from './cms-routes';
2
2
  export type { CmsSiteData, CollectionRef } from './cms-routes';
3
3
  export { BloxBuildResponseError, bloxBuildJson, bloxBuildRequest, getBloxBuildRequestOptions } from './build-request';
4
+ export { parseBloxBuildGrantBody, resolveBloxBuildGrant } from './build-grant';
5
+ export type { BloxBuildGrant, ResolveBloxBuildGrantOptions } from './build-grant';
4
6
  export type { BloxBuildRequestOptions } from './build-request';
5
7
  export { getCollectionCache, getEmbeddedWebsiteId, installCollectionCache } from './collection-cache';
6
8
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ssg/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACvE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC9D,OAAO,EAAE,sBAAsB,EAAE,aAAa,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAA;AACrH,YAAY,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAC9D,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AACrG;;;;;;;;;;GAUG;AACH,OAAO,EAAE,2BAA2B,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAA;AAC5J,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,YAAY,EAAE,YAAY,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAA;AAC/E,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAC9F,YAAY,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACjG,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC1D,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,OAAO,CAAA;AACxO,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AACtF,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,mBAAmB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACnH,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACjF,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,YAAY,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ssg/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACvE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC9D,OAAO,EAAE,sBAAsB,EAAE,aAAa,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAA;AACrH,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAC9E,YAAY,EAAE,cAAc,EAAE,4BAA4B,EAAE,MAAM,eAAe,CAAA;AACjF,YAAY,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAC9D,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AACrG;;;;;;;;;;GAUG;AACH,OAAO,EAAE,2BAA2B,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAA;AAC5J,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,YAAY,EAAE,YAAY,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAA;AAC/E,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAC9F,YAAY,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACjG,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC1D,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,OAAO,CAAA;AACxO,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AACtF,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,mBAAmB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACnH,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACjF,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,YAAY,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAA"}
@@ -1,5 +1,6 @@
1
- import { b as buildPageHead, c as primaryContextEntry, d as buildJsonLd, e as extractPageText, B as BloxBuildResponseError, h as bloxBuildJson } from "../validate-output-CfHo6w9k.js";
2
- import { i, j, k, f, l, m, n, o, g, q, r, s, t, w, x, p, a, y, z, u, v } from "../validate-output-CfHo6w9k.js";
1
+ import { b as buildPageHead, c as primaryContextEntry, d as buildJsonLd, e as extractPageText, B as BloxBuildResponseError, h as bloxBuildJson } from "../validate-output-XdxaXjgE.js";
2
+ import { i, j, k, f, l, m, n, o, g, q, r, s, t, w, x, p, a, y, z, u, v } from "../validate-output-XdxaXjgE.js";
3
+ import { parseBloxBuildGrantBody, resolveBloxBuildGrant } from "./build-grant.mjs";
3
4
  import { BLOX_STATE_WINDOW_KEY, BLOX_WEBSITE_ID_WINDOW_KEY } from "./client.mjs";
4
5
  import { BLOX_COLLECTIONS_WINDOW_KEY, BLOX_DATA_WINDOW_KEY, BLOX_PAGE_SEO_WINDOW_KEY, getCollectionCache, getEmbeddedWebsiteId, installBloxStateCache, installCollectionCache } from "./client.mjs";
5
6
  import { createPinia } from "pinia";
@@ -89,6 +90,18 @@ ${jsonLd}`;
89
90
  function safeJson(value) {
90
91
  return JSON.stringify(value).replace(/</g, "\\u003c");
91
92
  }
93
+ function matchPublishedPage(pages, slug, allowTemplates = false) {
94
+ var _a;
95
+ const exact = pages.find((page) => page.slug === slug);
96
+ if (exact) return exact;
97
+ if (!allowTemplates) return null;
98
+ for (const template of pages) {
99
+ if (!((_a = template.slug) == null ? void 0 : _a.includes(":"))) continue;
100
+ const pattern = template.slug.replace(/:[a-z_]+/g, "[^/]+");
101
+ if (new RegExp(`^${pattern}$`).test(slug)) return template;
102
+ }
103
+ return null;
104
+ }
92
105
  function createBloxSSREntry(options) {
93
106
  var _a;
94
107
  const {
@@ -105,12 +118,13 @@ function createBloxSSREntry(options) {
105
118
  } = options;
106
119
  const apiBase = options.apiBase ?? (typeof process !== "undefined" ? (_a = process.env) == null ? void 0 : _a.BAGELINK_API_URL : void 0) ?? "https://api.bagel.to";
107
120
  let websiteIdCache = null;
121
+ const publishedBundleCache = /* @__PURE__ */ new Map();
108
122
  setApiOrigin(apiBase);
109
123
  setCollectionResolver(options.collectionResolver ?? null);
110
124
  async function getWebsiteId() {
111
- var _a2, _b;
125
+ var _a2, _b, _c;
112
126
  if (websiteIdCache) return websiteIdCache;
113
- const configuredWebsiteId = typeof process !== "undefined" ? (_b = (_a2 = process.env) == null ? void 0 : _a2.BLOX_WEBSITE_ID) == null ? void 0 : _b.trim() : void 0;
127
+ const configuredWebsiteId = ((_a2 = options.buildRequest) == null ? void 0 : _a2.websiteId) ?? (typeof process !== "undefined" ? (_c = (_b = process.env) == null ? void 0 : _b.BLOX_WEBSITE_ID) == null ? void 0 : _c.trim() : void 0);
114
128
  if (configuredWebsiteId) {
115
129
  websiteIdCache = configuredWebsiteId;
116
130
  return websiteIdCache;
@@ -134,18 +148,27 @@ function createBloxSSREntry(options) {
134
148
  return { locale, slug: urlPath || "/" };
135
149
  }
136
150
  async function fetchResolvedPage(slug, pageLocale) {
137
- var _a2, _b;
151
+ var _a2, _b, _c;
138
152
  const websiteId = await getWebsiteId();
139
- const configuredWebsiteId = typeof process !== "undefined" ? (_b = (_a2 = process.env) == null ? void 0 : _a2.BLOX_WEBSITE_ID) == null ? void 0 : _b.trim() : void 0;
153
+ const configuredWebsiteId = ((_a2 = options.buildRequest) == null ? void 0 : _a2.websiteId) ?? (typeof process !== "undefined" ? (_c = (_b = process.env) == null ? void 0 : _b.BLOX_WEBSITE_ID) == null ? void 0 : _c.trim() : void 0);
140
154
  if (configuredWebsiteId) {
141
- const bundle = await bloxBuildJson(
142
- `${apiBase}/blox-build/websites/${websiteId}/published?locale=${encodeURIComponent(pageLocale)}`,
143
- {},
144
- options.buildRequest
155
+ const cacheKey = pageLocale;
156
+ let pending = publishedBundleCache.get(cacheKey);
157
+ if (!pending) {
158
+ pending = bloxBuildJson(
159
+ `${apiBase}/blox-build/websites/${websiteId}/published?locale=${encodeURIComponent(pageLocale)}`,
160
+ {},
161
+ options.buildRequest
162
+ );
163
+ publishedBundleCache.set(cacheKey, pending);
164
+ }
165
+ const bundle = await pending;
166
+ const page = matchPublishedPage(
167
+ bundle.pages,
168
+ slug,
169
+ options.resolvePublishedPaths
145
170
  );
146
- const page = bundle.pages.find((candidate) => candidate.slug === slug);
147
- if (!page) return null;
148
- return { page, contexts: {}, warnings: [] };
171
+ return page ? { page, contexts: {}, warnings: [] } : null;
149
172
  }
150
173
  const url = `${apiBase}/blox/websites/${websiteId}/resolve-path?path=${encodeURIComponent(slug)}&locale=${pageLocale}`;
151
174
  return bloxBuildJson(url, {}, options.buildRequest);
@@ -335,10 +358,12 @@ export {
335
358
  installCollectionCache,
336
359
  w as localeSitemapPath,
337
360
  x as mergeLlmParts,
361
+ parseBloxBuildGrantBody,
338
362
  p as polyfillBloxSsgGlobals,
339
363
  a as prerender,
340
364
  querySnapshotRows,
341
365
  renderBloxSsgPage,
366
+ resolveBloxBuildGrant,
342
367
  y as resolveManifestProvenance,
343
368
  snapshotRows,
344
369
  z as splitSitemapPathsByLocale,
@@ -1,4 +1,5 @@
1
1
  import { BloxManifest } from '../manifest';
2
+ import { BloxBuildRequestOptions } from './build-request';
2
3
  export interface ManifestProvenance {
3
4
  repository: string;
4
5
  branch: string;
@@ -9,5 +10,5 @@ export interface ManifestUpload {
9
10
  provenance: ManifestProvenance;
10
11
  }
11
12
  export declare function resolveManifestProvenance(): Promise<ManifestProvenance>;
12
- export declare function uploadBloxManifest(apiBase: string, websiteId: string): Promise<void>;
13
+ export declare function uploadBloxManifest(apiBase: string, websiteId: string, requestOptions?: BloxBuildRequestOptions): Promise<void>;
13
14
  //# sourceMappingURL=manifest-upload.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manifest-upload.d.ts","sourceRoot":"","sources":["../../src/ssg/manifest-upload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAO/C,MAAM,WAAW,kBAAkB;IAClC,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,EAAE,YAAY,CAAA;IACtB,UAAU,EAAE,kBAAkB,CAAA;CAC9B;AAsBD,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAgB7E;AAED,wBAAsB,kBAAkB,CACvC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAmBf"}
1
+ {"version":3,"file":"manifest-upload.d.ts","sourceRoot":"","sources":["../../src/ssg/manifest-upload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAK/C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAG9D,MAAM,WAAW,kBAAkB;IAClC,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,EAAE,YAAY,CAAA;IACtB,UAAU,EAAE,kBAAkB,CAAA;CAC9B;AAsBD,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAgB7E;AAED,wBAAsB,kBAAkB,CACvC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,cAAc,GAAE,uBAA4B,GAC1C,OAAO,CAAC,IAAI,CAAC,CAoBf"}
@@ -1,22 +1,4 @@
1
- /**
2
- * Built-in sharded SSG runner (coordinator).
3
- *
4
- * Vue SSR (`renderToString`) is CPU-bound and single-threaded, and a single
5
- * long-lived `blox-ssg` process also accumulates happy-dom/window/timer state
6
- * under bun — on large sites (thousands of pages) that leak eventually crashes
7
- * the process silently. Splitting the work across N short-lived child processes
8
- * (each rendering a disjoint `--shard=i/n` slice into the same `dist`) both
9
- * parallelizes the CPU-bound render AND keeps each process well under the leak
10
- * threshold.
11
- *
12
- * This module is the coordinator: it enumerates the route list once (optionally
13
- * via an external `--routes-cmd` for router-driven sites that don't use CMS page
14
- * discovery), then spawns the shards, divides the resolve-prefetch budget across
15
- * them, and merges each shard's llms part file into the final llms.txt.
16
- *
17
- * Activated by `--shards=<n|auto>` on the CLI. Without it, the CLI runs a single
18
- * in-process render exactly as before (full backward compat).
19
- */
1
+ import { BloxBuildRequestOptions } from './build-request';
20
2
  export interface ShardRunnerOptions {
21
3
  /** Number of shards, or 'auto' → min(cores, cap). */
22
4
  shards: number | 'auto';
@@ -26,6 +8,8 @@ export interface ShardRunnerOptions {
26
8
  apiBase: string;
27
9
  /** CMS website name (for the post-run llms merge). */
28
10
  websiteName: string;
11
+ /** Ephemeral build authority inherited by discovery and child shards. */
12
+ buildRequest?: BloxBuildRequestOptions;
29
13
  /** Extra paths already parsed from argv (router-driven sites, static routes). */
30
14
  extraPaths: string[];
31
15
  /** Other pass-through flags to forward verbatim to each shard (e.g. --exclude=…, --crawl). */
@@ -1 +1 @@
1
- {"version":3,"file":"shard-runner.d.ts","sourceRoot":"","sources":["../../src/ssg/shard-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAWH,MAAM,WAAW,kBAAkB;IAClC,qDAAqD;IACrD,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAA;IACZ,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAA;IACf,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAA;IACnB,iFAAiF;IACjF,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,8FAA8F;IAC9F,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CAClB;AA4ED;;GAEG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAgI1E"}
1
+ {"version":3,"file":"shard-runner.d.ts","sourceRoot":"","sources":["../../src/ssg/shard-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAI9D,MAAM,WAAW,kBAAkB;IAClC,qDAAqD;IACrD,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAA;IACZ,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAA;IACf,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAA;IACnB,yEAAyE;IACzE,YAAY,CAAC,EAAE,uBAAuB,CAAA;IACtC,iFAAiF;IACjF,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,8FAA8F;IAC9F,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CAClB;AA4ED;;GAEG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAoI1E"}
@@ -41,6 +41,7 @@ function env(name) {
41
41
  }
42
42
  function getBloxBuildRequestOptions(overrides = {}) {
43
43
  return {
44
+ websiteId: overrides.websiteId,
44
45
  token: overrides.token ?? env("BLOX_BUILD_TOKEN"),
45
46
  tokenHeader: overrides.tokenHeader ?? env("BLOX_BUILD_TOKEN_HEADER") ?? "Authorization",
46
47
  tokenScheme: overrides.tokenScheme ?? env("BLOX_BUILD_TOKEN_SCHEME") ?? "Bearer",
@@ -111,7 +112,7 @@ function expandLocalePaths(paths, defaultLocale, supportedLocales) {
111
112
  }
112
113
  async function fetchCmsSiteData(apiBase, websiteName, requestOptions = {}) {
113
114
  var _a, _b, _c;
114
- const websiteId = typeof process !== "undefined" ? (_b = (_a = process.env) == null ? void 0 : _a.BLOX_WEBSITE_ID) == null ? void 0 : _b.trim() : void 0;
115
+ const websiteId = requestOptions.websiteId ?? (typeof process !== "undefined" ? (_b = (_a = process.env) == null ? void 0 : _a.BLOX_WEBSITE_ID) == null ? void 0 : _b.trim() : void 0);
115
116
  if (websiteId) {
116
117
  const bundle = await bloxBuildJson(
117
118
  `${apiBase}/blox-build/websites/${websiteId}/published`,
@@ -134,9 +135,11 @@ async function fetchCmsSiteData(apiBase, websiteName, requestOptions = {}) {
134
135
  collections: extractCollectionRefs(bundle.pages)
135
136
  };
136
137
  }
137
- const sitesData = await bloxBuildJson(`${apiBase}/blox/websites`, {}, requestOptions);
138
- const sites = Array.isArray(sitesData) ? sitesData : sitesData.data ?? [];
139
- const site = sites.find((s) => s.name === websiteName);
138
+ const site = await bloxBuildJson(
139
+ `${apiBase}/blox/sites/${encodeURIComponent(websiteName)}`,
140
+ {},
141
+ requestOptions
142
+ );
140
143
  if ((site == null ? void 0 : site.id) == null || site.id === "") throw new Error(`Website "${websiteName}" not found at ${apiBase}`);
141
144
  const website = await bloxBuildJson(
142
145
  `${apiBase}/blox/websites/${site.id}`,
@@ -192,6 +195,7 @@ async function fetchCmsPrerenderPaths(apiBase, websiteName, requestOptions = {})
192
195
  }
193
196
  async function expandRoutes(apiBase, pages, requestOptions, locale) {
194
197
  const routes = [];
198
+ const grantedWebsiteId = requestOptions.websiteId;
195
199
  for (const page of pages) {
196
200
  const slug = page.slug ?? "/";
197
201
  if (page.status && page.status !== "published") continue;
@@ -201,12 +205,13 @@ async function expandRoutes(apiBase, pages, requestOptions, locale) {
201
205
  if (b.adapter === "datastore" && b.collection != null && b.collection !== "" && b.store != null && b.store !== "" && b.bind_by != null && b.bind_by !== "") {
202
206
  const q = b.filter ? `&q=${encodeURIComponent(b.filter)}` : "";
203
207
  const localeParam = locale ? `&locale=${encodeURIComponent(locale)}` : "";
208
+ const collectionPath = grantedWebsiteId ? `/blox-build/websites/${grantedWebsiteId}/collections/${b.store}/${b.collection}` : `/datastore/${b.store}/collections/${b.collection}`;
204
209
  const itemsData = await bloxBuildJson(
205
- `${apiBase}/datastore/${b.store}/collections/${b.collection}?limit=200${localeParam}${q}`,
210
+ `${apiBase}${collectionPath}?limit=200${localeParam}${q}`,
206
211
  {},
207
212
  requestOptions
208
213
  );
209
- const items = Array.isArray(itemsData) ? itemsData : itemsData.data ?? [];
214
+ const items = Array.isArray(itemsData) ? itemsData : itemsData.items ?? itemsData.data ?? [];
210
215
  for (const item of items) {
211
216
  const bindValue = item[b.bind_by];
212
217
  if (typeof bindValue !== "string" || bindValue === "") continue;
@@ -272,9 +277,9 @@ async function resolveManifestProvenance() {
272
277
  commit
273
278
  };
274
279
  }
275
- async function uploadBloxManifest(apiBase, websiteId) {
276
- if (!environment("BLOX_BUILD_TOKEN")) {
277
- throw new Error("BLOX_BUILD_TOKEN is required to upload the Blox manifest");
280
+ async function uploadBloxManifest(apiBase, websiteId, requestOptions = {}) {
281
+ if (!requestOptions.token && !environment("BLOX_BUILD_TOKEN")) {
282
+ throw new Error("A Blox build grant is required to upload the Blox manifest");
278
283
  }
279
284
  const distDirectory = path.resolve(process$1.cwd(), "dist");
280
285
  const resolvedManifestPath = path.resolve(distDirectory, ".blox-manifest.json");
@@ -289,7 +294,8 @@ async function uploadBloxManifest(apiBase, websiteId) {
289
294
  method: "PUT",
290
295
  headers: { "Content-Type": "application/json" },
291
296
  body: JSON.stringify(payload)
292
- }
297
+ },
298
+ requestOptions
293
299
  );
294
300
  }
295
301
  async function polyfillBloxSsgGlobals(options) {
@@ -18,6 +18,7 @@ function env(name) {
18
18
  }
19
19
  function getBloxBuildRequestOptions(overrides = {}) {
20
20
  return {
21
+ websiteId: overrides.websiteId,
21
22
  token: overrides.token ?? env("BLOX_BUILD_TOKEN"),
22
23
  tokenHeader: overrides.tokenHeader ?? env("BLOX_BUILD_TOKEN_HEADER") ?? "Authorization",
23
24
  tokenScheme: overrides.tokenScheme ?? env("BLOX_BUILD_TOKEN_SCHEME") ?? "Bearer",
@@ -88,7 +89,7 @@ function expandLocalePaths(paths, defaultLocale, supportedLocales) {
88
89
  }
89
90
  async function fetchCmsSiteData(apiBase, websiteName, requestOptions = {}) {
90
91
  var _a, _b, _c;
91
- const websiteId = typeof process !== "undefined" ? (_b = (_a = process.env) == null ? void 0 : _a.BLOX_WEBSITE_ID) == null ? void 0 : _b.trim() : void 0;
92
+ const websiteId = requestOptions.websiteId ?? (typeof process !== "undefined" ? (_b = (_a = process.env) == null ? void 0 : _a.BLOX_WEBSITE_ID) == null ? void 0 : _b.trim() : void 0);
92
93
  if (websiteId) {
93
94
  const bundle = await bloxBuildJson(
94
95
  `${apiBase}/blox-build/websites/${websiteId}/published`,
@@ -111,9 +112,11 @@ async function fetchCmsSiteData(apiBase, websiteName, requestOptions = {}) {
111
112
  collections: extractCollectionRefs(bundle.pages)
112
113
  };
113
114
  }
114
- const sitesData = await bloxBuildJson(`${apiBase}/blox/websites`, {}, requestOptions);
115
- const sites = Array.isArray(sitesData) ? sitesData : sitesData.data ?? [];
116
- const site = sites.find((s) => s.name === websiteName);
115
+ const site = await bloxBuildJson(
116
+ `${apiBase}/blox/sites/${encodeURIComponent(websiteName)}`,
117
+ {},
118
+ requestOptions
119
+ );
117
120
  if ((site == null ? void 0 : site.id) == null || site.id === "") throw new Error(`Website "${websiteName}" not found at ${apiBase}`);
118
121
  const website = await bloxBuildJson(
119
122
  `${apiBase}/blox/websites/${site.id}`,
@@ -169,6 +172,7 @@ async function fetchCmsPrerenderPaths(apiBase, websiteName, requestOptions = {})
169
172
  }
170
173
  async function expandRoutes(apiBase, pages, requestOptions, locale) {
171
174
  const routes = [];
175
+ const grantedWebsiteId = requestOptions.websiteId;
172
176
  for (const page of pages) {
173
177
  const slug = page.slug ?? "/";
174
178
  if (page.status && page.status !== "published") continue;
@@ -178,12 +182,13 @@ async function expandRoutes(apiBase, pages, requestOptions, locale) {
178
182
  if (b.adapter === "datastore" && b.collection != null && b.collection !== "" && b.store != null && b.store !== "" && b.bind_by != null && b.bind_by !== "") {
179
183
  const q = b.filter ? `&q=${encodeURIComponent(b.filter)}` : "";
180
184
  const localeParam = locale ? `&locale=${encodeURIComponent(locale)}` : "";
185
+ const collectionPath = grantedWebsiteId ? `/blox-build/websites/${grantedWebsiteId}/collections/${b.store}/${b.collection}` : `/datastore/${b.store}/collections/${b.collection}`;
181
186
  const itemsData = await bloxBuildJson(
182
- `${apiBase}/datastore/${b.store}/collections/${b.collection}?limit=200${localeParam}${q}`,
187
+ `${apiBase}${collectionPath}?limit=200${localeParam}${q}`,
183
188
  {},
184
189
  requestOptions
185
190
  );
186
- const items = Array.isArray(itemsData) ? itemsData : itemsData.data ?? [];
191
+ const items = Array.isArray(itemsData) ? itemsData : itemsData.items ?? itemsData.data ?? [];
187
192
  for (const item of items) {
188
193
  const bindValue = item[b.bind_by];
189
194
  if (typeof bindValue !== "string" || bindValue === "") continue;
@@ -249,9 +254,9 @@ async function resolveManifestProvenance() {
249
254
  commit
250
255
  };
251
256
  }
252
- async function uploadBloxManifest(apiBase, websiteId) {
253
- if (!environment("BLOX_BUILD_TOKEN")) {
254
- throw new Error("BLOX_BUILD_TOKEN is required to upload the Blox manifest");
257
+ async function uploadBloxManifest(apiBase, websiteId, requestOptions = {}) {
258
+ if (!requestOptions.token && !environment("BLOX_BUILD_TOKEN")) {
259
+ throw new Error("A Blox build grant is required to upload the Blox manifest");
255
260
  }
256
261
  const distDirectory = resolve(process$1.cwd(), "dist");
257
262
  const resolvedManifestPath = resolve(distDirectory, ".blox-manifest.json");
@@ -266,7 +271,8 @@ async function uploadBloxManifest(apiBase, websiteId) {
266
271
  method: "PUT",
267
272
  headers: { "Content-Type": "application/json" },
268
273
  body: JSON.stringify(payload)
269
- }
274
+ },
275
+ requestOptions
270
276
  );
271
277
  }
272
278
  async function polyfillBloxSsgGlobals(options) {
@@ -176,6 +176,7 @@ function bloxPlugin(options = {}) {
176
176
  let outDir = "dist";
177
177
  let isSsrBuild = false;
178
178
  let vuePlugin;
179
+ let resolvedAliases;
179
180
  plugins.push({
180
181
  name: "vite-plugin-blox-manifest",
181
182
  apply: "build",
@@ -184,6 +185,7 @@ function bloxPlugin(options = {}) {
184
185
  outDir = resolved.build.outDir;
185
186
  isSsrBuild = !!resolved.build.ssr;
186
187
  vuePlugin = resolved.plugins.find((plugin) => plugin.name === "vite:vue");
188
+ resolvedAliases = resolved.resolve.alias;
187
189
  },
188
190
  resolveId(id) {
189
191
  if (id === VIRTUAL_ENTRY) return RESOLVED_ENTRY;
@@ -212,6 +214,7 @@ function bloxPlugin(options = {}) {
212
214
  configFile: false,
213
215
  logLevel: "silent",
214
216
  server: { middlewareMode: true, hmr: false },
217
+ resolve: { alias: resolvedAliases },
215
218
  plugins: [
216
219
  {
217
220
  name: "vite-plugin-blox-manifest-entry",
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,MAAM,CAAA;AAM9C,MAAM,WAAW,iBAAiB;IACjC;;;;;OAKG;IACH,GAAG,CAAC,EAAE,OAAO,CAAA;IACb;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,GAAG,MAAM,EAAE,CAogBpE"}
1
+ {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,MAAM,CAAA;AAM9C,MAAM,WAAW,iBAAiB;IACjC;;;;;OAKG;IACH,GAAG,CAAC,EAAE,OAAO,CAAA;IACb;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,GAAG,MAAM,EAAE,CAugBpE"}
@@ -152,6 +152,7 @@ function bloxPlugin(options = {}) {
152
152
  let outDir = "dist";
153
153
  let isSsrBuild = false;
154
154
  let vuePlugin;
155
+ let resolvedAliases;
155
156
  plugins.push({
156
157
  name: "vite-plugin-blox-manifest",
157
158
  apply: "build",
@@ -160,6 +161,7 @@ function bloxPlugin(options = {}) {
160
161
  outDir = resolved.build.outDir;
161
162
  isSsrBuild = !!resolved.build.ssr;
162
163
  vuePlugin = resolved.plugins.find((plugin) => plugin.name === "vite:vue");
164
+ resolvedAliases = resolved.resolve.alias;
163
165
  },
164
166
  resolveId(id) {
165
167
  if (id === VIRTUAL_ENTRY) return RESOLVED_ENTRY;
@@ -188,6 +190,7 @@ function bloxPlugin(options = {}) {
188
190
  configFile: false,
189
191
  logLevel: "silent",
190
192
  server: { middlewareMode: true, hmr: false },
193
+ resolve: { alias: resolvedAliases },
191
194
  plugins: [
192
195
  {
193
196
  name: "vite-plugin-blox-manifest-entry",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/blox",
3
3
  "type": "module",
4
- "version": "1.15.535",
4
+ "version": "1.15.543",
5
5
  "description": "Blox page builder library for drag-and-drop page building and static data management",
6
6
  "author": {
7
7
  "name": "Bagel Studio",
@@ -53,6 +53,10 @@
53
53
  "types": "./dist/ssg/client.d.ts",
54
54
  "import": "./dist/ssg/client.mjs"
55
55
  },
56
+ "./ssg/build-grant": {
57
+ "types": "./dist/ssg/build-grant.d.ts",
58
+ "import": "./dist/ssg/build-grant.mjs"
59
+ },
56
60
  "./style.css": "./dist/style.css",
57
61
  "./dist/style.css": "./dist/style.css"
58
62
  },