@bagelink/blox 1.15.539 → 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-DqDUmsyO.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) {
@@ -137,7 +137,7 @@ async function runSharded(opts) {
137
137
  }
138
138
  if (process.env.BLOX_SSG_LLM !== "0") {
139
139
  try {
140
- const { mergeLlmParts } = await Promise.resolve().then(() => require("./validate-output-DqDUmsyO.cjs")).then((n) => n.llmArtifacts);
140
+ const { mergeLlmParts } = await Promise.resolve().then(() => require("./validate-output-Dku8tCir.cjs")).then((n) => n.llmArtifacts);
141
141
  const mergeWebsite = website;
142
142
  const partFiles = Array.from({ length: total }, (_, i) => path.join(llmPartsDir, `part.${i}.json`));
143
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-CV4nlrHm.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) {
@@ -113,7 +113,7 @@ async function runSharded(opts) {
113
113
  }
114
114
  if (process.env.BLOX_SSG_LLM !== "0") {
115
115
  try {
116
- const { mergeLlmParts } = await import("./validate-output-CV4nlrHm.js").then((n) => n.D);
116
+ const { mergeLlmParts } = await import("./validate-output-XdxaXjgE.js").then((n) => n.A);
117
117
  const mergeWebsite = website;
118
118
  const partFiles = Array.from({ length: total }, (_, i) => path.join(llmPartsDir, `part.${i}.json`));
119
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,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
+ };
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-DqDUmsyO.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,7 +132,7 @@ Environment:
131
132
  console.log(`[blox-ssg] validated output in ${validateOutDir}`);
132
133
  return;
133
134
  }
134
- const buildGrant = llmArtifacts.resolveBloxBuildGrant({ mode });
135
+ const buildGrant = ssg_buildGrant.resolveBloxBuildGrant({ mode });
135
136
  if (buildGrant) {
136
137
  process.env.BLOX_WEBSITE_ID = buildGrant.websiteId;
137
138
  process.env.BLOX_BUILD_TOKEN = buildGrant.grant;
@@ -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 Promise.resolve().then(() => require("../shard-runner-D778xfd2.cjs"));
144
+ const { runSharded } = await Promise.resolve().then(() => require("../shard-runner-DOK26Y78.cjs"));
144
145
  const code = await runSharded({
145
146
  shards: shardsOpt ?? "auto",
146
147
  mode,
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, r as resolveBloxBuildGrant, u as uploadBloxManifest, p as polyfillBloxSsgGlobals, f as fetchCmsSiteData, a as prerender } from "../validate-output-CV4nlrHm.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;
@@ -139,7 +140,7 @@ Environment:
139
140
  if (shardsOpt !== null || routesCmd) {
140
141
  const { apiBase: apiBase2, websiteName: configWebsiteName2 } = await resolveApiBase(mode);
141
142
  const websiteName2 = process.env.WEBSITE_NAME ?? configWebsiteName2 ?? "default";
142
- const { runSharded } = await import("../shard-runner-BWwEIABX.js");
143
+ const { runSharded } = await import("../shard-runner-Ic_t76Xj.js");
143
144
  const code = await runSharded({
144
145
  shards: shardsOpt ?? "auto",
145
146
  mode,
@@ -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,CAuNnF"}
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-DqDUmsyO.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 {
@@ -172,9 +185,12 @@ function createBloxSSREntry(options) {
172
185
  publishedBundleCache.set(cacheKey, pending);
173
186
  }
174
187
  const bundle = await pending;
175
- const page = bundle.pages.find((candidate) => candidate.slug === slug);
176
- if (!page) return null;
177
- return { page, contexts: {}, warnings: [] };
188
+ const page = matchPublishedPage(
189
+ bundle.pages,
190
+ slug,
191
+ options.resolvePublishedPaths
192
+ );
193
+ return page ? { page, contexts: {}, warnings: [] } : null;
178
194
  }
179
195
  const url = `${apiBase}/blox/websites/${websiteId}/resolve-path?path=${encodeURIComponent(slug)}&locale=${pageLocale}`;
180
196
  return llmArtifacts.bloxBuildJson(url, {}, options.buildRequest);
@@ -352,14 +368,14 @@ exports.getBloxBuildRequestOptions = llmArtifacts.getBloxBuildRequestOptions;
352
368
  exports.getSiteIconFlags = llmArtifacts.getSiteIconFlags;
353
369
  exports.localeSitemapPath = llmArtifacts.localeSitemapPath;
354
370
  exports.mergeLlmParts = llmArtifacts.mergeLlmParts;
355
- exports.parseBloxBuildGrantBody = llmArtifacts.parseBloxBuildGrantBody;
356
371
  exports.polyfillBloxSsgGlobals = llmArtifacts.polyfillBloxSsgGlobals;
357
372
  exports.prerender = llmArtifacts.prerender;
358
- exports.resolveBloxBuildGrant = llmArtifacts.resolveBloxBuildGrant;
359
373
  exports.resolveManifestProvenance = llmArtifacts.resolveManifestProvenance;
360
374
  exports.splitSitemapPathsByLocale = llmArtifacts.splitSitemapPathsByLocale;
361
375
  exports.uploadBloxManifest = llmArtifacts.uploadBloxManifest;
362
376
  exports.validateSsgOutput = llmArtifacts.validateSsgOutput;
377
+ exports.parseBloxBuildGrantBody = ssg_buildGrant.parseBloxBuildGrantBody;
378
+ exports.resolveBloxBuildGrant = ssg_buildGrant.resolveBloxBuildGrant;
363
379
  exports.BLOX_COLLECTIONS_WINDOW_KEY = ssg_client.BLOX_COLLECTIONS_WINDOW_KEY;
364
380
  exports.BLOX_DATA_WINDOW_KEY = ssg_client.BLOX_DATA_WINDOW_KEY;
365
381
  exports.BLOX_PAGE_SEO_WINDOW_KEY = ssg_client.BLOX_PAGE_SEO_WINDOW_KEY;
@@ -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-CV4nlrHm.js";
2
- import { i, j, k, f, l, m, n, o, g, q, s, t, w, x, y, z, p, a, r, A, C, u, v } from "../validate-output-CV4nlrHm.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 {
@@ -150,9 +163,12 @@ function createBloxSSREntry(options) {
150
163
  publishedBundleCache.set(cacheKey, pending);
151
164
  }
152
165
  const bundle = await pending;
153
- const page = bundle.pages.find((candidate) => candidate.slug === slug);
154
- if (!page) return null;
155
- return { page, contexts: {}, warnings: [] };
166
+ const page = matchPublishedPage(
167
+ bundle.pages,
168
+ slug,
169
+ options.resolvePublishedPaths
170
+ );
171
+ return page ? { page, contexts: {}, warnings: [] } : null;
156
172
  }
157
173
  const url = `${apiBase}/blox/websites/${websiteId}/resolve-path?path=${encodeURIComponent(slug)}&locale=${pageLocale}`;
158
174
  return bloxBuildJson(url, {}, options.buildRequest);
@@ -333,24 +349,24 @@ export {
333
349
  o as generateRobotsTxt,
334
350
  g as generateSitemapArtifacts,
335
351
  q as generateSitemapIndexXml,
336
- s as generateSitemapXml,
337
- t as getBloxBuildRequestOptions,
352
+ r as generateSitemapXml,
353
+ s as getBloxBuildRequestOptions,
338
354
  getCollectionCache,
339
355
  getEmbeddedWebsiteId,
340
- w as getSiteIconFlags,
356
+ t as getSiteIconFlags,
341
357
  installBloxStateCache,
342
358
  installCollectionCache,
343
- x as localeSitemapPath,
344
- y as mergeLlmParts,
345
- z as parseBloxBuildGrantBody,
359
+ w as localeSitemapPath,
360
+ x as mergeLlmParts,
361
+ parseBloxBuildGrantBody,
346
362
  p as polyfillBloxSsgGlobals,
347
363
  a as prerender,
348
364
  querySnapshotRows,
349
365
  renderBloxSsgPage,
350
- r as resolveBloxBuildGrant,
351
- A as resolveManifestProvenance,
366
+ resolveBloxBuildGrant,
367
+ y as resolveManifestProvenance,
352
368
  snapshotRows,
353
- C as splitSitemapPathsByLocale,
369
+ z as splitSitemapPathsByLocale,
354
370
  u as uploadBloxManifest,
355
371
  v as validateSsgOutput
356
372
  };
@@ -21,81 +21,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
21
21
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
22
  mod
23
23
  ));
24
- const process$1 = require("node:process");
25
24
  const node_child_process = require("node:child_process");
26
25
  const fs = require("node:fs/promises");
27
26
  const path = require("node:path");
27
+ const process$1 = require("node:process");
28
28
  const node_url = require("node:url");
29
29
  const pageTitle = require("./pageTitle-nIl1cDfD.cjs");
30
- 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;
31
- const PAYLOAD_FIELDS = /* @__PURE__ */ new Set(["version", "source", "website_id", "grant"]);
32
- function parseJsonObject(value) {
33
- let parsed;
34
- try {
35
- parsed = JSON.parse(value);
36
- } catch {
37
- throw new Error("Invalid Blox build hook payload");
38
- }
39
- if (parsed === null || Array.isArray(parsed) || typeof parsed !== "object") {
40
- throw new Error("Invalid Blox build hook payload");
41
- }
42
- return parsed;
43
- }
44
- function parseBloxBuildGrantBody(body) {
45
- const trimmed = body.trim();
46
- if (!trimmed) throw new Error("Missing Blox build hook payload");
47
- let payload;
48
- try {
49
- payload = parseJsonObject(trimmed);
50
- } catch {
51
- let decoded;
52
- try {
53
- decoded = decodeURIComponent(trimmed);
54
- } catch {
55
- throw new Error("Invalid Blox build hook payload");
56
- }
57
- payload = parseJsonObject(decoded);
58
- }
59
- if (Object.keys(payload).some((field) => !PAYLOAD_FIELDS.has(field))) {
60
- throw new Error("Invalid Blox build hook payload fields");
61
- }
62
- 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() === "") {
63
- throw new Error("Invalid Blox build hook payload");
64
- }
65
- return {
66
- version: 1,
67
- source: "blox",
68
- websiteId: payload.website_id,
69
- grant: payload.grant
70
- };
71
- }
72
- function isLocalOrTest(mode, env2) {
73
- return mode === "localhost" || mode === "development" || mode === "test" || env2.NODE_ENV === "development" || env2.NODE_ENV === "test";
74
- }
75
- function resolveBloxBuildGrant(options = {}) {
76
- var _a, _b, _c, _d, _e;
77
- const env2 = options.env ?? process$1.env;
78
- if (isLocalOrTest(options.mode, env2)) {
79
- const websiteId = (_a = env2.BLOX_WEBSITE_ID) == null ? void 0 : _a.trim();
80
- const grant2 = (_b = env2.BLOX_BUILD_TOKEN) == null ? void 0 : _b.trim();
81
- if (!websiteId && !grant2) return void 0;
82
- if (!websiteId || !UUID_PATTERN.test(websiteId) || !grant2) {
83
- throw new Error("Local Blox build overrides require a valid BLOX_WEBSITE_ID and BLOX_BUILD_TOKEN");
84
- }
85
- return { version: 1, source: "blox", websiteId, grant: grant2 };
86
- }
87
- if (!((_c = env2.INCOMING_HOOK_URL) == null ? void 0 : _c.trim()) || !((_d = env2.INCOMING_HOOK_TITLE) == null ? void 0 : _d.trim())) {
88
- throw new Error("Blox production builds require Netlify incoming hook metadata");
89
- }
90
- const body = env2.INCOMING_HOOK_BODY;
91
- if (body == null) throw new Error("Blox production builds require a hook payload");
92
- const grant = parseBloxBuildGrantBody(body);
93
- const configuredWebsiteId = (_e = env2.BLOX_WEBSITE_ID) == null ? void 0 : _e.trim();
94
- if (configuredWebsiteId && configuredWebsiteId !== grant.websiteId) {
95
- throw new Error("Blox build hook website does not match the configured website");
96
- }
97
- return grant;
98
- }
99
30
  class BloxBuildResponseError extends Error {
100
31
  constructor(status, url, statusText) {
101
32
  super(`Build API ${status} ${statusText}: ${url}`);
@@ -1405,11 +1336,9 @@ exports.getSiteIconFlags = getSiteIconFlags;
1405
1336
  exports.llmArtifacts = llmArtifacts;
1406
1337
  exports.localeSitemapPath = localeSitemapPath;
1407
1338
  exports.mergeLlmParts = mergeLlmParts;
1408
- exports.parseBloxBuildGrantBody = parseBloxBuildGrantBody;
1409
1339
  exports.polyfillBloxSsgGlobals = polyfillBloxSsgGlobals;
1410
1340
  exports.prerender = prerender;
1411
1341
  exports.primaryContextEntry = primaryContextEntry;
1412
- exports.resolveBloxBuildGrant = resolveBloxBuildGrant;
1413
1342
  exports.resolveManifestProvenance = resolveManifestProvenance;
1414
1343
  exports.splitSitemapPathsByLocale = splitSitemapPathsByLocale;
1415
1344
  exports.uploadBloxManifest = uploadBloxManifest;
@@ -1,78 +1,9 @@
1
- import process$1 from "node:process";
2
1
  import { execFile } from "node:child_process";
3
2
  import fs, { readFile } from "node:fs/promises";
4
3
  import path, { resolve } from "node:path";
4
+ import process$1 from "node:process";
5
5
  import { pathToFileURL } from "node:url";
6
6
  import { r as resolvePageTitle, p as primaryPageContext, c as contextPageTitle } from "./pageTitle-BOTMH-D8.js";
7
- 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;
8
- const PAYLOAD_FIELDS = /* @__PURE__ */ new Set(["version", "source", "website_id", "grant"]);
9
- function parseJsonObject(value) {
10
- let parsed;
11
- try {
12
- parsed = JSON.parse(value);
13
- } catch {
14
- throw new Error("Invalid Blox build hook payload");
15
- }
16
- if (parsed === null || Array.isArray(parsed) || typeof parsed !== "object") {
17
- throw new Error("Invalid Blox build hook payload");
18
- }
19
- return parsed;
20
- }
21
- function parseBloxBuildGrantBody(body) {
22
- const trimmed = body.trim();
23
- if (!trimmed) throw new Error("Missing Blox build hook payload");
24
- let payload;
25
- try {
26
- payload = parseJsonObject(trimmed);
27
- } catch {
28
- let decoded;
29
- try {
30
- decoded = decodeURIComponent(trimmed);
31
- } catch {
32
- throw new Error("Invalid Blox build hook payload");
33
- }
34
- payload = parseJsonObject(decoded);
35
- }
36
- if (Object.keys(payload).some((field) => !PAYLOAD_FIELDS.has(field))) {
37
- throw new Error("Invalid Blox build hook payload fields");
38
- }
39
- 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() === "") {
40
- throw new Error("Invalid Blox build hook payload");
41
- }
42
- return {
43
- version: 1,
44
- source: "blox",
45
- websiteId: payload.website_id,
46
- grant: payload.grant
47
- };
48
- }
49
- function isLocalOrTest(mode, env2) {
50
- return mode === "localhost" || mode === "development" || mode === "test" || env2.NODE_ENV === "development" || env2.NODE_ENV === "test";
51
- }
52
- function resolveBloxBuildGrant(options = {}) {
53
- var _a, _b, _c, _d, _e;
54
- const env2 = options.env ?? process$1.env;
55
- if (isLocalOrTest(options.mode, env2)) {
56
- const websiteId = (_a = env2.BLOX_WEBSITE_ID) == null ? void 0 : _a.trim();
57
- const grant2 = (_b = env2.BLOX_BUILD_TOKEN) == null ? void 0 : _b.trim();
58
- if (!websiteId && !grant2) return void 0;
59
- if (!websiteId || !UUID_PATTERN.test(websiteId) || !grant2) {
60
- throw new Error("Local Blox build overrides require a valid BLOX_WEBSITE_ID and BLOX_BUILD_TOKEN");
61
- }
62
- return { version: 1, source: "blox", websiteId, grant: grant2 };
63
- }
64
- if (!((_c = env2.INCOMING_HOOK_URL) == null ? void 0 : _c.trim()) || !((_d = env2.INCOMING_HOOK_TITLE) == null ? void 0 : _d.trim())) {
65
- throw new Error("Blox production builds require Netlify incoming hook metadata");
66
- }
67
- const body = env2.INCOMING_HOOK_BODY;
68
- if (body == null) throw new Error("Blox production builds require a hook payload");
69
- const grant = parseBloxBuildGrantBody(body);
70
- const configuredWebsiteId = (_e = env2.BLOX_WEBSITE_ID) == null ? void 0 : _e.trim();
71
- if (configuredWebsiteId && configuredWebsiteId !== grant.websiteId) {
72
- throw new Error("Blox build hook website does not match the configured website");
73
- }
74
- return grant;
75
- }
76
7
  class BloxBuildResponseError extends Error {
77
8
  constructor(status, url, statusText) {
78
9
  super(`Build API ${status} ${statusText}: ${url}`);
@@ -1362,10 +1293,8 @@ async function validateSitemap(outDir, content) {
1362
1293
  return failures;
1363
1294
  }
1364
1295
  export {
1365
- resolveManifestProvenance as A,
1296
+ llmArtifacts as A,
1366
1297
  BloxBuildResponseError as B,
1367
- splitSitemapPathsByLocale as C,
1368
- llmArtifacts as D,
1369
1298
  prerender as a,
1370
1299
  buildPageHead as b,
1371
1300
  primaryContextEntry as c,
@@ -1383,13 +1312,13 @@ export {
1383
1312
  generateRobotsTxt as o,
1384
1313
  polyfillBloxSsgGlobals as p,
1385
1314
  generateSitemapIndexXml as q,
1386
- resolveBloxBuildGrant as r,
1387
- generateSitemapXml as s,
1388
- getBloxBuildRequestOptions as t,
1315
+ generateSitemapXml as r,
1316
+ getBloxBuildRequestOptions as s,
1317
+ getSiteIconFlags as t,
1389
1318
  uploadBloxManifest as u,
1390
1319
  validateSsgOutput as v,
1391
- getSiteIconFlags as w,
1392
- localeSitemapPath as x,
1393
- mergeLlmParts as y,
1394
- parseBloxBuildGrantBody as z
1320
+ localeSitemapPath as w,
1321
+ mergeLlmParts as x,
1322
+ resolveManifestProvenance as y,
1323
+ splitSitemapPathsByLocale as z
1395
1324
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/blox",
3
3
  "type": "module",
4
- "version": "1.15.539",
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
  },