@riverbankcms/sdk 0.7.4 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -1
- package/dist/cli/index.js +3693 -39
- package/dist/cli/index.js.map +1 -1
- package/dist/client/client.d.mts +2 -2
- package/dist/client/client.d.ts +2 -2
- package/dist/client/client.js +167 -4
- package/dist/client/client.js.map +1 -1
- package/dist/client/client.mjs +167 -4
- package/dist/client/client.mjs.map +1 -1
- package/dist/client/hooks.d.mts +2 -2
- package/dist/client/hooks.d.ts +2 -2
- package/dist/client/usePage-CdnO2CP5.d.mts +6875 -0
- package/dist/client/usePage-_ksKXlUF.d.ts +6875 -0
- package/dist/server/{Layout-qWLdVm5-.d.mts → Layout-D4J009eS.d.mts} +1 -1
- package/dist/server/{Layout-Yluyb6sK.d.ts → Layout-l2v4Qa6E.d.ts} +1 -1
- package/dist/server/{chunk-74XUVNOO.mjs → chunk-4YQJUL5W.mjs} +4 -2
- package/dist/server/{chunk-74XUVNOO.mjs.map → chunk-4YQJUL5W.mjs.map} +1 -1
- package/dist/server/{chunk-JNU7ZS2V.mjs → chunk-65A5HAUZ.mjs} +168 -5
- package/dist/server/chunk-65A5HAUZ.mjs.map +1 -0
- package/dist/server/{chunk-JWRNMNWI.js → chunk-EIJ27EZQ.js} +4 -2
- package/dist/server/chunk-EIJ27EZQ.js.map +1 -0
- package/dist/server/{chunk-6Z4MQG47.js → chunk-WM646WI3.js} +168 -5
- package/dist/server/chunk-WM646WI3.js.map +1 -0
- package/dist/server/{components-Di5ME6He.d.ts → components-D2uCKCj7.d.ts} +3 -3
- package/dist/server/{components-DNHfSCML.d.mts → components-vtYEmmPF.d.mts} +3 -3
- package/dist/server/components.d.mts +5 -5
- package/dist/server/components.d.ts +5 -5
- package/dist/server/config-validation.d.mts +2 -2
- package/dist/server/config-validation.d.ts +2 -2
- package/dist/server/config.d.mts +3 -3
- package/dist/server/config.d.ts +3 -3
- package/dist/server/data.d.mts +2 -2
- package/dist/server/data.d.ts +2 -2
- package/dist/server/{index-Clm3skz_.d.mts → index-2qnY7VH_.d.mts} +1 -1
- package/dist/server/{index-DLvNddi-.d.ts → index-BxrAuL9K.d.ts} +1 -1
- package/dist/server/{index-C9Ra8dza.d.ts → index-CH_dvF6n.d.ts} +2 -2
- package/dist/server/{index--Oyunk_B.d.mts → index-DfWg1Qle.d.mts} +2 -2
- package/dist/server/index.d.mts +13 -5
- package/dist/server/index.d.ts +13 -5
- package/dist/server/index.js +10 -10
- package/dist/server/index.mjs +1 -1
- package/dist/server/{loadContent-D7LQwI0o.d.ts → loadContent-DECnsp4k.d.ts} +3 -3
- package/dist/server/{loadContent-DVfuBLiZ.d.mts → loadContent-Du5kS8UM.d.mts} +3 -3
- package/dist/server/{loadPage-BmYJCe_V.d.ts → loadPage-BZohBxxf.d.ts} +2 -2
- package/dist/server/{loadPage-BucnLHmE.d.mts → loadPage-VBorKlWv.d.mts} +2 -2
- package/dist/server/metadata.d.mts +4 -4
- package/dist/server/metadata.d.ts +4 -4
- package/dist/server/navigation.d.mts +2 -2
- package/dist/server/navigation.d.ts +2 -2
- package/dist/server/next.d.mts +38 -7
- package/dist/server/next.d.ts +38 -7
- package/dist/server/next.js +35 -17
- package/dist/server/next.js.map +1 -1
- package/dist/server/next.mjs +30 -12
- package/dist/server/next.mjs.map +1 -1
- package/dist/server/rendering/server.d.mts +4 -4
- package/dist/server/rendering/server.d.ts +4 -4
- package/dist/server/rendering.d.mts +7 -7
- package/dist/server/rendering.d.ts +7 -7
- package/dist/server/rendering.js +2 -2
- package/dist/server/rendering.mjs +1 -1
- package/dist/server/routing.d.mts +4 -4
- package/dist/server/routing.d.ts +4 -4
- package/dist/server/server.d.mts +5 -5
- package/dist/server/server.d.ts +5 -5
- package/dist/server/server.js +3 -3
- package/dist/server/server.mjs +2 -2
- package/dist/server/{types-C-LShyIg.d.mts → types-BRQ_6yOc.d.mts} +43 -1
- package/dist/server/{types-BjgZt8xJ.d.mts → types-CJfJwcuL.d.mts} +37 -0
- package/dist/server/{types-Dt98DeYa.d.ts → types-CgSO0yxg.d.ts} +8 -0
- package/dist/server/{types-BRQyLrQU.d.ts → types-D0rPF8l5.d.ts} +43 -1
- package/dist/server/{types-DLBhEPSt.d.ts → types-D8XqwoVd.d.ts} +37 -0
- package/dist/server/{types-BSV6Vc-P.d.mts → types-DT30Qy7x.d.mts} +8 -0
- package/dist/server/{validation-DU2YE7u5.d.ts → validation-D1LaY1kQ.d.ts} +1 -1
- package/dist/server/{validation-BGuRo8P1.d.mts → validation-Pv3Zs6dP.d.mts} +1 -1
- package/package.json +2 -1
- package/dist/server/chunk-6Z4MQG47.js.map +0 -1
- package/dist/server/chunk-JNU7ZS2V.mjs.map +0 -1
- package/dist/server/chunk-JWRNMNWI.js.map +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
var jiti = require('jiti');
|
|
5
5
|
var path9 = require('path');
|
|
6
|
-
var
|
|
6
|
+
var fs6 = require('fs');
|
|
7
7
|
var dotenv = require('dotenv');
|
|
8
8
|
var commander = require('commander');
|
|
9
9
|
var zod = require('zod');
|
|
@@ -13,6 +13,10 @@ var readline = require('readline');
|
|
|
13
13
|
var equal = require('fast-deep-equal');
|
|
14
14
|
var os = require('os');
|
|
15
15
|
var child_process = require('child_process');
|
|
16
|
+
var simpleGit = require('simple-git');
|
|
17
|
+
require('react');
|
|
18
|
+
require('react/jsx-runtime');
|
|
19
|
+
var crypto2 = require('crypto');
|
|
16
20
|
|
|
17
21
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
18
22
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -36,14 +40,19 @@ function _interopNamespace(e) {
|
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
var path9__namespace = /*#__PURE__*/_interopNamespace(path9);
|
|
43
|
+
var fs6__namespace = /*#__PURE__*/_interopNamespace(fs6);
|
|
39
44
|
var prompts__default = /*#__PURE__*/_interopDefault(prompts);
|
|
40
45
|
var fs3__namespace = /*#__PURE__*/_interopNamespace(fs3);
|
|
41
46
|
var readline__namespace = /*#__PURE__*/_interopNamespace(readline);
|
|
42
47
|
var equal__default = /*#__PURE__*/_interopDefault(equal);
|
|
43
48
|
var os__namespace = /*#__PURE__*/_interopNamespace(os);
|
|
49
|
+
var simpleGit__default = /*#__PURE__*/_interopDefault(simpleGit);
|
|
50
|
+
var crypto2__namespace = /*#__PURE__*/_interopNamespace(crypto2);
|
|
44
51
|
|
|
45
52
|
var __defProp = Object.defineProperty;
|
|
53
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
46
54
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
55
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
47
56
|
var __esm = (fn, res) => function __init() {
|
|
48
57
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
49
58
|
};
|
|
@@ -51,6 +60,15 @@ var __export = (target, all) => {
|
|
|
51
60
|
for (var name in all)
|
|
52
61
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
53
62
|
};
|
|
63
|
+
var __copyProps = (to, from, except, desc) => {
|
|
64
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
65
|
+
for (let key of __getOwnPropNames(from))
|
|
66
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
67
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
68
|
+
}
|
|
69
|
+
return to;
|
|
70
|
+
};
|
|
71
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
54
72
|
|
|
55
73
|
// src/cli/load-config.ts
|
|
56
74
|
var load_config_exports = {};
|
|
@@ -59,7 +77,7 @@ __export(load_config_exports, {
|
|
|
59
77
|
});
|
|
60
78
|
async function loadConfigFile(configPath) {
|
|
61
79
|
const resolvedPath = resolveConfigPath(configPath);
|
|
62
|
-
if (!
|
|
80
|
+
if (!fs6.existsSync(resolvedPath)) {
|
|
63
81
|
throw new Error(
|
|
64
82
|
`Config file not found: ${resolvedPath}
|
|
65
83
|
Create a riverbank.config.ts file or specify a path with --config`
|
|
@@ -90,7 +108,7 @@ function resolveConfigPath(configPath) {
|
|
|
90
108
|
return path9.resolve(process.cwd(), DEFAULT_CONFIG_FILENAME);
|
|
91
109
|
}
|
|
92
110
|
const resolved = path9.resolve(configPath);
|
|
93
|
-
if (
|
|
111
|
+
if (fs6.existsSync(resolved) && !resolved.endsWith(".ts") && !resolved.endsWith(".js")) {
|
|
94
112
|
return path9.resolve(resolved, DEFAULT_CONFIG_FILENAME);
|
|
95
113
|
}
|
|
96
114
|
return resolved;
|
|
@@ -102,6 +120,240 @@ var init_load_config = __esm({
|
|
|
102
120
|
}
|
|
103
121
|
});
|
|
104
122
|
|
|
123
|
+
// src/constants.ts
|
|
124
|
+
var PREBUILD_PAGE_SIZE, DEFAULT_MAX_PREBUILD_AGE_SEC, DEFAULT_PREBUILD_DIR;
|
|
125
|
+
var init_constants = __esm({
|
|
126
|
+
"src/constants.ts"() {
|
|
127
|
+
PREBUILD_PAGE_SIZE = 50;
|
|
128
|
+
DEFAULT_MAX_PREBUILD_AGE_SEC = 86400;
|
|
129
|
+
DEFAULT_PREBUILD_DIR = ".riverbank-cache";
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// src/prebuild/loader.ts
|
|
134
|
+
var loader_exports = {};
|
|
135
|
+
__export(loader_exports, {
|
|
136
|
+
PrebuildLoader: () => PrebuildLoader,
|
|
137
|
+
canUsePrebuild: () => canUsePrebuild,
|
|
138
|
+
createPrebuildLoader: () => createPrebuildLoader
|
|
139
|
+
});
|
|
140
|
+
function loadManifest(prebuildDir) {
|
|
141
|
+
if (cachedManifest?.dir === prebuildDir) {
|
|
142
|
+
return cachedManifest.manifest;
|
|
143
|
+
}
|
|
144
|
+
const manifestPath = path9__namespace.join(prebuildDir, "manifest.json");
|
|
145
|
+
if (!fs6__namespace.existsSync(manifestPath)) {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
const content = fs6__namespace.readFileSync(manifestPath, "utf-8");
|
|
150
|
+
const manifest = JSON.parse(content);
|
|
151
|
+
cachedManifest = { manifest, dir: prebuildDir };
|
|
152
|
+
return manifest;
|
|
153
|
+
} catch {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function loadJsonFile(prebuildDir, relativePath) {
|
|
158
|
+
const filePath = path9__namespace.join(prebuildDir, relativePath);
|
|
159
|
+
if (!fs6__namespace.existsSync(filePath)) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
const content = fs6__namespace.readFileSync(filePath, "utf-8");
|
|
164
|
+
return JSON.parse(content);
|
|
165
|
+
} catch {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function isPrebuildExpired(manifest, maxAgeSec) {
|
|
170
|
+
const ageMs = Date.now() - new Date(manifest.generatedAt).getTime();
|
|
171
|
+
return ageMs > maxAgeSec * 1e3;
|
|
172
|
+
}
|
|
173
|
+
function getPrebuildAgeSec(manifest) {
|
|
174
|
+
const ageMs = Date.now() - new Date(manifest.generatedAt).getTime();
|
|
175
|
+
return Math.floor(ageMs / 1e3);
|
|
176
|
+
}
|
|
177
|
+
function canUsePrebuild() {
|
|
178
|
+
if (typeof process === "undefined" || !process.versions?.node) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
return typeof fs6__namespace.existsSync === "function";
|
|
183
|
+
} catch {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function createPrebuildLoader(config3) {
|
|
188
|
+
return new PrebuildLoader(config3);
|
|
189
|
+
}
|
|
190
|
+
var cachedManifest, PrebuildLoader;
|
|
191
|
+
var init_loader = __esm({
|
|
192
|
+
"src/prebuild/loader.ts"() {
|
|
193
|
+
init_constants();
|
|
194
|
+
cachedManifest = null;
|
|
195
|
+
PrebuildLoader = class {
|
|
196
|
+
constructor(config3) {
|
|
197
|
+
this.prebuildDir = config3.prebuildDir ?? DEFAULT_PREBUILD_DIR;
|
|
198
|
+
this.maxPrebuildAgeSec = config3.maxPrebuildAgeSec ?? DEFAULT_MAX_PREBUILD_AGE_SEC;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Check if prebuild is available and not expired.
|
|
202
|
+
*/
|
|
203
|
+
isAvailable() {
|
|
204
|
+
if (!canUsePrebuild()) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
const manifest = loadManifest(this.prebuildDir);
|
|
208
|
+
if (!manifest) {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
return !isPrebuildExpired(manifest, this.maxPrebuildAgeSec);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Load site data from prebuild cache.
|
|
215
|
+
*/
|
|
216
|
+
loadSite(siteId) {
|
|
217
|
+
const manifest = loadManifest(this.prebuildDir);
|
|
218
|
+
if (!manifest || isPrebuildExpired(manifest, this.maxPrebuildAgeSec)) {
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
const cacheFile = loadJsonFile(this.prebuildDir, "site.json");
|
|
222
|
+
if (!cacheFile || cacheFile.data.site.id !== siteId) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
data: cacheFile.data,
|
|
227
|
+
prebuildAgeSec: getPrebuildAgeSec(manifest)
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Load page data from prebuild cache.
|
|
232
|
+
*/
|
|
233
|
+
loadPage(siteId, pagePath) {
|
|
234
|
+
const manifest = loadManifest(this.prebuildDir);
|
|
235
|
+
if (!manifest || isPrebuildExpired(manifest, this.maxPrebuildAgeSec)) {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
const cacheKey = `page:${siteId}:${pagePath}:false`;
|
|
239
|
+
const relativePath = manifest.keyToFile[cacheKey];
|
|
240
|
+
if (!relativePath) {
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
const cacheFile = loadJsonFile(this.prebuildDir, relativePath);
|
|
244
|
+
if (!cacheFile) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
data: cacheFile.data,
|
|
249
|
+
prebuildAgeSec: getPrebuildAgeSec(manifest)
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Load entries from prebuild cache with runtime filtering.
|
|
254
|
+
*
|
|
255
|
+
* The prebuild stores ALL entries for each content type.
|
|
256
|
+
* Filtering, ordering, and pagination are applied at runtime.
|
|
257
|
+
*/
|
|
258
|
+
loadEntries(siteId, params) {
|
|
259
|
+
if (params.preview) {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
if (params.mode === "manual" && params.entryIds?.length) {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
const manifest = loadManifest(this.prebuildDir);
|
|
266
|
+
if (!manifest || isPrebuildExpired(manifest, this.maxPrebuildAgeSec)) {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
const cacheKey = `entries-all:${siteId}:${params.contentType}`;
|
|
270
|
+
const relativePath = manifest.keyToFile[cacheKey];
|
|
271
|
+
if (!relativePath) {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
const cacheFile = loadJsonFile(this.prebuildDir, relativePath);
|
|
275
|
+
if (!cacheFile) {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
let entries = [...cacheFile.entries];
|
|
279
|
+
if (params.order === "newest") {
|
|
280
|
+
entries.sort((a, b) => {
|
|
281
|
+
const aTime = a.publishedAt ? new Date(a.publishedAt).getTime() : 0;
|
|
282
|
+
const bTime = b.publishedAt ? new Date(b.publishedAt).getTime() : 0;
|
|
283
|
+
return bTime - aTime;
|
|
284
|
+
});
|
|
285
|
+
} else if (params.order === "oldest") {
|
|
286
|
+
entries.sort((a, b) => {
|
|
287
|
+
const aTime = a.publishedAt ? new Date(a.publishedAt).getTime() : 0;
|
|
288
|
+
const bTime = b.publishedAt ? new Date(b.publishedAt).getTime() : 0;
|
|
289
|
+
return aTime - bTime;
|
|
290
|
+
});
|
|
291
|
+
} else if (params.order === "title") {
|
|
292
|
+
entries.sort((a, b) => (a.title || "").localeCompare(b.title || ""));
|
|
293
|
+
}
|
|
294
|
+
const total = entries.length;
|
|
295
|
+
const offset = params.offset ?? 0;
|
|
296
|
+
const limit = params.limit ?? 10;
|
|
297
|
+
if (offset > 0) {
|
|
298
|
+
entries = entries.slice(offset);
|
|
299
|
+
}
|
|
300
|
+
entries = entries.slice(0, limit);
|
|
301
|
+
const prebuildAgeSec = getPrebuildAgeSec(manifest);
|
|
302
|
+
if (params.includeMeta) {
|
|
303
|
+
return {
|
|
304
|
+
data: {
|
|
305
|
+
entries,
|
|
306
|
+
total,
|
|
307
|
+
hasMore: offset + entries.length < total,
|
|
308
|
+
limit,
|
|
309
|
+
offset,
|
|
310
|
+
totalPages: Math.ceil(total / limit),
|
|
311
|
+
currentPage: Math.floor(offset / limit) + 1
|
|
312
|
+
},
|
|
313
|
+
prebuildAgeSec
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
return {
|
|
317
|
+
data: { entries },
|
|
318
|
+
prebuildAgeSec
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Load navigation data from prebuild cache.
|
|
323
|
+
*/
|
|
324
|
+
loadNavigation() {
|
|
325
|
+
const manifest = loadManifest(this.prebuildDir);
|
|
326
|
+
if (!manifest || isPrebuildExpired(manifest, this.maxPrebuildAgeSec)) {
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
const cacheFile = loadJsonFile(
|
|
330
|
+
this.prebuildDir,
|
|
331
|
+
"navigation/menus.json"
|
|
332
|
+
);
|
|
333
|
+
if (!cacheFile) {
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
return {
|
|
337
|
+
data: cacheFile.menus,
|
|
338
|
+
prebuildAgeSec: getPrebuildAgeSec(manifest)
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Get the manifest for inspection.
|
|
343
|
+
*/
|
|
344
|
+
getManifest() {
|
|
345
|
+
return loadManifest(this.prebuildDir);
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Clear the cached manifest (for testing).
|
|
349
|
+
*/
|
|
350
|
+
clearCache() {
|
|
351
|
+
cachedManifest = null;
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
|
|
105
357
|
// ../blocks/src/system/manifest/augmentManifest.ts
|
|
106
358
|
function augmentManifest(manifest) {
|
|
107
359
|
let augmentedFields = manifest.fields ?? [];
|
|
@@ -574,11 +826,11 @@ function bind(from, options) {
|
|
|
574
826
|
}
|
|
575
827
|
});
|
|
576
828
|
}
|
|
577
|
-
function when(
|
|
829
|
+
function when(path13, options) {
|
|
578
830
|
return (node) => ({
|
|
579
831
|
...node,
|
|
580
832
|
$when: {
|
|
581
|
-
when: { from:
|
|
833
|
+
when: { from: path13 },
|
|
582
834
|
...options?.equals !== void 0 ? { equals: options.equals } : {},
|
|
583
835
|
...options?.not ? { not: true } : {}
|
|
584
836
|
}
|
|
@@ -651,25 +903,25 @@ function devValidate(node) {
|
|
|
651
903
|
}
|
|
652
904
|
|
|
653
905
|
// ../blocks/src/system/node/fragments/backgroundLayer.ts
|
|
654
|
-
function backgroundLayer(
|
|
906
|
+
function backgroundLayer(path13, options = {}) {
|
|
655
907
|
const {
|
|
656
908
|
styleClassName = "absolute inset-0 -z-10 h-full w-full pointer-events-none",
|
|
657
909
|
imageClassName
|
|
658
910
|
} = options;
|
|
659
911
|
const styleLayer = el("div", {
|
|
660
|
-
className: { $bind: { from:
|
|
661
|
-
style: { $bind: { from:
|
|
912
|
+
className: { $bind: { from: path13, transforms: [{ id: "background.resolveClass", options: { baseClass: styleClassName } }] } },
|
|
913
|
+
style: { $bind: { from: path13, transforms: [{ id: "background.resolveStyle" }] } }
|
|
662
914
|
});
|
|
663
|
-
const imageLayer = createBackgroundImageNode(
|
|
915
|
+
const imageLayer = createBackgroundImageNode(path13, imageClassName);
|
|
664
916
|
return [styleLayer, imageLayer];
|
|
665
917
|
}
|
|
666
|
-
function createBackgroundImageNode(
|
|
667
|
-
const imagePath = `${
|
|
918
|
+
function createBackgroundImageNode(path13, baseClassName = "absolute -z-10") {
|
|
919
|
+
const imagePath = `${path13}.image`;
|
|
668
920
|
return media(
|
|
669
921
|
{
|
|
670
922
|
className: {
|
|
671
923
|
$bind: {
|
|
672
|
-
from:
|
|
924
|
+
from: path13,
|
|
673
925
|
transforms: [{
|
|
674
926
|
id: "background.resolveImageClassName",
|
|
675
927
|
options: { baseClass: `background-image ${baseClassName}` }
|
|
@@ -678,7 +930,7 @@ function createBackgroundImageNode(path11, baseClassName = "absolute -z-10") {
|
|
|
678
930
|
},
|
|
679
931
|
style: {
|
|
680
932
|
$bind: {
|
|
681
|
-
from:
|
|
933
|
+
from: path13,
|
|
682
934
|
transforms: [{ id: "background.resolveImageStyle" }]
|
|
683
935
|
}
|
|
684
936
|
}
|
|
@@ -1106,27 +1358,27 @@ function scopePropValue(value, scope) {
|
|
|
1106
1358
|
}
|
|
1107
1359
|
return value;
|
|
1108
1360
|
}
|
|
1109
|
-
function scopeContentPath(
|
|
1361
|
+
function scopeContentPath(path13, scope) {
|
|
1110
1362
|
if (!scope || scope.length === 0) {
|
|
1111
|
-
return
|
|
1363
|
+
return path13;
|
|
1112
1364
|
}
|
|
1113
|
-
if (
|
|
1365
|
+
if (path13 === "content") {
|
|
1114
1366
|
return `content.${scope}`;
|
|
1115
1367
|
}
|
|
1116
|
-
if (
|
|
1117
|
-
const remainder =
|
|
1368
|
+
if (path13.startsWith("content.")) {
|
|
1369
|
+
const remainder = path13.slice("content.".length);
|
|
1118
1370
|
return remainder.length > 0 ? `content.${scope}.${remainder}` : `content.${scope}`;
|
|
1119
1371
|
}
|
|
1120
|
-
if (
|
|
1121
|
-
return
|
|
1372
|
+
if (path13.startsWith("content[")) {
|
|
1373
|
+
return path13.replace(/^content/, `content.${scope}`);
|
|
1122
1374
|
}
|
|
1123
|
-
if (
|
|
1124
|
-
return
|
|
1375
|
+
if (path13.startsWith("$root.")) {
|
|
1376
|
+
return path13;
|
|
1125
1377
|
}
|
|
1126
|
-
if (
|
|
1127
|
-
return
|
|
1378
|
+
if (path13.includes(".")) {
|
|
1379
|
+
return path13;
|
|
1128
1380
|
}
|
|
1129
|
-
return `content.${scope}.${
|
|
1381
|
+
return `content.${scope}.${path13}`;
|
|
1130
1382
|
}
|
|
1131
1383
|
|
|
1132
1384
|
// ../blocks/src/system/fragments/builder.ts
|
|
@@ -5133,7 +5385,7 @@ var contentConfigSchema = contentConfigBaseSchema.superRefine((data, ctx) => {
|
|
|
5133
5385
|
});
|
|
5134
5386
|
}
|
|
5135
5387
|
const paths = data.pages.map((p) => p.path);
|
|
5136
|
-
const duplicatePaths = paths.filter((
|
|
5388
|
+
const duplicatePaths = paths.filter((path13, i) => paths.indexOf(path13) !== i);
|
|
5137
5389
|
if (duplicatePaths.length > 0) {
|
|
5138
5390
|
ctx.addIssue({
|
|
5139
5391
|
code: zod.z.ZodIssueCode.custom,
|
|
@@ -5510,8 +5762,8 @@ var ManagementApiError = class extends Error {
|
|
|
5510
5762
|
function createHttpClient(config3) {
|
|
5511
5763
|
const baseUrl = `${config3.dashboardUrl}/api/sdk/${config3.siteId}`;
|
|
5512
5764
|
const timeout = config3.timeout ?? 3e4;
|
|
5513
|
-
async function request(method,
|
|
5514
|
-
let url = `${baseUrl}${
|
|
5765
|
+
async function request(method, path13, options) {
|
|
5766
|
+
let url = `${baseUrl}${path13}`;
|
|
5515
5767
|
if (options?.params && Object.keys(options.params).length > 0) {
|
|
5516
5768
|
const searchParams = new URLSearchParams(options.params);
|
|
5517
5769
|
url = `${url}?${searchParams.toString()}`;
|
|
@@ -5579,17 +5831,17 @@ function createHttpClient(config3) {
|
|
|
5579
5831
|
return json.data;
|
|
5580
5832
|
}
|
|
5581
5833
|
return {
|
|
5582
|
-
async get(
|
|
5583
|
-
return request("GET",
|
|
5834
|
+
async get(path13, params) {
|
|
5835
|
+
return request("GET", path13, { params });
|
|
5584
5836
|
},
|
|
5585
|
-
async post(
|
|
5586
|
-
return request("POST",
|
|
5837
|
+
async post(path13, body) {
|
|
5838
|
+
return request("POST", path13, { body });
|
|
5587
5839
|
},
|
|
5588
|
-
async patch(
|
|
5589
|
-
return request("PATCH",
|
|
5840
|
+
async patch(path13, body) {
|
|
5841
|
+
return request("PATCH", path13, { body });
|
|
5590
5842
|
},
|
|
5591
|
-
async delete(
|
|
5592
|
-
await request("DELETE",
|
|
5843
|
+
async delete(path13, body) {
|
|
5844
|
+
await request("DELETE", path13, { body });
|
|
5593
5845
|
}
|
|
5594
5846
|
};
|
|
5595
5847
|
}
|
|
@@ -6748,11 +7000,11 @@ function findChangedFields(local, remote, prefix = "") {
|
|
|
6748
7000
|
const changes = [];
|
|
6749
7001
|
const allKeys = /* @__PURE__ */ new Set([...Object.keys(local), ...Object.keys(remote)]);
|
|
6750
7002
|
for (const key of allKeys) {
|
|
6751
|
-
const
|
|
7003
|
+
const path13 = prefix ? `${prefix}.${key}` : key;
|
|
6752
7004
|
const localVal = local[key];
|
|
6753
7005
|
const remoteVal = remote[key];
|
|
6754
7006
|
if (!equal__default.default(localVal, remoteVal)) {
|
|
6755
|
-
changes.push(
|
|
7007
|
+
changes.push(path13);
|
|
6756
7008
|
}
|
|
6757
7009
|
}
|
|
6758
7010
|
return changes;
|
|
@@ -8505,7 +8757,7 @@ function getContentDir() {
|
|
|
8505
8757
|
function loadTemplate(name) {
|
|
8506
8758
|
const contentDir = getContentDir();
|
|
8507
8759
|
const filePath = path9__namespace.join(contentDir, `${name}.md`);
|
|
8508
|
-
return
|
|
8760
|
+
return fs6.readFileSync(filePath, "utf-8");
|
|
8509
8761
|
}
|
|
8510
8762
|
async function initDocs(options) {
|
|
8511
8763
|
const { rootDir, configPath, agentsPath } = options;
|
|
@@ -8692,6 +8944,3407 @@ Examples:
|
|
|
8692
8944
|
$ riverbankcms identifiers backfill
|
|
8693
8945
|
`).addCommand(backfillCommand);
|
|
8694
8946
|
|
|
8947
|
+
// src/cli/commands/deploy.ts
|
|
8948
|
+
init_load_config();
|
|
8949
|
+
|
|
8950
|
+
// ../api/src/endpoints.ts
|
|
8951
|
+
var ENDPOINT_DEFINITIONS = {
|
|
8952
|
+
// AI endpoints - no cache due to dynamic nature
|
|
8953
|
+
aiContentUpdateChat: {
|
|
8954
|
+
path: "/ai/content-update-chat",
|
|
8955
|
+
method: "POST",
|
|
8956
|
+
auth: "user",
|
|
8957
|
+
responseKind: "stream"
|
|
8958
|
+
},
|
|
8959
|
+
aiChat: {
|
|
8960
|
+
path: "/ai/chat",
|
|
8961
|
+
method: "POST",
|
|
8962
|
+
auth: "user",
|
|
8963
|
+
responseKind: "stream"
|
|
8964
|
+
},
|
|
8965
|
+
applySeoChanges: {
|
|
8966
|
+
path: "/seo/apply",
|
|
8967
|
+
method: "POST",
|
|
8968
|
+
auth: "user",
|
|
8969
|
+
responseKind: "json"
|
|
8970
|
+
},
|
|
8971
|
+
aiCreateBriefChat: {
|
|
8972
|
+
path: "/ai/chat/create-brief",
|
|
8973
|
+
method: "POST",
|
|
8974
|
+
auth: "user",
|
|
8975
|
+
responseKind: "json"
|
|
8976
|
+
},
|
|
8977
|
+
aiPrototypeChat: {
|
|
8978
|
+
path: "/ai/chat/create-prototype",
|
|
8979
|
+
method: "POST",
|
|
8980
|
+
revalidate: 30,
|
|
8981
|
+
// Short cache for AI responses to avoid duplicate calls
|
|
8982
|
+
tags: ["ai-prototype"],
|
|
8983
|
+
auth: "user",
|
|
8984
|
+
responseKind: "json"
|
|
8985
|
+
},
|
|
8986
|
+
aiPatchDryRun: {
|
|
8987
|
+
path: "/ai/patch/dry-run",
|
|
8988
|
+
method: "POST",
|
|
8989
|
+
auth: "user",
|
|
8990
|
+
responseKind: "json"
|
|
8991
|
+
},
|
|
8992
|
+
aiPatchApply: {
|
|
8993
|
+
path: "/ai/patch/apply",
|
|
8994
|
+
method: "POST",
|
|
8995
|
+
auth: "user",
|
|
8996
|
+
responseKind: "json"
|
|
8997
|
+
},
|
|
8998
|
+
aiPlaygroundPropose: {
|
|
8999
|
+
path: "/sites/{siteId}/ai/playground/propose",
|
|
9000
|
+
method: "POST",
|
|
9001
|
+
auth: "user",
|
|
9002
|
+
responseKind: "json"
|
|
9003
|
+
},
|
|
9004
|
+
// Admin SEO
|
|
9005
|
+
listGscPropertiesAdmin: {
|
|
9006
|
+
path: "/admin/seo/gsc/properties",
|
|
9007
|
+
method: "GET",
|
|
9008
|
+
auth: "admin",
|
|
9009
|
+
responseKind: "json"
|
|
9010
|
+
},
|
|
9011
|
+
adminSetGscPersist: {
|
|
9012
|
+
path: "/admin/seo/gsc/meta/persist",
|
|
9013
|
+
method: "POST",
|
|
9014
|
+
auth: "admin",
|
|
9015
|
+
responseKind: "json"
|
|
9016
|
+
},
|
|
9017
|
+
adminStartGscVerification: {
|
|
9018
|
+
path: "/admin/seo/gsc/properties/verify/start",
|
|
9019
|
+
method: "POST",
|
|
9020
|
+
auth: "admin",
|
|
9021
|
+
responseKind: "json"
|
|
9022
|
+
},
|
|
9023
|
+
adminConfirmGscVerification: {
|
|
9024
|
+
path: "/admin/seo/gsc/properties/verify/confirm",
|
|
9025
|
+
method: "POST",
|
|
9026
|
+
auth: "admin",
|
|
9027
|
+
responseKind: "json"
|
|
9028
|
+
},
|
|
9029
|
+
adminRunGscIngest: {
|
|
9030
|
+
path: "/admin/seo/ingest/run",
|
|
9031
|
+
method: "POST",
|
|
9032
|
+
auth: "admin",
|
|
9033
|
+
responseKind: "json"
|
|
9034
|
+
},
|
|
9035
|
+
getSeoVerificationMeta: {
|
|
9036
|
+
path: "/public/seo/verification/meta",
|
|
9037
|
+
method: "GET",
|
|
9038
|
+
auth: "public",
|
|
9039
|
+
responseKind: "json"
|
|
9040
|
+
},
|
|
9041
|
+
checkRedirect: {
|
|
9042
|
+
path: "/api/public/content/redirect",
|
|
9043
|
+
method: "GET",
|
|
9044
|
+
revalidate: 86400,
|
|
9045
|
+
// 24 hours - redirects rarely change
|
|
9046
|
+
tags: ["redirect"],
|
|
9047
|
+
auth: "public",
|
|
9048
|
+
responseKind: "json"
|
|
9049
|
+
},
|
|
9050
|
+
listRedirectRules: {
|
|
9051
|
+
path: "/sites/{siteId}/redirects",
|
|
9052
|
+
method: "GET",
|
|
9053
|
+
auth: "user",
|
|
9054
|
+
responseKind: "json"
|
|
9055
|
+
},
|
|
9056
|
+
createRedirectRule: {
|
|
9057
|
+
path: "/sites/{siteId}/redirects",
|
|
9058
|
+
method: "POST",
|
|
9059
|
+
auth: "user",
|
|
9060
|
+
responseKind: "json"
|
|
9061
|
+
},
|
|
9062
|
+
deleteRedirectRule: {
|
|
9063
|
+
path: "/sites/{siteId}/redirects/{ruleId}",
|
|
9064
|
+
method: "DELETE",
|
|
9065
|
+
auth: "user",
|
|
9066
|
+
responseKind: "json"
|
|
9067
|
+
},
|
|
9068
|
+
// API Keys (Account-level - DEPRECATED, use site-scoped endpoints)
|
|
9069
|
+
listApiKeys: {
|
|
9070
|
+
path: "/account/api-keys",
|
|
9071
|
+
method: "GET",
|
|
9072
|
+
auth: "user",
|
|
9073
|
+
responseKind: "json"
|
|
9074
|
+
},
|
|
9075
|
+
createApiKey: {
|
|
9076
|
+
path: "/account/api-keys",
|
|
9077
|
+
method: "POST",
|
|
9078
|
+
auth: "user",
|
|
9079
|
+
responseKind: "json"
|
|
9080
|
+
},
|
|
9081
|
+
revokeApiKey: {
|
|
9082
|
+
path: "/account/api-keys/{keyId}",
|
|
9083
|
+
method: "DELETE",
|
|
9084
|
+
auth: "user",
|
|
9085
|
+
responseKind: "json"
|
|
9086
|
+
},
|
|
9087
|
+
// API Keys (Site-scoped - preferred)
|
|
9088
|
+
listSiteApiKeys: {
|
|
9089
|
+
path: "/sites/{siteId}/api-keys",
|
|
9090
|
+
method: "GET",
|
|
9091
|
+
auth: "user",
|
|
9092
|
+
tags: ["site-{siteId}", "api-keys"],
|
|
9093
|
+
responseKind: "json"
|
|
9094
|
+
},
|
|
9095
|
+
createSiteApiKey: {
|
|
9096
|
+
path: "/sites/{siteId}/api-keys",
|
|
9097
|
+
method: "POST",
|
|
9098
|
+
auth: "user",
|
|
9099
|
+
tags: ["site-{siteId}", "api-keys"],
|
|
9100
|
+
responseKind: "json"
|
|
9101
|
+
},
|
|
9102
|
+
revokeSiteApiKey: {
|
|
9103
|
+
path: "/sites/{siteId}/api-keys/{keyId}",
|
|
9104
|
+
method: "DELETE",
|
|
9105
|
+
auth: "user",
|
|
9106
|
+
tags: ["site-{siteId}", "api-keys"],
|
|
9107
|
+
responseKind: "json"
|
|
9108
|
+
},
|
|
9109
|
+
getSitePreviewKey: {
|
|
9110
|
+
path: "/sites/{siteId}/api-keys/preview",
|
|
9111
|
+
method: "GET",
|
|
9112
|
+
auth: "user",
|
|
9113
|
+
tags: ["site-{siteId}", "api-keys", "preview-key"],
|
|
9114
|
+
responseKind: "json"
|
|
9115
|
+
},
|
|
9116
|
+
regenerateSitePreviewKey: {
|
|
9117
|
+
path: "/sites/{siteId}/api-keys/preview/regenerate",
|
|
9118
|
+
method: "POST",
|
|
9119
|
+
auth: "user",
|
|
9120
|
+
tags: ["site-{siteId}", "api-keys", "preview-key"],
|
|
9121
|
+
responseKind: "json"
|
|
9122
|
+
},
|
|
9123
|
+
getSiteApiKeyAccessLogs: {
|
|
9124
|
+
path: "/sites/{siteId}/api-keys/access-logs",
|
|
9125
|
+
method: "GET",
|
|
9126
|
+
auth: "user",
|
|
9127
|
+
tags: ["site-{siteId}", "api-keys", "access-logs"],
|
|
9128
|
+
responseKind: "json"
|
|
9129
|
+
},
|
|
9130
|
+
// Management API Keys (SDK write operations)
|
|
9131
|
+
listManagementKeys: {
|
|
9132
|
+
path: "/sites/{siteId}/api-keys/management",
|
|
9133
|
+
method: "GET",
|
|
9134
|
+
auth: "user",
|
|
9135
|
+
tags: ["site-{siteId}", "api-keys", "management-keys"],
|
|
9136
|
+
responseKind: "json"
|
|
9137
|
+
},
|
|
9138
|
+
createManagementKey: {
|
|
9139
|
+
path: "/sites/{siteId}/api-keys/management",
|
|
9140
|
+
method: "POST",
|
|
9141
|
+
auth: "user",
|
|
9142
|
+
tags: ["site-{siteId}", "api-keys", "management-keys"],
|
|
9143
|
+
responseKind: "json"
|
|
9144
|
+
},
|
|
9145
|
+
revokeManagementKey: {
|
|
9146
|
+
path: "/sites/{siteId}/api-keys/management",
|
|
9147
|
+
method: "DELETE",
|
|
9148
|
+
auth: "user",
|
|
9149
|
+
tags: ["site-{siteId}", "api-keys", "management-keys"],
|
|
9150
|
+
responseKind: "json"
|
|
9151
|
+
},
|
|
9152
|
+
getBookingSettings: {
|
|
9153
|
+
path: "/sites/{siteId}/bookings/settings",
|
|
9154
|
+
method: "GET",
|
|
9155
|
+
auth: "user",
|
|
9156
|
+
responseKind: "json"
|
|
9157
|
+
},
|
|
9158
|
+
updateBookingSettings: {
|
|
9159
|
+
path: "/sites/{siteId}/bookings/settings",
|
|
9160
|
+
method: "PUT",
|
|
9161
|
+
auth: "user",
|
|
9162
|
+
responseKind: "json"
|
|
9163
|
+
},
|
|
9164
|
+
listAppointmentResources: {
|
|
9165
|
+
path: "/sites/{siteId}/bookings/resources",
|
|
9166
|
+
method: "GET",
|
|
9167
|
+
auth: "user",
|
|
9168
|
+
responseKind: "json"
|
|
9169
|
+
},
|
|
9170
|
+
createAppointmentResource: {
|
|
9171
|
+
path: "/sites/{siteId}/bookings/resources",
|
|
9172
|
+
method: "POST",
|
|
9173
|
+
auth: "user",
|
|
9174
|
+
responseKind: "json"
|
|
9175
|
+
},
|
|
9176
|
+
getAppointmentResource: {
|
|
9177
|
+
path: "/sites/{siteId}/bookings/resources/{resourceId}",
|
|
9178
|
+
method: "GET",
|
|
9179
|
+
auth: "user",
|
|
9180
|
+
responseKind: "json"
|
|
9181
|
+
},
|
|
9182
|
+
updateAppointmentResource: {
|
|
9183
|
+
path: "/sites/{siteId}/bookings/resources/{resourceId}",
|
|
9184
|
+
method: "PUT",
|
|
9185
|
+
auth: "user",
|
|
9186
|
+
responseKind: "json"
|
|
9187
|
+
},
|
|
9188
|
+
deleteAppointmentResource: {
|
|
9189
|
+
path: "/sites/{siteId}/bookings/resources/{resourceId}",
|
|
9190
|
+
method: "DELETE",
|
|
9191
|
+
auth: "user",
|
|
9192
|
+
responseKind: "json"
|
|
9193
|
+
},
|
|
9194
|
+
listAppointmentServices: {
|
|
9195
|
+
path: "/sites/{siteId}/bookings/services",
|
|
9196
|
+
method: "GET",
|
|
9197
|
+
auth: "user",
|
|
9198
|
+
responseKind: "json"
|
|
9199
|
+
},
|
|
9200
|
+
createAppointmentService: {
|
|
9201
|
+
path: "/sites/{siteId}/bookings/services",
|
|
9202
|
+
method: "POST",
|
|
9203
|
+
auth: "user",
|
|
9204
|
+
responseKind: "json"
|
|
9205
|
+
},
|
|
9206
|
+
getAppointmentService: {
|
|
9207
|
+
path: "/sites/{siteId}/bookings/services/{serviceId}",
|
|
9208
|
+
method: "GET",
|
|
9209
|
+
auth: "user",
|
|
9210
|
+
responseKind: "json"
|
|
9211
|
+
},
|
|
9212
|
+
updateAppointmentService: {
|
|
9213
|
+
path: "/sites/{siteId}/bookings/services/{serviceId}",
|
|
9214
|
+
method: "PUT",
|
|
9215
|
+
auth: "user",
|
|
9216
|
+
responseKind: "json"
|
|
9217
|
+
},
|
|
9218
|
+
deleteAppointmentService: {
|
|
9219
|
+
path: "/sites/{siteId}/bookings/services/{serviceId}",
|
|
9220
|
+
method: "DELETE",
|
|
9221
|
+
auth: "user",
|
|
9222
|
+
responseKind: "json"
|
|
9223
|
+
},
|
|
9224
|
+
getAppointmentServicesReference: {
|
|
9225
|
+
path: "/sites/{siteId}/bookings/services/reference",
|
|
9226
|
+
method: "GET",
|
|
9227
|
+
auth: "user",
|
|
9228
|
+
responseKind: "json"
|
|
9229
|
+
},
|
|
9230
|
+
getAppointmentResourcesReference: {
|
|
9231
|
+
path: "/sites/{siteId}/bookings/resources/reference",
|
|
9232
|
+
method: "GET",
|
|
9233
|
+
auth: "user",
|
|
9234
|
+
responseKind: "json"
|
|
9235
|
+
},
|
|
9236
|
+
// Service-Resource linking
|
|
9237
|
+
getResourceServices: {
|
|
9238
|
+
path: "/sites/{siteId}/bookings/resources/{resourceId}/services",
|
|
9239
|
+
method: "GET",
|
|
9240
|
+
auth: "user",
|
|
9241
|
+
responseKind: "json"
|
|
9242
|
+
},
|
|
9243
|
+
updateResourceServices: {
|
|
9244
|
+
path: "/sites/{siteId}/bookings/resources/{resourceId}/services",
|
|
9245
|
+
method: "PUT",
|
|
9246
|
+
auth: "user",
|
|
9247
|
+
responseKind: "json"
|
|
9248
|
+
},
|
|
9249
|
+
getServiceResources: {
|
|
9250
|
+
path: "/sites/{siteId}/bookings/services/{serviceId}/resources",
|
|
9251
|
+
method: "GET",
|
|
9252
|
+
auth: "user",
|
|
9253
|
+
responseKind: "json"
|
|
9254
|
+
},
|
|
9255
|
+
updateServiceResources: {
|
|
9256
|
+
path: "/sites/{siteId}/bookings/services/{serviceId}/resources",
|
|
9257
|
+
method: "PUT",
|
|
9258
|
+
auth: "user",
|
|
9259
|
+
responseKind: "json"
|
|
9260
|
+
},
|
|
9261
|
+
// Availability management
|
|
9262
|
+
listAvailabilityRules: {
|
|
9263
|
+
path: "/sites/{siteId}/bookings/resources/{resourceId}/availability",
|
|
9264
|
+
method: "GET",
|
|
9265
|
+
auth: "user",
|
|
9266
|
+
responseKind: "json"
|
|
9267
|
+
},
|
|
9268
|
+
upsertAvailabilityRule: {
|
|
9269
|
+
path: "/sites/{siteId}/bookings/resources/{resourceId}/availability",
|
|
9270
|
+
method: "POST",
|
|
9271
|
+
auth: "user",
|
|
9272
|
+
responseKind: "json"
|
|
9273
|
+
},
|
|
9274
|
+
deleteAvailabilityRule: {
|
|
9275
|
+
path: "/sites/{siteId}/bookings/resources/{resourceId}/availability/{ruleId}",
|
|
9276
|
+
method: "DELETE",
|
|
9277
|
+
auth: "user",
|
|
9278
|
+
responseKind: "json"
|
|
9279
|
+
},
|
|
9280
|
+
listBlackouts: {
|
|
9281
|
+
path: "/sites/{siteId}/bookings/resources/{resourceId}/blackouts",
|
|
9282
|
+
method: "GET",
|
|
9283
|
+
auth: "user",
|
|
9284
|
+
responseKind: "json"
|
|
9285
|
+
},
|
|
9286
|
+
createBlackout: {
|
|
9287
|
+
path: "/sites/{siteId}/bookings/resources/{resourceId}/blackouts",
|
|
9288
|
+
method: "POST",
|
|
9289
|
+
auth: "user",
|
|
9290
|
+
responseKind: "json"
|
|
9291
|
+
},
|
|
9292
|
+
deleteBlackout: {
|
|
9293
|
+
path: "/sites/{siteId}/bookings/resources/{resourceId}/blackouts/{blackoutId}",
|
|
9294
|
+
method: "DELETE",
|
|
9295
|
+
auth: "user",
|
|
9296
|
+
responseKind: "json"
|
|
9297
|
+
},
|
|
9298
|
+
getAvailableSlots: {
|
|
9299
|
+
path: "/sites/{siteId}/bookings/availability/slots",
|
|
9300
|
+
method: "GET",
|
|
9301
|
+
auth: "user",
|
|
9302
|
+
responseKind: "json"
|
|
9303
|
+
},
|
|
9304
|
+
createAppointment: {
|
|
9305
|
+
path: "/sites/{siteId}/bookings/appointments",
|
|
9306
|
+
method: "POST",
|
|
9307
|
+
auth: "user",
|
|
9308
|
+
responseKind: "json"
|
|
9309
|
+
},
|
|
9310
|
+
// Data retrieval endpoints - good candidates for caching
|
|
9311
|
+
getBrief: {
|
|
9312
|
+
path: "/briefs",
|
|
9313
|
+
method: "GET",
|
|
9314
|
+
revalidate: 120,
|
|
9315
|
+
// 2 minutes
|
|
9316
|
+
tags: ["brief"],
|
|
9317
|
+
auth: "user",
|
|
9318
|
+
responseKind: "json"
|
|
9319
|
+
},
|
|
9320
|
+
// Unified site data endpoint - use this for all site lookups
|
|
9321
|
+
getSite: {
|
|
9322
|
+
path: "/sites",
|
|
9323
|
+
method: "GET",
|
|
9324
|
+
revalidate: 900,
|
|
9325
|
+
// 15 minutes - site data changes less frequently
|
|
9326
|
+
tags: ["site"],
|
|
9327
|
+
auth: "user",
|
|
9328
|
+
responseKind: "json"
|
|
9329
|
+
},
|
|
9330
|
+
// DEPRECATED: Use getSite with ?slug={slug} instead
|
|
9331
|
+
getSiteBySlug: {
|
|
9332
|
+
path: "/sites/by-slug/{slug}",
|
|
9333
|
+
method: "GET",
|
|
9334
|
+
revalidate: 900,
|
|
9335
|
+
// 15 minutes - site data changes less frequently
|
|
9336
|
+
tags: ["site", "site-{slug}"],
|
|
9337
|
+
auth: "user",
|
|
9338
|
+
responseKind: "json"
|
|
9339
|
+
},
|
|
9340
|
+
// DEPRECATED: Use getSite with ?domain={domain} instead
|
|
9341
|
+
getSiteByDomain: {
|
|
9342
|
+
path: "/sites/by-domain/{domain}",
|
|
9343
|
+
method: "GET",
|
|
9344
|
+
revalidate: 900,
|
|
9345
|
+
// 15 minutes - site data changes less frequently
|
|
9346
|
+
tags: ["site", "site-domain-{domain}"],
|
|
9347
|
+
auth: "user",
|
|
9348
|
+
responseKind: "json"
|
|
9349
|
+
},
|
|
9350
|
+
createBriefTurn: {
|
|
9351
|
+
path: "/brief-turns",
|
|
9352
|
+
method: "POST",
|
|
9353
|
+
tags: ["brief"],
|
|
9354
|
+
// Tags for invalidation after mutation
|
|
9355
|
+
auth: "user",
|
|
9356
|
+
responseKind: "json"
|
|
9357
|
+
},
|
|
9358
|
+
upsertBrief: {
|
|
9359
|
+
path: "/briefs",
|
|
9360
|
+
method: "PUT",
|
|
9361
|
+
tags: ["brief"],
|
|
9362
|
+
auth: "user",
|
|
9363
|
+
responseKind: "json"
|
|
9364
|
+
},
|
|
9365
|
+
aiBriefToSpec: {
|
|
9366
|
+
path: "/ai/actions/brief-to-spec",
|
|
9367
|
+
method: "POST",
|
|
9368
|
+
tags: ["brief", "spec"],
|
|
9369
|
+
auth: "user",
|
|
9370
|
+
responseKind: "json"
|
|
9371
|
+
},
|
|
9372
|
+
createSite: {
|
|
9373
|
+
path: "/sites",
|
|
9374
|
+
method: "POST",
|
|
9375
|
+
tags: ["site"],
|
|
9376
|
+
auth: "user",
|
|
9377
|
+
responseKind: "json"
|
|
9378
|
+
},
|
|
9379
|
+
createSiteManual: {
|
|
9380
|
+
path: "/sites/manual",
|
|
9381
|
+
method: "POST",
|
|
9382
|
+
tags: ["site"],
|
|
9383
|
+
auth: "user",
|
|
9384
|
+
responseKind: "json"
|
|
9385
|
+
},
|
|
9386
|
+
updateSite: {
|
|
9387
|
+
path: "/sites",
|
|
9388
|
+
method: "PUT",
|
|
9389
|
+
tags: ["site"],
|
|
9390
|
+
auth: "user",
|
|
9391
|
+
responseKind: "json"
|
|
9392
|
+
},
|
|
9393
|
+
deleteSite: {
|
|
9394
|
+
path: "/sites/{siteId}",
|
|
9395
|
+
method: "DELETE",
|
|
9396
|
+
tags: ["site", "site-{siteId}"],
|
|
9397
|
+
auth: "user",
|
|
9398
|
+
responseKind: "json"
|
|
9399
|
+
},
|
|
9400
|
+
listSiteMembers: {
|
|
9401
|
+
path: "/sites/{siteId}/members",
|
|
9402
|
+
method: "GET",
|
|
9403
|
+
tags: ["site-{siteId}", "site-members-{siteId}"],
|
|
9404
|
+
auth: "user",
|
|
9405
|
+
responseKind: "json"
|
|
9406
|
+
},
|
|
9407
|
+
inviteSiteMember: {
|
|
9408
|
+
path: "/sites/{siteId}/members",
|
|
9409
|
+
method: "POST",
|
|
9410
|
+
tags: ["site-{siteId}", "site-members-{siteId}"],
|
|
9411
|
+
auth: "user",
|
|
9412
|
+
responseKind: "json"
|
|
9413
|
+
},
|
|
9414
|
+
updateSiteMemberRole: {
|
|
9415
|
+
path: "/sites/{siteId}/members/{memberId}",
|
|
9416
|
+
method: "PATCH",
|
|
9417
|
+
tags: ["site-{siteId}", "site-members-{siteId}", "site-member-{memberId}"],
|
|
9418
|
+
auth: "user",
|
|
9419
|
+
responseKind: "json"
|
|
9420
|
+
},
|
|
9421
|
+
authLogin: {
|
|
9422
|
+
path: "/auth/login/submit",
|
|
9423
|
+
method: "POST",
|
|
9424
|
+
tags: ["auth"],
|
|
9425
|
+
auth: "public",
|
|
9426
|
+
responseKind: "json"
|
|
9427
|
+
},
|
|
9428
|
+
authForgotPassword: {
|
|
9429
|
+
path: "/auth/forgot/submit",
|
|
9430
|
+
method: "POST",
|
|
9431
|
+
tags: ["auth"],
|
|
9432
|
+
auth: "public",
|
|
9433
|
+
responseKind: "json"
|
|
9434
|
+
},
|
|
9435
|
+
authRegister: {
|
|
9436
|
+
path: "/auth/register/submit",
|
|
9437
|
+
method: "POST",
|
|
9438
|
+
tags: ["auth"],
|
|
9439
|
+
auth: "public",
|
|
9440
|
+
responseKind: "json"
|
|
9441
|
+
},
|
|
9442
|
+
authReauthenticate: {
|
|
9443
|
+
path: "/auth/reauth/submit",
|
|
9444
|
+
method: "POST",
|
|
9445
|
+
tags: ["auth"],
|
|
9446
|
+
auth: "public",
|
|
9447
|
+
responseKind: "json"
|
|
9448
|
+
},
|
|
9449
|
+
lookupSiteDomains: {
|
|
9450
|
+
path: "/sites/{siteId}/domains/lookup",
|
|
9451
|
+
method: "POST",
|
|
9452
|
+
tags: ["site-{siteId}", "site-domains"],
|
|
9453
|
+
auth: "user",
|
|
9454
|
+
responseKind: "json"
|
|
9455
|
+
},
|
|
9456
|
+
registerSiteDomain: {
|
|
9457
|
+
path: "/sites/{siteId}/domains/register",
|
|
9458
|
+
method: "POST",
|
|
9459
|
+
tags: ["site-{siteId}", "site-domains"],
|
|
9460
|
+
auth: "user",
|
|
9461
|
+
responseKind: "json"
|
|
9462
|
+
},
|
|
9463
|
+
addCustomDomain: {
|
|
9464
|
+
path: "/sites/{siteId}/domains/custom",
|
|
9465
|
+
method: "POST",
|
|
9466
|
+
tags: ["site-{siteId}", "site-domains"],
|
|
9467
|
+
auth: "user",
|
|
9468
|
+
responseKind: "json"
|
|
9469
|
+
},
|
|
9470
|
+
removeCustomDomain: {
|
|
9471
|
+
path: "/sites/{siteId}/domains/custom",
|
|
9472
|
+
method: "DELETE",
|
|
9473
|
+
tags: ["site-{siteId}", "site-domains"],
|
|
9474
|
+
auth: "user",
|
|
9475
|
+
responseKind: "json"
|
|
9476
|
+
},
|
|
9477
|
+
syncCustomDomainToEdgeConfig: {
|
|
9478
|
+
path: "/sites/{siteId}/domains/custom/sync",
|
|
9479
|
+
method: "POST",
|
|
9480
|
+
tags: ["site-{siteId}", "site-domains"],
|
|
9481
|
+
auth: "user",
|
|
9482
|
+
responseKind: "json"
|
|
9483
|
+
},
|
|
9484
|
+
removeSiteMember: {
|
|
9485
|
+
path: "/sites/{siteId}/members/{memberId}",
|
|
9486
|
+
method: "DELETE",
|
|
9487
|
+
tags: ["site-{siteId}", "site-members-{siteId}", "site-member-{memberId}"],
|
|
9488
|
+
auth: "user",
|
|
9489
|
+
responseKind: "json"
|
|
9490
|
+
},
|
|
9491
|
+
revokeSiteInvitation: {
|
|
9492
|
+
path: "/sites/{siteId}/members/invitations/{invitationId}",
|
|
9493
|
+
method: "DELETE",
|
|
9494
|
+
tags: ["site-{siteId}", "site-members-{siteId}", "site-invite-{invitationId}"],
|
|
9495
|
+
auth: "user",
|
|
9496
|
+
responseKind: "json"
|
|
9497
|
+
},
|
|
9498
|
+
transferSiteOwnership: {
|
|
9499
|
+
path: "/sites/{siteId}/members/transfer-ownership",
|
|
9500
|
+
method: "POST",
|
|
9501
|
+
tags: ["site-{siteId}", "site-members-{siteId}"],
|
|
9502
|
+
auth: "user",
|
|
9503
|
+
responseKind: "json"
|
|
9504
|
+
},
|
|
9505
|
+
listContentEntries: {
|
|
9506
|
+
path: "/sites/{siteId}/content/{type}",
|
|
9507
|
+
method: "GET",
|
|
9508
|
+
revalidate: 60,
|
|
9509
|
+
tags: ["site-{siteId}", "content-{siteId}-{type}"],
|
|
9510
|
+
auth: "user",
|
|
9511
|
+
responseKind: "json"
|
|
9512
|
+
},
|
|
9513
|
+
getContentTemplate: {
|
|
9514
|
+
path: "/sites/{siteId}/content/types/{type}/template",
|
|
9515
|
+
method: "GET",
|
|
9516
|
+
revalidate: 60,
|
|
9517
|
+
tags: ["site-{siteId}", "content-template-{siteId}-{type}"],
|
|
9518
|
+
auth: "user",
|
|
9519
|
+
responseKind: "json"
|
|
9520
|
+
},
|
|
9521
|
+
updateContentTemplateBlock: {
|
|
9522
|
+
path: "/sites/{siteId}/content/types/{type}/template/blocks/{blockId}",
|
|
9523
|
+
method: "PATCH",
|
|
9524
|
+
tags: ["site-{siteId}", "content-template-{siteId}-{type}", "content-template-block-{blockId}"],
|
|
9525
|
+
auth: "user",
|
|
9526
|
+
responseKind: "json"
|
|
9527
|
+
},
|
|
9528
|
+
applyContentTemplateAddon: {
|
|
9529
|
+
path: "/sites/{siteId}/content/types/{type}/template/addons",
|
|
9530
|
+
method: "POST",
|
|
9531
|
+
tags: ["site-{siteId}", "content-template-{siteId}-{type}"],
|
|
9532
|
+
auth: "user",
|
|
9533
|
+
responseKind: "json"
|
|
9534
|
+
},
|
|
9535
|
+
updateContentTemplateBlockBindings: {
|
|
9536
|
+
path: "/sites/{siteId}/content/types/{type}/template/blocks/{blockId}/bindings",
|
|
9537
|
+
method: "PATCH",
|
|
9538
|
+
tags: ["site-{siteId}", "content-template-{siteId}-{type}", "content-template-block-{blockId}"],
|
|
9539
|
+
auth: "user",
|
|
9540
|
+
responseKind: "json"
|
|
9541
|
+
},
|
|
9542
|
+
createTemplateBlock: {
|
|
9543
|
+
path: "/sites/{siteId}/content/types/{type}/template/blocks",
|
|
9544
|
+
method: "POST",
|
|
9545
|
+
tags: ["site-{siteId}", "content-template-{siteId}-{type}"],
|
|
9546
|
+
auth: "user",
|
|
9547
|
+
responseKind: "json"
|
|
9548
|
+
},
|
|
9549
|
+
deleteTemplateBlock: {
|
|
9550
|
+
path: "/sites/{siteId}/content/types/{type}/template/blocks/{blockId}",
|
|
9551
|
+
method: "DELETE",
|
|
9552
|
+
tags: ["site-{siteId}", "content-template-{siteId}-{type}", "content-template-block-{blockId}"],
|
|
9553
|
+
auth: "user",
|
|
9554
|
+
responseKind: "json"
|
|
9555
|
+
},
|
|
9556
|
+
reorderTemplateBlocks: {
|
|
9557
|
+
path: "/sites/{siteId}/content/types/{type}/template/blocks/reorder",
|
|
9558
|
+
method: "POST",
|
|
9559
|
+
tags: ["site-{siteId}", "content-template-{siteId}-{type}"],
|
|
9560
|
+
auth: "user",
|
|
9561
|
+
responseKind: "json"
|
|
9562
|
+
},
|
|
9563
|
+
getTransforms: {
|
|
9564
|
+
path: "/transforms",
|
|
9565
|
+
method: "GET",
|
|
9566
|
+
revalidate: 3600,
|
|
9567
|
+
tags: ["transforms"],
|
|
9568
|
+
auth: "public",
|
|
9569
|
+
responseKind: "json"
|
|
9570
|
+
},
|
|
9571
|
+
createContentEntry: {
|
|
9572
|
+
path: "/sites/{siteId}/content/{type}",
|
|
9573
|
+
method: "POST",
|
|
9574
|
+
tags: ["site-{siteId}", "content-{siteId}-{type}"],
|
|
9575
|
+
auth: "user",
|
|
9576
|
+
responseKind: "json"
|
|
9577
|
+
},
|
|
9578
|
+
getContentEntry: {
|
|
9579
|
+
path: "/sites/{siteId}/content/{type}/{entryId}",
|
|
9580
|
+
method: "GET",
|
|
9581
|
+
tags: ["site-{siteId}", "content-{siteId}-{type}", "content-entry-{entryId}"],
|
|
9582
|
+
auth: "user",
|
|
9583
|
+
responseKind: "json"
|
|
9584
|
+
},
|
|
9585
|
+
updateContentEntry: {
|
|
9586
|
+
path: "/sites/{siteId}/content/{type}/{entryId}",
|
|
9587
|
+
method: "PUT",
|
|
9588
|
+
tags: ["site-{siteId}", "content-{siteId}-{type}", "content-entry-{entryId}"],
|
|
9589
|
+
auth: "user",
|
|
9590
|
+
responseKind: "json"
|
|
9591
|
+
},
|
|
9592
|
+
updateContentEntryContent: {
|
|
9593
|
+
path: "/sites/{siteId}/content/{type}/{entryId}/content",
|
|
9594
|
+
method: "PUT",
|
|
9595
|
+
tags: ["site-{siteId}", "content-{siteId}-{type}", "content-entry-{entryId}"],
|
|
9596
|
+
auth: "user",
|
|
9597
|
+
responseKind: "json"
|
|
9598
|
+
},
|
|
9599
|
+
updateRouteMetadata: {
|
|
9600
|
+
path: "/sites/{siteId}/routes/{routeId}/metadata",
|
|
9601
|
+
method: "PATCH",
|
|
9602
|
+
tags: ["site-{siteId}", "route-{routeId}"],
|
|
9603
|
+
auth: "user",
|
|
9604
|
+
responseKind: "json"
|
|
9605
|
+
},
|
|
9606
|
+
publishContentEntry: {
|
|
9607
|
+
path: "/sites/{siteId}/content/{type}/{entryId}/publish",
|
|
9608
|
+
method: "POST",
|
|
9609
|
+
tags: ["site-{siteId}", "content-{siteId}-{type}", "content-entry-{entryId}"],
|
|
9610
|
+
auth: "user",
|
|
9611
|
+
responseKind: "json"
|
|
9612
|
+
},
|
|
9613
|
+
discardContentEntry: {
|
|
9614
|
+
path: "/sites/{siteId}/content/{type}/{entryId}/discard",
|
|
9615
|
+
method: "POST",
|
|
9616
|
+
tags: ["site-{siteId}", "content-{siteId}-{type}", "content-entry-{entryId}"],
|
|
9617
|
+
auth: "user",
|
|
9618
|
+
responseKind: "json"
|
|
9619
|
+
},
|
|
9620
|
+
unpublishContentEntry: {
|
|
9621
|
+
path: "/sites/{siteId}/content/{type}/{entryId}/unpublish",
|
|
9622
|
+
method: "POST",
|
|
9623
|
+
tags: ["site-{siteId}", "content-{siteId}-{type}", "content-entry-{entryId}"],
|
|
9624
|
+
auth: "user",
|
|
9625
|
+
responseKind: "json"
|
|
9626
|
+
},
|
|
9627
|
+
// Content types: enable + setup
|
|
9628
|
+
listContentTypes: {
|
|
9629
|
+
path: "/sites/{siteId}/content-types",
|
|
9630
|
+
method: "GET",
|
|
9631
|
+
revalidate: 120,
|
|
9632
|
+
// 2 minutes
|
|
9633
|
+
tags: ["site-{siteId}", "content-types"],
|
|
9634
|
+
auth: "user",
|
|
9635
|
+
responseKind: "json"
|
|
9636
|
+
},
|
|
9637
|
+
enableContentType: {
|
|
9638
|
+
path: "/sites/{siteId}/content-types/{key}/enable",
|
|
9639
|
+
method: "POST",
|
|
9640
|
+
tags: ["site-{siteId}", "content-types", "content-type-{key}"],
|
|
9641
|
+
auth: "user",
|
|
9642
|
+
responseKind: "json"
|
|
9643
|
+
},
|
|
9644
|
+
setupContentType: {
|
|
9645
|
+
path: "/sites/{siteId}/content-types/{key}/setup",
|
|
9646
|
+
method: "POST",
|
|
9647
|
+
tags: ["site-{siteId}", "content-types", "content-type-{key}"],
|
|
9648
|
+
auth: "user",
|
|
9649
|
+
responseKind: "json"
|
|
9650
|
+
},
|
|
9651
|
+
deleteContentEntry: {
|
|
9652
|
+
path: "/sites/{siteId}/content/{type}/{entryId}",
|
|
9653
|
+
method: "DELETE",
|
|
9654
|
+
tags: ["site-{siteId}", "content-{siteId}-{type}", "content-entry-{entryId}"],
|
|
9655
|
+
auth: "user",
|
|
9656
|
+
responseKind: "json"
|
|
9657
|
+
},
|
|
9658
|
+
updateSiteGeneralSettings: {
|
|
9659
|
+
path: "/sites/{siteId}/settings/general",
|
|
9660
|
+
method: "POST",
|
|
9661
|
+
tags: ["site-{siteId}", "site-settings-{siteId}"],
|
|
9662
|
+
auth: "user",
|
|
9663
|
+
responseKind: "json"
|
|
9664
|
+
},
|
|
9665
|
+
getSiteLayoutSettings: {
|
|
9666
|
+
path: "/sites/{siteId}/settings/layout",
|
|
9667
|
+
method: "GET",
|
|
9668
|
+
revalidate: 120,
|
|
9669
|
+
tags: ["site-{siteId}", "site-settings-{siteId}"],
|
|
9670
|
+
auth: "user",
|
|
9671
|
+
responseKind: "json"
|
|
9672
|
+
},
|
|
9673
|
+
updateSiteLayoutSettings: {
|
|
9674
|
+
path: "/sites/{siteId}/settings/layout",
|
|
9675
|
+
method: "POST",
|
|
9676
|
+
tags: ["site-{siteId}", "site-settings-{siteId}"],
|
|
9677
|
+
auth: "user",
|
|
9678
|
+
responseKind: "json"
|
|
9679
|
+
},
|
|
9680
|
+
getMaintenanceSettings: {
|
|
9681
|
+
path: "/sites/{siteId}/settings/maintenance",
|
|
9682
|
+
method: "GET",
|
|
9683
|
+
revalidate: 120,
|
|
9684
|
+
tags: ["site-{siteId}", "site-settings-{siteId}"],
|
|
9685
|
+
auth: "user",
|
|
9686
|
+
responseKind: "json"
|
|
9687
|
+
},
|
|
9688
|
+
updateMaintenanceSettings: {
|
|
9689
|
+
path: "/sites/{siteId}/settings/maintenance",
|
|
9690
|
+
method: "POST",
|
|
9691
|
+
tags: ["site-{siteId}", "site-settings-{siteId}"],
|
|
9692
|
+
auth: "user",
|
|
9693
|
+
responseKind: "json"
|
|
9694
|
+
},
|
|
9695
|
+
setHomepage: {
|
|
9696
|
+
path: "/sites/{siteId}/settings/homepage",
|
|
9697
|
+
method: "POST",
|
|
9698
|
+
tags: ["site-{siteId}", "site-homepage"],
|
|
9699
|
+
auth: "user",
|
|
9700
|
+
responseKind: "json"
|
|
9701
|
+
},
|
|
9702
|
+
listAccountDomains: {
|
|
9703
|
+
path: "/domains",
|
|
9704
|
+
method: "GET",
|
|
9705
|
+
tags: ["domains"],
|
|
9706
|
+
auth: "user",
|
|
9707
|
+
responseKind: "json"
|
|
9708
|
+
},
|
|
9709
|
+
searchDomains: {
|
|
9710
|
+
path: "/domains/search",
|
|
9711
|
+
method: "POST",
|
|
9712
|
+
tags: ["domains"],
|
|
9713
|
+
auth: "user",
|
|
9714
|
+
responseKind: "json"
|
|
9715
|
+
},
|
|
9716
|
+
registerDomain: {
|
|
9717
|
+
path: "/domains/register",
|
|
9718
|
+
method: "POST",
|
|
9719
|
+
tags: ["domains"],
|
|
9720
|
+
auth: "user",
|
|
9721
|
+
responseKind: "json"
|
|
9722
|
+
},
|
|
9723
|
+
assignDomain: {
|
|
9724
|
+
path: "/domains/{domainId}/assign",
|
|
9725
|
+
method: "POST",
|
|
9726
|
+
tags: ["domains", "domain-{domainId}"],
|
|
9727
|
+
auth: "user",
|
|
9728
|
+
responseKind: "json"
|
|
9729
|
+
},
|
|
9730
|
+
adminStartImpersonation: {
|
|
9731
|
+
path: "/admin/impersonation/start",
|
|
9732
|
+
method: "POST",
|
|
9733
|
+
tags: ["admin", "impersonation"],
|
|
9734
|
+
auth: "user",
|
|
9735
|
+
responseKind: "json"
|
|
9736
|
+
},
|
|
9737
|
+
adminStopImpersonation: {
|
|
9738
|
+
path: "/admin/impersonation/stop",
|
|
9739
|
+
method: "POST",
|
|
9740
|
+
tags: ["admin", "impersonation"],
|
|
9741
|
+
auth: "user",
|
|
9742
|
+
responseKind: "json"
|
|
9743
|
+
},
|
|
9744
|
+
adminAssignRole: {
|
|
9745
|
+
path: "/admin/roles/assign",
|
|
9746
|
+
method: "POST",
|
|
9747
|
+
tags: ["admin", "roles"],
|
|
9748
|
+
auth: "user",
|
|
9749
|
+
responseKind: "json"
|
|
9750
|
+
},
|
|
9751
|
+
adminRevokeRole: {
|
|
9752
|
+
path: "/admin/roles/revoke",
|
|
9753
|
+
method: "POST",
|
|
9754
|
+
tags: ["admin", "roles"],
|
|
9755
|
+
auth: "user",
|
|
9756
|
+
responseKind: "json"
|
|
9757
|
+
},
|
|
9758
|
+
adminChangePlan: {
|
|
9759
|
+
path: "/admin/billing/plan",
|
|
9760
|
+
method: "POST",
|
|
9761
|
+
tags: ["admin", "billing"],
|
|
9762
|
+
auth: "user",
|
|
9763
|
+
responseKind: "json"
|
|
9764
|
+
},
|
|
9765
|
+
changePlan: {
|
|
9766
|
+
path: "/billing/plan/change",
|
|
9767
|
+
method: "POST",
|
|
9768
|
+
tags: ["billing"],
|
|
9769
|
+
auth: "user",
|
|
9770
|
+
responseKind: "json"
|
|
9771
|
+
},
|
|
9772
|
+
mfaTotpEnroll: {
|
|
9773
|
+
path: "/auth/mfa/totp/enroll",
|
|
9774
|
+
method: "POST",
|
|
9775
|
+
tags: ["mfa"],
|
|
9776
|
+
auth: "user",
|
|
9777
|
+
responseKind: "json"
|
|
9778
|
+
},
|
|
9779
|
+
mfaTotpVerify: {
|
|
9780
|
+
path: "/auth/mfa/totp/verify",
|
|
9781
|
+
method: "POST",
|
|
9782
|
+
tags: ["mfa"],
|
|
9783
|
+
auth: "user",
|
|
9784
|
+
responseKind: "json"
|
|
9785
|
+
},
|
|
9786
|
+
mfaTotpActivate: {
|
|
9787
|
+
path: "/auth/mfa/totp/activate",
|
|
9788
|
+
method: "POST",
|
|
9789
|
+
tags: ["mfa"],
|
|
9790
|
+
auth: "user",
|
|
9791
|
+
responseKind: "json"
|
|
9792
|
+
},
|
|
9793
|
+
mfaDeleteFactor: {
|
|
9794
|
+
path: "/auth/mfa/factors/{factorId}",
|
|
9795
|
+
method: "DELETE",
|
|
9796
|
+
tags: ["mfa"],
|
|
9797
|
+
auth: "user",
|
|
9798
|
+
responseKind: "json"
|
|
9799
|
+
},
|
|
9800
|
+
mfaBackupCodesGet: {
|
|
9801
|
+
path: "/auth/mfa/backup-codes",
|
|
9802
|
+
method: "GET",
|
|
9803
|
+
tags: ["mfa"],
|
|
9804
|
+
auth: "user",
|
|
9805
|
+
responseKind: "json"
|
|
9806
|
+
},
|
|
9807
|
+
mfaBackupCodesRotate: {
|
|
9808
|
+
path: "/auth/mfa/backup-codes/rotate",
|
|
9809
|
+
method: "POST",
|
|
9810
|
+
tags: ["mfa"],
|
|
9811
|
+
auth: "user",
|
|
9812
|
+
responseKind: "json"
|
|
9813
|
+
},
|
|
9814
|
+
mfaPhoneEnroll: {
|
|
9815
|
+
path: "/auth/mfa/phone/enroll",
|
|
9816
|
+
method: "POST",
|
|
9817
|
+
tags: ["mfa"],
|
|
9818
|
+
auth: "user",
|
|
9819
|
+
responseKind: "json"
|
|
9820
|
+
},
|
|
9821
|
+
mfaPhoneChallenge: {
|
|
9822
|
+
path: "/auth/mfa/phone/challenge",
|
|
9823
|
+
method: "POST",
|
|
9824
|
+
tags: ["mfa"],
|
|
9825
|
+
auth: "user",
|
|
9826
|
+
responseKind: "json"
|
|
9827
|
+
},
|
|
9828
|
+
mfaPhoneVerify: {
|
|
9829
|
+
path: "/auth/mfa/phone/verify",
|
|
9830
|
+
method: "POST",
|
|
9831
|
+
tags: ["mfa"],
|
|
9832
|
+
auth: "user",
|
|
9833
|
+
responseKind: "json"
|
|
9834
|
+
},
|
|
9835
|
+
accountUpdatePassword: {
|
|
9836
|
+
path: "/account/password/update",
|
|
9837
|
+
method: "POST",
|
|
9838
|
+
tags: ["account"],
|
|
9839
|
+
auth: "user",
|
|
9840
|
+
responseKind: "json"
|
|
9841
|
+
},
|
|
9842
|
+
accountRevokeSessions: {
|
|
9843
|
+
path: "/account/sessions/revoke",
|
|
9844
|
+
method: "POST",
|
|
9845
|
+
tags: ["account"],
|
|
9846
|
+
auth: "user",
|
|
9847
|
+
responseKind: "json"
|
|
9848
|
+
},
|
|
9849
|
+
adminListInvites: {
|
|
9850
|
+
path: "/admin/invites",
|
|
9851
|
+
method: "GET",
|
|
9852
|
+
tags: ["admin", "invites"],
|
|
9853
|
+
auth: "user",
|
|
9854
|
+
responseKind: "json"
|
|
9855
|
+
},
|
|
9856
|
+
adminCreateInvite: {
|
|
9857
|
+
path: "/admin/invites",
|
|
9858
|
+
method: "POST",
|
|
9859
|
+
tags: ["admin", "invites"],
|
|
9860
|
+
auth: "user",
|
|
9861
|
+
responseKind: "json"
|
|
9862
|
+
},
|
|
9863
|
+
adminRevokeInvite: {
|
|
9864
|
+
path: "/admin/invites/{inviteId}",
|
|
9865
|
+
method: "DELETE",
|
|
9866
|
+
tags: ["admin", "invites"],
|
|
9867
|
+
auth: "user",
|
|
9868
|
+
responseKind: "json"
|
|
9869
|
+
},
|
|
9870
|
+
adminCreateUser: {
|
|
9871
|
+
path: "/admin/users",
|
|
9872
|
+
method: "POST",
|
|
9873
|
+
tags: ["admin", "users"],
|
|
9874
|
+
auth: "admin",
|
|
9875
|
+
responseKind: "json"
|
|
9876
|
+
},
|
|
9877
|
+
adminListAllowedDomains: {
|
|
9878
|
+
path: "/admin/allowed-domains",
|
|
9879
|
+
method: "GET",
|
|
9880
|
+
tags: ["admin", "allowed-domains"],
|
|
9881
|
+
auth: "user",
|
|
9882
|
+
responseKind: "json"
|
|
9883
|
+
},
|
|
9884
|
+
adminAddAllowedDomain: {
|
|
9885
|
+
path: "/admin/allowed-domains",
|
|
9886
|
+
method: "POST",
|
|
9887
|
+
tags: ["admin", "allowed-domains"],
|
|
9888
|
+
auth: "user",
|
|
9889
|
+
responseKind: "json"
|
|
9890
|
+
},
|
|
9891
|
+
adminDeleteAllowedDomain: {
|
|
9892
|
+
path: "/admin/allowed-domains/{domainId}",
|
|
9893
|
+
method: "DELETE",
|
|
9894
|
+
tags: ["admin", "allowed-domains"],
|
|
9895
|
+
auth: "user",
|
|
9896
|
+
responseKind: "json"
|
|
9897
|
+
},
|
|
9898
|
+
authAcceptInvite: {
|
|
9899
|
+
path: "/auth/invite/accept",
|
|
9900
|
+
method: "POST",
|
|
9901
|
+
tags: ["auth", "invite"],
|
|
9902
|
+
auth: "user",
|
|
9903
|
+
responseKind: "json"
|
|
9904
|
+
},
|
|
9905
|
+
acceptSiteInvitation: {
|
|
9906
|
+
path: "/sites/invitations/accept",
|
|
9907
|
+
method: "POST",
|
|
9908
|
+
tags: ["site-invitations"],
|
|
9909
|
+
auth: "user",
|
|
9910
|
+
responseKind: "json"
|
|
9911
|
+
},
|
|
9912
|
+
getNavigationMenus: {
|
|
9913
|
+
path: "/sites/{siteId}/navigation/menus",
|
|
9914
|
+
method: "GET",
|
|
9915
|
+
tags: ["site-{siteId}", "navigation"],
|
|
9916
|
+
auth: "user",
|
|
9917
|
+
responseKind: "json"
|
|
9918
|
+
},
|
|
9919
|
+
createNavigationMenu: {
|
|
9920
|
+
path: "/sites/{siteId}/navigation/menus",
|
|
9921
|
+
method: "POST",
|
|
9922
|
+
tags: ["site-{siteId}", "navigation"],
|
|
9923
|
+
auth: "user",
|
|
9924
|
+
responseKind: "json"
|
|
9925
|
+
},
|
|
9926
|
+
updateNavigationMenu: {
|
|
9927
|
+
path: "/sites/{siteId}/navigation/menus/{menuId}",
|
|
9928
|
+
method: "PATCH",
|
|
9929
|
+
tags: ["site-{siteId}", "navigation", "navigation-menu-{menuId}"],
|
|
9930
|
+
auth: "user",
|
|
9931
|
+
responseKind: "json"
|
|
9932
|
+
},
|
|
9933
|
+
deleteNavigationMenu: {
|
|
9934
|
+
path: "/sites/{siteId}/navigation/menus/{menuId}",
|
|
9935
|
+
method: "DELETE",
|
|
9936
|
+
tags: ["site-{siteId}", "navigation", "navigation-menu-{menuId}"],
|
|
9937
|
+
auth: "user",
|
|
9938
|
+
responseKind: "json"
|
|
9939
|
+
},
|
|
9940
|
+
createNavigationItem: {
|
|
9941
|
+
path: "/sites/{siteId}/navigation/menus/{menuId}/items",
|
|
9942
|
+
method: "POST",
|
|
9943
|
+
tags: ["site-{siteId}", "navigation", "navigation-menu-{menuId}"],
|
|
9944
|
+
auth: "user",
|
|
9945
|
+
responseKind: "json"
|
|
9946
|
+
},
|
|
9947
|
+
updateNavigationItem: {
|
|
9948
|
+
path: "/sites/{siteId}/navigation/menus/{menuId}/items/{itemId}",
|
|
9949
|
+
method: "PATCH",
|
|
9950
|
+
tags: ["site-{siteId}", "navigation", "navigation-menu-{menuId}", "navigation-item-{itemId}"],
|
|
9951
|
+
auth: "user",
|
|
9952
|
+
responseKind: "json"
|
|
9953
|
+
},
|
|
9954
|
+
deleteNavigationItem: {
|
|
9955
|
+
path: "/sites/{siteId}/navigation/menus/{menuId}/items/{itemId}",
|
|
9956
|
+
method: "DELETE",
|
|
9957
|
+
tags: ["site-{siteId}", "navigation", "navigation-menu-{menuId}", "navigation-item-{itemId}"],
|
|
9958
|
+
auth: "user",
|
|
9959
|
+
responseKind: "json"
|
|
9960
|
+
},
|
|
9961
|
+
reorderNavigationItems: {
|
|
9962
|
+
path: "/sites/{siteId}/navigation/menus/{menuId}/items/reorder",
|
|
9963
|
+
method: "POST",
|
|
9964
|
+
tags: ["site-{siteId}", "navigation", "navigation-menu-{menuId}"],
|
|
9965
|
+
auth: "user",
|
|
9966
|
+
responseKind: "json"
|
|
9967
|
+
},
|
|
9968
|
+
getRoutableContent: {
|
|
9969
|
+
path: "/sites/{siteId}/routable-content",
|
|
9970
|
+
method: "GET",
|
|
9971
|
+
revalidate: 60,
|
|
9972
|
+
tags: ["site-{siteId}", "routable-content-{siteId}"],
|
|
9973
|
+
auth: "user",
|
|
9974
|
+
responseKind: "json"
|
|
9975
|
+
},
|
|
9976
|
+
// Public routable content for SDK SSG
|
|
9977
|
+
getPublicRoutableContent: {
|
|
9978
|
+
path: "/public/sites/{siteId}/routable-content",
|
|
9979
|
+
method: "GET",
|
|
9980
|
+
revalidate: 60,
|
|
9981
|
+
tags: ["site-{siteId}", "routable-content-{siteId}"],
|
|
9982
|
+
auth: "public",
|
|
9983
|
+
responseKind: "json"
|
|
9984
|
+
},
|
|
9985
|
+
// Generic public content preview (preferred)
|
|
9986
|
+
getPublishedEntryPreview: {
|
|
9987
|
+
path: "/public/content/{siteId}/{type}/{slug}/preview",
|
|
9988
|
+
method: "GET",
|
|
9989
|
+
revalidate: 60,
|
|
9990
|
+
tags: ["content-{siteId}-{type}-{slug}"],
|
|
9991
|
+
auth: "public",
|
|
9992
|
+
responseKind: "json"
|
|
9993
|
+
},
|
|
9994
|
+
listPublishedEntries: {
|
|
9995
|
+
path: "/public/content/{siteId}/{type}/entries",
|
|
9996
|
+
method: "GET",
|
|
9997
|
+
revalidate: 60,
|
|
9998
|
+
tags: ["content-{siteId}-{type}"],
|
|
9999
|
+
auth: "public",
|
|
10000
|
+
responseKind: "json"
|
|
10001
|
+
},
|
|
10002
|
+
getPublishedPostPreview: {
|
|
10003
|
+
path: "/public/posts/{siteId}/{slug}/preview",
|
|
10004
|
+
method: "GET",
|
|
10005
|
+
revalidate: 60,
|
|
10006
|
+
tags: ["blog-post:{siteId}:{slug}"],
|
|
10007
|
+
auth: "public",
|
|
10008
|
+
responseKind: "json"
|
|
10009
|
+
},
|
|
10010
|
+
proposalsSelect: {
|
|
10011
|
+
path: "/proposals/select",
|
|
10012
|
+
method: "POST",
|
|
10013
|
+
tags: ["proposal", "site"],
|
|
10014
|
+
auth: "user",
|
|
10015
|
+
responseKind: "json"
|
|
10016
|
+
},
|
|
10017
|
+
createTheme: {
|
|
10018
|
+
path: "/ai/chat/create-theme",
|
|
10019
|
+
method: "POST",
|
|
10020
|
+
revalidate: 60,
|
|
10021
|
+
// 1 minute cache for theme creation to avoid duplicate requests
|
|
10022
|
+
tags: ["theme", "ai-theme"],
|
|
10023
|
+
auth: "user",
|
|
10024
|
+
responseKind: "json"
|
|
10025
|
+
},
|
|
10026
|
+
generateThemes: {
|
|
10027
|
+
path: "/theme/generate",
|
|
10028
|
+
method: "POST",
|
|
10029
|
+
tags: ["theme"],
|
|
10030
|
+
auth: "user",
|
|
10031
|
+
responseKind: "json"
|
|
10032
|
+
},
|
|
10033
|
+
extractThemeFromInspiration: {
|
|
10034
|
+
path: "/theme/extract-from-inspiration",
|
|
10035
|
+
method: "POST",
|
|
10036
|
+
tags: ["theme", "preferences"],
|
|
10037
|
+
auth: "user",
|
|
10038
|
+
responseKind: "json"
|
|
10039
|
+
},
|
|
10040
|
+
saveSiteTheme: {
|
|
10041
|
+
path: "/sites/{siteId}/theme/save",
|
|
10042
|
+
method: "POST",
|
|
10043
|
+
tags: ["site-{siteId}", "theme"],
|
|
10044
|
+
auth: "user",
|
|
10045
|
+
responseKind: "json"
|
|
10046
|
+
},
|
|
10047
|
+
uploadSiteLogo: {
|
|
10048
|
+
path: "/storage/upload-site-logo",
|
|
10049
|
+
method: "POST",
|
|
10050
|
+
tags: ["site", "logo"],
|
|
10051
|
+
auth: "user",
|
|
10052
|
+
responseKind: "json"
|
|
10053
|
+
},
|
|
10054
|
+
upsertThemePreferences: {
|
|
10055
|
+
path: "/theme-preferences/upsert",
|
|
10056
|
+
method: "POST",
|
|
10057
|
+
tags: ["theme", "preferences"],
|
|
10058
|
+
auth: "user",
|
|
10059
|
+
responseKind: "json"
|
|
10060
|
+
},
|
|
10061
|
+
finalizeSite: {
|
|
10062
|
+
path: "/sites/finalize",
|
|
10063
|
+
method: "POST",
|
|
10064
|
+
tags: ["site"],
|
|
10065
|
+
auth: "user",
|
|
10066
|
+
responseKind: "json"
|
|
10067
|
+
},
|
|
10068
|
+
instagramUploadZip: {
|
|
10069
|
+
path: "/api/instagram/upload-zip",
|
|
10070
|
+
method: "POST",
|
|
10071
|
+
tags: ["instagram-import"],
|
|
10072
|
+
auth: "user",
|
|
10073
|
+
responseKind: "json"
|
|
10074
|
+
},
|
|
10075
|
+
getAnalyticsReport: {
|
|
10076
|
+
path: "/sites/{siteId}/analytics/report",
|
|
10077
|
+
method: "GET",
|
|
10078
|
+
revalidate: 300,
|
|
10079
|
+
tags: ["site-{siteId}", "analytics-{siteId}"],
|
|
10080
|
+
auth: "user",
|
|
10081
|
+
responseKind: "json"
|
|
10082
|
+
},
|
|
10083
|
+
getSeoOverview: {
|
|
10084
|
+
path: "/sites/{siteId}/seo/overview",
|
|
10085
|
+
method: "GET",
|
|
10086
|
+
revalidate: 300,
|
|
10087
|
+
tags: ["site-{siteId}", "seo-overview-{siteId}"],
|
|
10088
|
+
auth: "user",
|
|
10089
|
+
responseKind: "json"
|
|
10090
|
+
},
|
|
10091
|
+
getSeoPages: {
|
|
10092
|
+
path: "/sites/{siteId}/seo/pages",
|
|
10093
|
+
method: "GET",
|
|
10094
|
+
revalidate: 300,
|
|
10095
|
+
tags: ["site-{siteId}", "seo-pages-{siteId}"],
|
|
10096
|
+
auth: "user",
|
|
10097
|
+
responseKind: "json"
|
|
10098
|
+
},
|
|
10099
|
+
getSeoQueries: {
|
|
10100
|
+
path: "/sites/{siteId}/seo/queries",
|
|
10101
|
+
method: "GET",
|
|
10102
|
+
revalidate: 300,
|
|
10103
|
+
tags: ["site-{siteId}", "seo-queries-{siteId}"],
|
|
10104
|
+
auth: "user",
|
|
10105
|
+
responseKind: "json"
|
|
10106
|
+
},
|
|
10107
|
+
getPerformanceOverview: {
|
|
10108
|
+
path: "/sites/{siteId}/performance/overview",
|
|
10109
|
+
method: "GET",
|
|
10110
|
+
revalidate: 300,
|
|
10111
|
+
tags: ["site-{siteId}", "performance-overview-{siteId}"],
|
|
10112
|
+
auth: "user",
|
|
10113
|
+
responseKind: "json"
|
|
10114
|
+
},
|
|
10115
|
+
createMediaAsset: {
|
|
10116
|
+
path: "/media",
|
|
10117
|
+
method: "POST",
|
|
10118
|
+
tags: ["media"],
|
|
10119
|
+
auth: "user",
|
|
10120
|
+
responseKind: "json"
|
|
10121
|
+
},
|
|
10122
|
+
mediaList: {
|
|
10123
|
+
path: "/media",
|
|
10124
|
+
method: "GET",
|
|
10125
|
+
tags: ["media"],
|
|
10126
|
+
auth: "user",
|
|
10127
|
+
responseKind: "json"
|
|
10128
|
+
},
|
|
10129
|
+
mediaGet: {
|
|
10130
|
+
path: "/media/{assetId}",
|
|
10131
|
+
method: "GET",
|
|
10132
|
+
tags: ["media", "media-{assetId}"],
|
|
10133
|
+
auth: "user",
|
|
10134
|
+
responseKind: "json"
|
|
10135
|
+
},
|
|
10136
|
+
mediaUpdate: {
|
|
10137
|
+
path: "/media/{assetId}",
|
|
10138
|
+
method: "PATCH",
|
|
10139
|
+
tags: ["media", "media-{assetId}"],
|
|
10140
|
+
auth: "user",
|
|
10141
|
+
responseKind: "json"
|
|
10142
|
+
},
|
|
10143
|
+
mediaDelete: {
|
|
10144
|
+
path: "/media/{assetId}",
|
|
10145
|
+
method: "DELETE",
|
|
10146
|
+
tags: ["media", "media-{assetId}"],
|
|
10147
|
+
auth: "user",
|
|
10148
|
+
responseKind: "void"
|
|
10149
|
+
},
|
|
10150
|
+
mediaBulkDelete: {
|
|
10151
|
+
path: "/media/bulk-delete",
|
|
10152
|
+
method: "POST",
|
|
10153
|
+
tags: ["media"],
|
|
10154
|
+
auth: "user",
|
|
10155
|
+
responseKind: "json"
|
|
10156
|
+
},
|
|
10157
|
+
mediaGetSignedUrl: {
|
|
10158
|
+
path: "/media/{assetId}/signed-url",
|
|
10159
|
+
method: "GET",
|
|
10160
|
+
tags: ["media", "media-{assetId}"],
|
|
10161
|
+
auth: "user",
|
|
10162
|
+
responseKind: "json"
|
|
10163
|
+
},
|
|
10164
|
+
mediaUpload: {
|
|
10165
|
+
path: "/media/upload",
|
|
10166
|
+
method: "POST",
|
|
10167
|
+
tags: ["media"],
|
|
10168
|
+
auth: "user",
|
|
10169
|
+
responseKind: "json"
|
|
10170
|
+
},
|
|
10171
|
+
getMediaLabels: {
|
|
10172
|
+
path: "/media/labels",
|
|
10173
|
+
method: "GET",
|
|
10174
|
+
tags: ["media", "media-labels"],
|
|
10175
|
+
auth: "user",
|
|
10176
|
+
responseKind: "json"
|
|
10177
|
+
},
|
|
10178
|
+
getMediaSettings: {
|
|
10179
|
+
path: "/media/settings",
|
|
10180
|
+
method: "GET",
|
|
10181
|
+
tags: ["media-settings"],
|
|
10182
|
+
auth: "user",
|
|
10183
|
+
responseKind: "json"
|
|
10184
|
+
},
|
|
10185
|
+
updateMediaSettings: {
|
|
10186
|
+
path: "/media/settings",
|
|
10187
|
+
method: "POST",
|
|
10188
|
+
tags: ["media-settings"],
|
|
10189
|
+
auth: "user",
|
|
10190
|
+
responseKind: "json"
|
|
10191
|
+
},
|
|
10192
|
+
// Media endpoints
|
|
10193
|
+
mediaSearch: {
|
|
10194
|
+
path: "/media/search",
|
|
10195
|
+
method: "POST",
|
|
10196
|
+
tags: ["media-search"],
|
|
10197
|
+
auth: "user",
|
|
10198
|
+
responseKind: "json"
|
|
10199
|
+
},
|
|
10200
|
+
classifyMediaAsset: {
|
|
10201
|
+
path: "/media/{assetId}/classify",
|
|
10202
|
+
method: "POST",
|
|
10203
|
+
tags: ["media", "media-{assetId}"],
|
|
10204
|
+
auth: "user",
|
|
10205
|
+
responseKind: "json"
|
|
10206
|
+
},
|
|
10207
|
+
classifyMediaBatch: {
|
|
10208
|
+
path: "/media/classify",
|
|
10209
|
+
method: "POST",
|
|
10210
|
+
tags: ["media"],
|
|
10211
|
+
auth: "user",
|
|
10212
|
+
responseKind: "json"
|
|
10213
|
+
},
|
|
10214
|
+
mediaJobsStatus: {
|
|
10215
|
+
path: "/media/jobs/status",
|
|
10216
|
+
method: "GET",
|
|
10217
|
+
tags: ["media"],
|
|
10218
|
+
auth: "user",
|
|
10219
|
+
responseKind: "json"
|
|
10220
|
+
},
|
|
10221
|
+
enqueueMediaClassifyJob: {
|
|
10222
|
+
path: "/media/jobs",
|
|
10223
|
+
method: "POST",
|
|
10224
|
+
tags: ["media"],
|
|
10225
|
+
auth: "user",
|
|
10226
|
+
responseKind: "json"
|
|
10227
|
+
},
|
|
10228
|
+
runMediaClassifyJob: {
|
|
10229
|
+
path: "/media/jobs/run",
|
|
10230
|
+
method: "POST",
|
|
10231
|
+
tags: ["media"],
|
|
10232
|
+
auth: "user",
|
|
10233
|
+
responseKind: "json"
|
|
10234
|
+
},
|
|
10235
|
+
runAllMediaClassifyJobs: {
|
|
10236
|
+
path: "/media/jobs/run-all",
|
|
10237
|
+
method: "POST",
|
|
10238
|
+
tags: ["media"],
|
|
10239
|
+
auth: "user",
|
|
10240
|
+
responseKind: "json"
|
|
10241
|
+
},
|
|
10242
|
+
initSiteContent: {
|
|
10243
|
+
path: "/sites/{siteId}/content/init",
|
|
10244
|
+
method: "POST",
|
|
10245
|
+
tags: ["site", "content"],
|
|
10246
|
+
auth: "user",
|
|
10247
|
+
responseKind: "json"
|
|
10248
|
+
},
|
|
10249
|
+
updateBlockContent: {
|
|
10250
|
+
path: "/blocks/{blockId}/content",
|
|
10251
|
+
method: "POST",
|
|
10252
|
+
tags: ["block", "block-{blockId}", "content"],
|
|
10253
|
+
auth: "user",
|
|
10254
|
+
responseKind: "json"
|
|
10255
|
+
},
|
|
10256
|
+
saveBlockContent: {
|
|
10257
|
+
path: "/blocks/{blockId}/content",
|
|
10258
|
+
method: "POST",
|
|
10259
|
+
tags: ["block", "block-{blockId}", "content"],
|
|
10260
|
+
auth: "user",
|
|
10261
|
+
responseKind: "json"
|
|
10262
|
+
},
|
|
10263
|
+
createBlock: {
|
|
10264
|
+
path: "/sites/{siteId}/pages/{pageId}/blocks",
|
|
10265
|
+
method: "POST",
|
|
10266
|
+
tags: ["site-{siteId}", "page-{pageId}", "blocks"],
|
|
10267
|
+
auth: "user",
|
|
10268
|
+
responseKind: "json"
|
|
10269
|
+
},
|
|
10270
|
+
reorderBlocks: {
|
|
10271
|
+
path: "/sites/{siteId}/pages/{pageId}/blocks/reorder",
|
|
10272
|
+
method: "POST",
|
|
10273
|
+
tags: ["site-{siteId}", "page-{pageId}", "blocks"],
|
|
10274
|
+
auth: "user",
|
|
10275
|
+
responseKind: "json"
|
|
10276
|
+
},
|
|
10277
|
+
deleteBlock: {
|
|
10278
|
+
path: "/sites/{siteId}/pages/{pageId}/blocks/{blockId}",
|
|
10279
|
+
method: "DELETE",
|
|
10280
|
+
tags: ["site-{siteId}", "page-{pageId}", "blocks"],
|
|
10281
|
+
auth: "user",
|
|
10282
|
+
responseKind: "json"
|
|
10283
|
+
},
|
|
10284
|
+
listBlocks: {
|
|
10285
|
+
path: "/sites/{siteId}/pages/{pageId}/blocks",
|
|
10286
|
+
method: "GET",
|
|
10287
|
+
tags: ["site-{siteId}", "page-{pageId}", "blocks"],
|
|
10288
|
+
auth: "user",
|
|
10289
|
+
responseKind: "json"
|
|
10290
|
+
},
|
|
10291
|
+
getBlockContent: {
|
|
10292
|
+
path: "/blocks/{blockId}/content",
|
|
10293
|
+
method: "GET",
|
|
10294
|
+
tags: ["block-{blockId}", "content"],
|
|
10295
|
+
auth: "user",
|
|
10296
|
+
responseKind: "json"
|
|
10297
|
+
},
|
|
10298
|
+
// DEPRECATED: Use getSite with ?id={id} instead
|
|
10299
|
+
getSiteById: {
|
|
10300
|
+
path: "/sites/by-id/{id}",
|
|
10301
|
+
method: "GET",
|
|
10302
|
+
revalidate: 900,
|
|
10303
|
+
// 15 minutes
|
|
10304
|
+
tags: ["site-{id}"],
|
|
10305
|
+
auth: "user",
|
|
10306
|
+
responseKind: "json"
|
|
10307
|
+
},
|
|
10308
|
+
// Page data endpoints
|
|
10309
|
+
getPageById: {
|
|
10310
|
+
path: "/sites/{siteId}/pages/{pageId}",
|
|
10311
|
+
method: "GET",
|
|
10312
|
+
revalidate: 900,
|
|
10313
|
+
// 15 minutes
|
|
10314
|
+
tags: ["site-{siteId}", "page-{pageId}"],
|
|
10315
|
+
auth: "user",
|
|
10316
|
+
responseKind: "json"
|
|
10317
|
+
},
|
|
10318
|
+
getContentByPath: {
|
|
10319
|
+
path: "/sites/{siteId}/pages",
|
|
10320
|
+
method: "GET",
|
|
10321
|
+
tags: ["site-{siteId}", "routable-content-{siteId}"],
|
|
10322
|
+
auth: "public",
|
|
10323
|
+
responseKind: "json"
|
|
10324
|
+
},
|
|
10325
|
+
getPageByPath: {
|
|
10326
|
+
path: "/sites/{siteId}/pages",
|
|
10327
|
+
method: "GET",
|
|
10328
|
+
tags: ["site-{siteId}"],
|
|
10329
|
+
auth: "user",
|
|
10330
|
+
responseKind: "json"
|
|
10331
|
+
},
|
|
10332
|
+
// Forms CRUD
|
|
10333
|
+
listForms: {
|
|
10334
|
+
path: "/sites/{siteId}/forms",
|
|
10335
|
+
method: "GET",
|
|
10336
|
+
tags: ["site-{siteId}", "forms"],
|
|
10337
|
+
auth: "user",
|
|
10338
|
+
responseKind: "json"
|
|
10339
|
+
},
|
|
10340
|
+
listBookingForms: {
|
|
10341
|
+
path: "/sites/{siteId}/bookings/forms",
|
|
10342
|
+
method: "GET",
|
|
10343
|
+
tags: ["site-{siteId}", "forms"],
|
|
10344
|
+
auth: "user",
|
|
10345
|
+
responseKind: "json"
|
|
10346
|
+
},
|
|
10347
|
+
createForm: {
|
|
10348
|
+
path: "/sites/{siteId}/forms",
|
|
10349
|
+
method: "POST",
|
|
10350
|
+
tags: ["site-{siteId}", "forms"],
|
|
10351
|
+
auth: "user",
|
|
10352
|
+
responseKind: "json"
|
|
10353
|
+
},
|
|
10354
|
+
updateForm: {
|
|
10355
|
+
path: "/sites/{siteId}/forms/{slug}",
|
|
10356
|
+
method: "PATCH",
|
|
10357
|
+
tags: ["site-{siteId}", "forms", "form-{slug}"],
|
|
10358
|
+
auth: "user",
|
|
10359
|
+
responseKind: "json"
|
|
10360
|
+
},
|
|
10361
|
+
deleteForm: {
|
|
10362
|
+
path: "/sites/{siteId}/forms/{slug}",
|
|
10363
|
+
method: "DELETE",
|
|
10364
|
+
tags: ["site-{siteId}", "forms", "form-{slug}"],
|
|
10365
|
+
auth: "user",
|
|
10366
|
+
responseKind: "json"
|
|
10367
|
+
},
|
|
10368
|
+
listFormSubmissions: {
|
|
10369
|
+
path: "/sites/{siteId}/forms/{slug}/submissions",
|
|
10370
|
+
method: "GET",
|
|
10371
|
+
revalidate: 30,
|
|
10372
|
+
tags: ["site-{siteId}", "form-{slug}", "form-submissions-{slug}"],
|
|
10373
|
+
auth: "user",
|
|
10374
|
+
responseKind: "json"
|
|
10375
|
+
},
|
|
10376
|
+
// Public submit
|
|
10377
|
+
submitForm: {
|
|
10378
|
+
path: "/forms/submit",
|
|
10379
|
+
method: "POST",
|
|
10380
|
+
tags: ["forms-submit"],
|
|
10381
|
+
auth: "public",
|
|
10382
|
+
responseKind: "json"
|
|
10383
|
+
},
|
|
10384
|
+
// Public forms
|
|
10385
|
+
getPublicFormById: {
|
|
10386
|
+
path: "/public/forms/{formId}",
|
|
10387
|
+
method: "GET",
|
|
10388
|
+
revalidate: 60,
|
|
10389
|
+
tags: ["form-{formId}"],
|
|
10390
|
+
auth: "public",
|
|
10391
|
+
responseKind: "json"
|
|
10392
|
+
},
|
|
10393
|
+
// Public booking services
|
|
10394
|
+
getPublicBookingServices: {
|
|
10395
|
+
path: "/public/bookings/services",
|
|
10396
|
+
method: "GET",
|
|
10397
|
+
revalidate: 60,
|
|
10398
|
+
tags: ["site-{siteId}"],
|
|
10399
|
+
auth: "public",
|
|
10400
|
+
responseKind: "json"
|
|
10401
|
+
},
|
|
10402
|
+
devToolsImpersonateAdmin: {
|
|
10403
|
+
path: "/dev-tools/impersonate/admin",
|
|
10404
|
+
method: "POST",
|
|
10405
|
+
auth: "admin",
|
|
10406
|
+
responseKind: "json"
|
|
10407
|
+
},
|
|
10408
|
+
devToolsImpersonateRandom: {
|
|
10409
|
+
path: "/dev-tools/impersonate/random",
|
|
10410
|
+
method: "POST",
|
|
10411
|
+
auth: "admin",
|
|
10412
|
+
responseKind: "json"
|
|
10413
|
+
},
|
|
10414
|
+
devToolsSeedDemoData: {
|
|
10415
|
+
path: "/dev-tools/seed",
|
|
10416
|
+
method: "POST",
|
|
10417
|
+
auth: "admin",
|
|
10418
|
+
responseKind: "json"
|
|
10419
|
+
},
|
|
10420
|
+
// Public analytics collection endpoint
|
|
10421
|
+
analyticsCollect: {
|
|
10422
|
+
path: "/api/analytics/collect",
|
|
10423
|
+
method: "POST",
|
|
10424
|
+
auth: "public",
|
|
10425
|
+
responseKind: "json"
|
|
10426
|
+
},
|
|
10427
|
+
// Public events for event calendar block
|
|
10428
|
+
listPublicEvents: {
|
|
10429
|
+
path: "/public/sites/{siteId}/events",
|
|
10430
|
+
method: "GET",
|
|
10431
|
+
revalidate: 60,
|
|
10432
|
+
tags: ["public-events-{siteId}"],
|
|
10433
|
+
auth: "public",
|
|
10434
|
+
responseKind: "json"
|
|
10435
|
+
},
|
|
10436
|
+
// Resolve event occurrence by URL segment (date or UUID)
|
|
10437
|
+
resolveEventOccurrence: {
|
|
10438
|
+
path: "/public/sites/{siteId}/events/occurrences/resolve",
|
|
10439
|
+
method: "GET",
|
|
10440
|
+
revalidate: 60,
|
|
10441
|
+
tags: ["public-events-{siteId}", "event-occurrence"],
|
|
10442
|
+
auth: "public",
|
|
10443
|
+
responseKind: "json"
|
|
10444
|
+
},
|
|
10445
|
+
// Public event registration
|
|
10446
|
+
registerForEvent: {
|
|
10447
|
+
path: "/public/sites/{siteId}/events/register",
|
|
10448
|
+
method: "POST",
|
|
10449
|
+
tags: ["public-events-{siteId}", "event-registration"],
|
|
10450
|
+
auth: "public",
|
|
10451
|
+
responseKind: "json"
|
|
10452
|
+
},
|
|
10453
|
+
// Content Types CRUD
|
|
10454
|
+
listSiteContentTypes: {
|
|
10455
|
+
path: "/sites/{siteId}/content-types",
|
|
10456
|
+
method: "GET",
|
|
10457
|
+
revalidate: 60,
|
|
10458
|
+
tags: ["site-{siteId}", "content-types-{siteId}"],
|
|
10459
|
+
auth: "user",
|
|
10460
|
+
responseKind: "json"
|
|
10461
|
+
},
|
|
10462
|
+
getContentType: {
|
|
10463
|
+
path: "/sites/{siteId}/content-types/by-id/{typeId}",
|
|
10464
|
+
method: "GET",
|
|
10465
|
+
revalidate: 60,
|
|
10466
|
+
tags: ["site-{siteId}", "content-type-{typeId}"],
|
|
10467
|
+
auth: "user",
|
|
10468
|
+
responseKind: "json"
|
|
10469
|
+
},
|
|
10470
|
+
createContentType: {
|
|
10471
|
+
path: "/sites/{siteId}/content-types",
|
|
10472
|
+
method: "POST",
|
|
10473
|
+
tags: ["site-{siteId}", "content-types-{siteId}"],
|
|
10474
|
+
auth: "user",
|
|
10475
|
+
responseKind: "json"
|
|
10476
|
+
},
|
|
10477
|
+
updateContentType: {
|
|
10478
|
+
path: "/sites/{siteId}/content-types/by-id/{typeId}",
|
|
10479
|
+
method: "PATCH",
|
|
10480
|
+
tags: ["site-{siteId}", "content-type-{typeId}", "content-types-{siteId}"],
|
|
10481
|
+
auth: "user",
|
|
10482
|
+
responseKind: "json"
|
|
10483
|
+
},
|
|
10484
|
+
deleteContentType: {
|
|
10485
|
+
path: "/sites/{siteId}/content-types/by-id/{typeId}",
|
|
10486
|
+
method: "DELETE",
|
|
10487
|
+
tags: ["site-{siteId}", "content-type-{typeId}", "content-types-{sideId}"],
|
|
10488
|
+
auth: "user",
|
|
10489
|
+
responseKind: "json"
|
|
10490
|
+
},
|
|
10491
|
+
duplicateContentType: {
|
|
10492
|
+
path: "/sites/{siteId}/content-types/by-id/{typeId}/duplicate",
|
|
10493
|
+
method: "POST",
|
|
10494
|
+
tags: ["site-{siteId}", "content-type-{typeId}", "content-types-{siteId}"],
|
|
10495
|
+
auth: "user",
|
|
10496
|
+
responseKind: "json"
|
|
10497
|
+
},
|
|
10498
|
+
// Admin site creation
|
|
10499
|
+
adminCreateSite: {
|
|
10500
|
+
path: "/admin/sites",
|
|
10501
|
+
method: "POST",
|
|
10502
|
+
tags: ["admin", "sites"],
|
|
10503
|
+
auth: "admin",
|
|
10504
|
+
responseKind: "json"
|
|
10505
|
+
},
|
|
10506
|
+
// SDK Config
|
|
10507
|
+
refreshSdkConfig: {
|
|
10508
|
+
path: "/sites/{siteId}/refresh-sdk-config",
|
|
10509
|
+
method: "POST",
|
|
10510
|
+
tags: ["site-{siteId}", "sdk-config"],
|
|
10511
|
+
auth: "user",
|
|
10512
|
+
responseKind: "json"
|
|
10513
|
+
},
|
|
10514
|
+
// Stripe Connect - Site billing
|
|
10515
|
+
stripeConnectAuthorize: {
|
|
10516
|
+
path: "/sites/{siteId}/billing/connect/authorize",
|
|
10517
|
+
method: "POST",
|
|
10518
|
+
tags: ["site-{siteId}", "stripe-connect"],
|
|
10519
|
+
auth: "user",
|
|
10520
|
+
responseKind: "json"
|
|
10521
|
+
},
|
|
10522
|
+
stripeConnectStatus: {
|
|
10523
|
+
path: "/sites/{siteId}/billing/connect/status",
|
|
10524
|
+
method: "GET",
|
|
10525
|
+
tags: ["site-{siteId}", "stripe-connect"],
|
|
10526
|
+
auth: "user",
|
|
10527
|
+
responseKind: "json"
|
|
10528
|
+
},
|
|
10529
|
+
stripeConnectDisconnect: {
|
|
10530
|
+
path: "/sites/{siteId}/billing/connect/disconnect",
|
|
10531
|
+
method: "DELETE",
|
|
10532
|
+
tags: ["site-{siteId}", "stripe-connect"],
|
|
10533
|
+
auth: "user",
|
|
10534
|
+
responseKind: "json"
|
|
10535
|
+
},
|
|
10536
|
+
// Backup
|
|
10537
|
+
importSiteBackup: {
|
|
10538
|
+
path: "/sites/{siteId}/backup/import",
|
|
10539
|
+
method: "POST",
|
|
10540
|
+
tags: ["site-{siteId}", "backup"],
|
|
10541
|
+
auth: "user",
|
|
10542
|
+
responseKind: "json"
|
|
10543
|
+
},
|
|
10544
|
+
previewBackup: {
|
|
10545
|
+
path: "/backup/preview",
|
|
10546
|
+
method: "POST",
|
|
10547
|
+
tags: ["backup"],
|
|
10548
|
+
auth: "user",
|
|
10549
|
+
responseKind: "json"
|
|
10550
|
+
},
|
|
10551
|
+
importBackupAsNewSite: {
|
|
10552
|
+
path: "/sites/backup/import-as-new",
|
|
10553
|
+
method: "POST",
|
|
10554
|
+
tags: ["site", "backup"],
|
|
10555
|
+
auth: "user",
|
|
10556
|
+
responseKind: "json"
|
|
10557
|
+
},
|
|
10558
|
+
// Admin billing price overrides
|
|
10559
|
+
adminGetPriceOverride: {
|
|
10560
|
+
path: "/admin/billing/price-override",
|
|
10561
|
+
method: "GET",
|
|
10562
|
+
tags: ["admin", "billing", "price-override"],
|
|
10563
|
+
auth: "admin",
|
|
10564
|
+
responseKind: "json"
|
|
10565
|
+
},
|
|
10566
|
+
adminUpsertPriceOverride: {
|
|
10567
|
+
path: "/admin/billing/price-override",
|
|
10568
|
+
method: "POST",
|
|
10569
|
+
tags: ["admin", "billing", "price-override"],
|
|
10570
|
+
auth: "admin",
|
|
10571
|
+
responseKind: "json"
|
|
10572
|
+
},
|
|
10573
|
+
adminDeletePriceOverride: {
|
|
10574
|
+
path: "/admin/billing/price-override",
|
|
10575
|
+
method: "DELETE",
|
|
10576
|
+
tags: ["admin", "billing", "price-override"],
|
|
10577
|
+
auth: "admin",
|
|
10578
|
+
responseKind: "json"
|
|
10579
|
+
}
|
|
10580
|
+
};
|
|
10581
|
+
var API_ENDPOINTS = ENDPOINT_DEFINITIONS;
|
|
10582
|
+
|
|
10583
|
+
// ../api/src/url.ts
|
|
10584
|
+
function getCmsApiUrl() {
|
|
10585
|
+
if (typeof window !== "undefined") {
|
|
10586
|
+
return "/api";
|
|
10587
|
+
}
|
|
10588
|
+
const internalUrl = process.env.CMS_API_URL;
|
|
10589
|
+
if (internalUrl) {
|
|
10590
|
+
return internalUrl.replace(/\/$/, "");
|
|
10591
|
+
}
|
|
10592
|
+
const dashboardUrl = process.env.NEXT_PUBLIC_DASHBOARD_URL;
|
|
10593
|
+
if (dashboardUrl) {
|
|
10594
|
+
const base = dashboardUrl.replace(/\/$/, "");
|
|
10595
|
+
return `${base}/api`;
|
|
10596
|
+
}
|
|
10597
|
+
const legacyApiUrl = process.env.NEXT_PUBLIC_CMS_API_URL;
|
|
10598
|
+
if (legacyApiUrl) {
|
|
10599
|
+
return legacyApiUrl.replace(/\/$/, "");
|
|
10600
|
+
}
|
|
10601
|
+
throw new Error(
|
|
10602
|
+
"NEXT_PUBLIC_DASHBOARD_URL is not configured. Set it to your dashboard URL (e.g., http://dashboard.local:4000)"
|
|
10603
|
+
);
|
|
10604
|
+
}
|
|
10605
|
+
function resolveApiBaseUrl() {
|
|
10606
|
+
return getCmsApiUrl();
|
|
10607
|
+
}
|
|
10608
|
+
|
|
10609
|
+
// ../api/src/request.ts
|
|
10610
|
+
var revalidateTag = null;
|
|
10611
|
+
if (typeof window === "undefined") {
|
|
10612
|
+
try {
|
|
10613
|
+
const dynamicRequire = new Function("modulePath", "return require(modulePath)");
|
|
10614
|
+
const nextCache = dynamicRequire("next/cache");
|
|
10615
|
+
revalidateTag = nextCache.revalidateTag ?? null;
|
|
10616
|
+
} catch {
|
|
10617
|
+
}
|
|
10618
|
+
}
|
|
10619
|
+
var sdkVersion;
|
|
10620
|
+
function generateRequestId() {
|
|
10621
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
10622
|
+
return crypto.randomUUID();
|
|
10623
|
+
}
|
|
10624
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
10625
|
+
const r = Math.random() * 16 | 0;
|
|
10626
|
+
const v = c === "x" ? r : r & 3 | 8;
|
|
10627
|
+
return v.toString(16);
|
|
10628
|
+
});
|
|
10629
|
+
}
|
|
10630
|
+
function setSdkVersion(version) {
|
|
10631
|
+
sdkVersion = version;
|
|
10632
|
+
}
|
|
10633
|
+
var ApiRequestError = class extends Error {
|
|
10634
|
+
constructor(message, options) {
|
|
10635
|
+
super(message);
|
|
10636
|
+
this.name = "ApiRequestError";
|
|
10637
|
+
this.endpoint = options.endpoint;
|
|
10638
|
+
this.status = options.status;
|
|
10639
|
+
this.method = options.method;
|
|
10640
|
+
this.auth = options.auth;
|
|
10641
|
+
this.requestId = options.requestId;
|
|
10642
|
+
this.body = options.body;
|
|
10643
|
+
this.cause = options.cause;
|
|
10644
|
+
this.errorCode = options.errorCode;
|
|
10645
|
+
this.retryAfterMs = options.retryAfterMs;
|
|
10646
|
+
}
|
|
10647
|
+
};
|
|
10648
|
+
function parseRetryAfterHeader(headerValue) {
|
|
10649
|
+
if (!headerValue) return void 0;
|
|
10650
|
+
if (/^\d+$/.test(headerValue)) {
|
|
10651
|
+
const seconds = parseInt(headerValue, 10);
|
|
10652
|
+
return seconds * 1e3;
|
|
10653
|
+
}
|
|
10654
|
+
const date = new Date(headerValue);
|
|
10655
|
+
if (!isNaN(date.getTime())) {
|
|
10656
|
+
const delayMs = date.getTime() - Date.now();
|
|
10657
|
+
return delayMs > 0 ? delayMs : void 0;
|
|
10658
|
+
}
|
|
10659
|
+
return void 0;
|
|
10660
|
+
}
|
|
10661
|
+
function buildEndpointURL(baseURL, endpoint) {
|
|
10662
|
+
return baseURL + API_ENDPOINTS[endpoint].path;
|
|
10663
|
+
}
|
|
10664
|
+
function invalidateCacheTags(tags, params) {
|
|
10665
|
+
if (typeof window !== "undefined" || !revalidateTag || !tags) return;
|
|
10666
|
+
tags.forEach((tag) => {
|
|
10667
|
+
let processedTag = tag;
|
|
10668
|
+
if (params) {
|
|
10669
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
10670
|
+
processedTag = processedTag.replace(`{${key}}`, String(value));
|
|
10671
|
+
});
|
|
10672
|
+
}
|
|
10673
|
+
try {
|
|
10674
|
+
revalidateTag(processedTag, "max");
|
|
10675
|
+
} catch {
|
|
10676
|
+
}
|
|
10677
|
+
});
|
|
10678
|
+
}
|
|
10679
|
+
async function parseErrorBody(response) {
|
|
10680
|
+
const clone = response.clone();
|
|
10681
|
+
const contentType = clone.headers.get("content-type") ?? "";
|
|
10682
|
+
if (contentType.includes("application/json")) {
|
|
10683
|
+
try {
|
|
10684
|
+
return await clone.json();
|
|
10685
|
+
} catch {
|
|
10686
|
+
}
|
|
10687
|
+
}
|
|
10688
|
+
try {
|
|
10689
|
+
const text2 = await clone.text();
|
|
10690
|
+
return text2.length ? text2 : null;
|
|
10691
|
+
} catch {
|
|
10692
|
+
return null;
|
|
10693
|
+
}
|
|
10694
|
+
}
|
|
10695
|
+
function buildSuccessEnvelope(data, requestId) {
|
|
10696
|
+
return {
|
|
10697
|
+
success: true,
|
|
10698
|
+
data,
|
|
10699
|
+
meta: {
|
|
10700
|
+
requestId: requestId ?? generateRequestId(),
|
|
10701
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10702
|
+
apiVersion: "2025-01-01"
|
|
10703
|
+
}
|
|
10704
|
+
};
|
|
10705
|
+
}
|
|
10706
|
+
function buildErrorEnvelope(code, message, status, requestId) {
|
|
10707
|
+
return {
|
|
10708
|
+
success: false,
|
|
10709
|
+
error: {
|
|
10710
|
+
code,
|
|
10711
|
+
message,
|
|
10712
|
+
requestId: requestId ?? generateRequestId(),
|
|
10713
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10714
|
+
status
|
|
10715
|
+
}
|
|
10716
|
+
};
|
|
10717
|
+
}
|
|
10718
|
+
async function parseSuccessResponse(endpoint, response, config3) {
|
|
10719
|
+
const responseKind = config3.responseKind ?? "json";
|
|
10720
|
+
const auth = config3.auth ?? "user";
|
|
10721
|
+
const requestId = response.headers.get("x-request-id") ?? void 0;
|
|
10722
|
+
switch (responseKind) {
|
|
10723
|
+
case "json": {
|
|
10724
|
+
if (response.status === 204 || response.status === 205 || response.status === 304) {
|
|
10725
|
+
return buildSuccessEnvelope(void 0, requestId);
|
|
10726
|
+
}
|
|
10727
|
+
const raw = await response.text();
|
|
10728
|
+
if (!raw.trim()) {
|
|
10729
|
+
return buildSuccessEnvelope(void 0, requestId);
|
|
10730
|
+
}
|
|
10731
|
+
let parsed;
|
|
10732
|
+
try {
|
|
10733
|
+
parsed = JSON.parse(raw);
|
|
10734
|
+
} catch (cause) {
|
|
10735
|
+
throw new ApiRequestError(
|
|
10736
|
+
`Failed to parse JSON response for endpoint ${String(endpoint)}`,
|
|
10737
|
+
{
|
|
10738
|
+
endpoint,
|
|
10739
|
+
status: response.status,
|
|
10740
|
+
method: config3.method,
|
|
10741
|
+
auth,
|
|
10742
|
+
requestId,
|
|
10743
|
+
body: raw,
|
|
10744
|
+
cause
|
|
10745
|
+
}
|
|
10746
|
+
);
|
|
10747
|
+
}
|
|
10748
|
+
if (parsed && typeof parsed === "object" && "success" in parsed && typeof parsed.success === "boolean") {
|
|
10749
|
+
return parsed;
|
|
10750
|
+
}
|
|
10751
|
+
return buildSuccessEnvelope(parsed, requestId);
|
|
10752
|
+
}
|
|
10753
|
+
case "text": {
|
|
10754
|
+
const text2 = await response.text();
|
|
10755
|
+
return buildSuccessEnvelope(text2, requestId);
|
|
10756
|
+
}
|
|
10757
|
+
case "stream": {
|
|
10758
|
+
const body = response.body;
|
|
10759
|
+
if (!body) {
|
|
10760
|
+
return buildErrorEnvelope(
|
|
10761
|
+
"server:internal_error",
|
|
10762
|
+
`Expected a streamed body for endpoint ${String(endpoint)}`,
|
|
10763
|
+
response.status,
|
|
10764
|
+
requestId
|
|
10765
|
+
);
|
|
10766
|
+
}
|
|
10767
|
+
const stream = body;
|
|
10768
|
+
return buildSuccessEnvelope(stream, requestId);
|
|
10769
|
+
}
|
|
10770
|
+
case "void": {
|
|
10771
|
+
return buildSuccessEnvelope(void 0, requestId);
|
|
10772
|
+
}
|
|
10773
|
+
default: {
|
|
10774
|
+
return buildSuccessEnvelope(void 0, requestId);
|
|
10775
|
+
}
|
|
10776
|
+
}
|
|
10777
|
+
}
|
|
10778
|
+
function createRawCMSClient(headers = {}, baseUrl) {
|
|
10779
|
+
return ({
|
|
10780
|
+
endpoint,
|
|
10781
|
+
body,
|
|
10782
|
+
params,
|
|
10783
|
+
options = {}
|
|
10784
|
+
}) => {
|
|
10785
|
+
const resolvedBaseUrl = baseUrl ?? resolveApiBaseUrl();
|
|
10786
|
+
let url = buildEndpointURL(resolvedBaseUrl, endpoint);
|
|
10787
|
+
const originalPath = API_ENDPOINTS[endpoint].path;
|
|
10788
|
+
const unusedParams = {};
|
|
10789
|
+
if (params) {
|
|
10790
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
10791
|
+
const placeholder = `{${key}}`;
|
|
10792
|
+
if (originalPath.includes(placeholder)) {
|
|
10793
|
+
url = url.replace(placeholder, value);
|
|
10794
|
+
} else {
|
|
10795
|
+
unusedParams[key] = value;
|
|
10796
|
+
}
|
|
10797
|
+
});
|
|
10798
|
+
}
|
|
10799
|
+
const endpointConfig = API_ENDPOINTS[endpoint];
|
|
10800
|
+
const method = endpointConfig.method;
|
|
10801
|
+
const isGetOrHead = method === "GET" || method === "HEAD";
|
|
10802
|
+
if (isGetOrHead) {
|
|
10803
|
+
const queryParams = new URLSearchParams();
|
|
10804
|
+
Object.entries(unusedParams).forEach(([key, value]) => {
|
|
10805
|
+
if (value !== void 0 && value !== null) {
|
|
10806
|
+
queryParams.append(key, String(value));
|
|
10807
|
+
}
|
|
10808
|
+
});
|
|
10809
|
+
if (body) {
|
|
10810
|
+
Object.entries(body).forEach(([key, value]) => {
|
|
10811
|
+
if (value !== void 0 && value !== null) {
|
|
10812
|
+
queryParams.append(key, String(value));
|
|
10813
|
+
}
|
|
10814
|
+
});
|
|
10815
|
+
}
|
|
10816
|
+
const queryString = queryParams.toString();
|
|
10817
|
+
if (queryString) {
|
|
10818
|
+
url += (url.includes("?") ? "&" : "?") + queryString;
|
|
10819
|
+
}
|
|
10820
|
+
}
|
|
10821
|
+
const isFormData = typeof FormData !== "undefined" && body instanceof FormData;
|
|
10822
|
+
const nextOptions = {};
|
|
10823
|
+
if (isGetOrHead && "revalidate" in endpointConfig && typeof endpointConfig.revalidate === "number") {
|
|
10824
|
+
nextOptions.revalidate = endpointConfig.revalidate;
|
|
10825
|
+
}
|
|
10826
|
+
if ("tags" in endpointConfig && Array.isArray(endpointConfig.tags)) {
|
|
10827
|
+
nextOptions.tags = endpointConfig.tags.map((tag) => {
|
|
10828
|
+
let processedTag = tag;
|
|
10829
|
+
if (params) {
|
|
10830
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
10831
|
+
processedTag = processedTag.replace(`{${key}}`, String(value));
|
|
10832
|
+
});
|
|
10833
|
+
}
|
|
10834
|
+
return processedTag;
|
|
10835
|
+
});
|
|
10836
|
+
}
|
|
10837
|
+
const requestInit = {
|
|
10838
|
+
method,
|
|
10839
|
+
...options,
|
|
10840
|
+
// Include credentials for same-origin requests (sends cookies for auth)
|
|
10841
|
+
credentials: "same-origin",
|
|
10842
|
+
// Don't include body for GET/HEAD requests
|
|
10843
|
+
body: isGetOrHead ? void 0 : isFormData ? body : body ? JSON.stringify(body) : void 0,
|
|
10844
|
+
headers: {
|
|
10845
|
+
...options.headers,
|
|
10846
|
+
...headers,
|
|
10847
|
+
// Include SDK version if set
|
|
10848
|
+
...sdkVersion && { "x-sdk-version": sdkVersion },
|
|
10849
|
+
// Don't set Content-Type for GET/HEAD requests without body
|
|
10850
|
+
...isGetOrHead ? {} : isFormData ? {} : { "Content-Type": "application/json" }
|
|
10851
|
+
},
|
|
10852
|
+
// Add Next.js caching options
|
|
10853
|
+
next: Object.keys(nextOptions).length > 0 ? nextOptions : void 0
|
|
10854
|
+
};
|
|
10855
|
+
const fetchPromise = fetch(url, requestInit);
|
|
10856
|
+
if (!isGetOrHead && "tags" in endpointConfig && Array.isArray(endpointConfig.tags)) {
|
|
10857
|
+
const tags = endpointConfig.tags.map((tag) => tag);
|
|
10858
|
+
return fetchPromise.then((response) => {
|
|
10859
|
+
if (response.ok) {
|
|
10860
|
+
invalidateCacheTags(tags, params);
|
|
10861
|
+
}
|
|
10862
|
+
return response;
|
|
10863
|
+
});
|
|
10864
|
+
}
|
|
10865
|
+
return fetchPromise;
|
|
10866
|
+
};
|
|
10867
|
+
}
|
|
10868
|
+
function createParsedClient(rawClient) {
|
|
10869
|
+
return async (params) => {
|
|
10870
|
+
const response = await rawClient(params);
|
|
10871
|
+
const endpoint = params.endpoint;
|
|
10872
|
+
const config3 = API_ENDPOINTS[endpoint];
|
|
10873
|
+
const auth = config3.auth ?? "user";
|
|
10874
|
+
if (!response.ok) {
|
|
10875
|
+
const body = await parseErrorBody(response);
|
|
10876
|
+
const requestId = response.headers.get("x-request-id") ?? void 0;
|
|
10877
|
+
const retryAfterMs = parseRetryAfterHeader(response.headers.get("retry-after"));
|
|
10878
|
+
throw new ApiRequestError(
|
|
10879
|
+
`Request to ${String(endpoint)} failed with status ${response.status}`,
|
|
10880
|
+
{
|
|
10881
|
+
endpoint,
|
|
10882
|
+
status: response.status,
|
|
10883
|
+
method: config3.method,
|
|
10884
|
+
auth,
|
|
10885
|
+
requestId,
|
|
10886
|
+
body,
|
|
10887
|
+
retryAfterMs
|
|
10888
|
+
}
|
|
10889
|
+
);
|
|
10890
|
+
}
|
|
10891
|
+
return parseSuccessResponse(endpoint, response, config3);
|
|
10892
|
+
};
|
|
10893
|
+
}
|
|
10894
|
+
function createCMSClient(headers = {}, baseUrl) {
|
|
10895
|
+
return createParsedClient(createRawCMSClient(headers, baseUrl));
|
|
10896
|
+
}
|
|
10897
|
+
function createBearerAPIClient(token, baseUrl) {
|
|
10898
|
+
const authHeaders = {
|
|
10899
|
+
Authorization: `Bearer ${token}`
|
|
10900
|
+
};
|
|
10901
|
+
return createCMSClient(authHeaders, baseUrl);
|
|
10902
|
+
}
|
|
10903
|
+
|
|
10904
|
+
// ../api/src/common/envelope.ts
|
|
10905
|
+
function isApiError(result) {
|
|
10906
|
+
return result.success === false;
|
|
10907
|
+
}
|
|
10908
|
+
function isApiSuccess(result) {
|
|
10909
|
+
return result.success === true;
|
|
10910
|
+
}
|
|
10911
|
+
var ApiEnvelopeError = class extends Error {
|
|
10912
|
+
constructor(error) {
|
|
10913
|
+
super(error.message);
|
|
10914
|
+
this.name = "ApiEnvelopeError";
|
|
10915
|
+
this.code = error.code;
|
|
10916
|
+
this.requestId = error.requestId;
|
|
10917
|
+
this.timestamp = error.timestamp;
|
|
10918
|
+
this.status = error.status;
|
|
10919
|
+
this.fieldErrors = error.fieldErrors;
|
|
10920
|
+
}
|
|
10921
|
+
};
|
|
10922
|
+
function unwrapResponse(result) {
|
|
10923
|
+
if (isApiSuccess(result)) {
|
|
10924
|
+
return result.data;
|
|
10925
|
+
}
|
|
10926
|
+
throw new ApiEnvelopeError(result.error);
|
|
10927
|
+
}
|
|
10928
|
+
|
|
10929
|
+
// src/client/cache.ts
|
|
10930
|
+
var SimpleCache = class {
|
|
10931
|
+
constructor(options = {}) {
|
|
10932
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
10933
|
+
this.maxSize = options.maxSize ?? 100;
|
|
10934
|
+
this.ttl = options.ttl ?? 3e5;
|
|
10935
|
+
this.staleTtl = options.staleTtl ?? 3e5;
|
|
10936
|
+
}
|
|
10937
|
+
/**
|
|
10938
|
+
* Get a fresh value (within TTL)
|
|
10939
|
+
* @returns The value if fresh, null otherwise
|
|
10940
|
+
*/
|
|
10941
|
+
getFresh(key) {
|
|
10942
|
+
const entry = this.cache.get(key);
|
|
10943
|
+
if (!entry) return null;
|
|
10944
|
+
const now = Date.now();
|
|
10945
|
+
if (now <= entry.freshUntil) {
|
|
10946
|
+
return entry.value;
|
|
10947
|
+
}
|
|
10948
|
+
return null;
|
|
10949
|
+
}
|
|
10950
|
+
/**
|
|
10951
|
+
* Get a value that may be stale (past TTL but within staleTtl)
|
|
10952
|
+
* @returns Object with value and stale age, or null if expired
|
|
10953
|
+
*/
|
|
10954
|
+
getStale(key) {
|
|
10955
|
+
const entry = this.cache.get(key);
|
|
10956
|
+
if (!entry) return null;
|
|
10957
|
+
const now = Date.now();
|
|
10958
|
+
if (now > entry.staleUntil) {
|
|
10959
|
+
this.cache.delete(key);
|
|
10960
|
+
return null;
|
|
10961
|
+
}
|
|
10962
|
+
const staleAgeSec = now <= entry.freshUntil ? 0 : Math.floor((now - entry.freshUntil) / 1e3);
|
|
10963
|
+
return {
|
|
10964
|
+
value: entry.value,
|
|
10965
|
+
staleAgeSec
|
|
10966
|
+
};
|
|
10967
|
+
}
|
|
10968
|
+
/**
|
|
10969
|
+
* Store a value with TTL and stale window
|
|
10970
|
+
*/
|
|
10971
|
+
set(key, value, options) {
|
|
10972
|
+
const ttl = options?.ttl ?? this.ttl;
|
|
10973
|
+
const staleTtl = options?.staleTtl ?? this.staleTtl;
|
|
10974
|
+
const now = Date.now();
|
|
10975
|
+
while (this.cache.size >= this.maxSize && !this.cache.has(key)) {
|
|
10976
|
+
this.evictOne(now);
|
|
10977
|
+
}
|
|
10978
|
+
this.cache.set(key, {
|
|
10979
|
+
value,
|
|
10980
|
+
createdAt: now,
|
|
10981
|
+
freshUntil: now + ttl,
|
|
10982
|
+
staleUntil: now + ttl + staleTtl
|
|
10983
|
+
});
|
|
10984
|
+
}
|
|
10985
|
+
/**
|
|
10986
|
+
* Evict one entry to make room for a new one
|
|
10987
|
+
* Priority: oldest stale entry, then oldest fresh entry
|
|
10988
|
+
*/
|
|
10989
|
+
evictOne(now) {
|
|
10990
|
+
let oldestStaleKey = null;
|
|
10991
|
+
let oldestStaleTime = Infinity;
|
|
10992
|
+
let oldestFreshKey = null;
|
|
10993
|
+
let oldestFreshTime = Infinity;
|
|
10994
|
+
for (const [key, entry] of this.cache) {
|
|
10995
|
+
if (now > entry.freshUntil) {
|
|
10996
|
+
if (entry.createdAt < oldestStaleTime) {
|
|
10997
|
+
oldestStaleTime = entry.createdAt;
|
|
10998
|
+
oldestStaleKey = key;
|
|
10999
|
+
}
|
|
11000
|
+
} else {
|
|
11001
|
+
if (entry.createdAt < oldestFreshTime) {
|
|
11002
|
+
oldestFreshTime = entry.createdAt;
|
|
11003
|
+
oldestFreshKey = key;
|
|
11004
|
+
}
|
|
11005
|
+
}
|
|
11006
|
+
}
|
|
11007
|
+
const keyToEvict = oldestStaleKey ?? oldestFreshKey;
|
|
11008
|
+
if (keyToEvict) {
|
|
11009
|
+
this.cache.delete(keyToEvict);
|
|
11010
|
+
}
|
|
11011
|
+
}
|
|
11012
|
+
/**
|
|
11013
|
+
* Remove all fully expired entries (past staleUntil)
|
|
11014
|
+
*/
|
|
11015
|
+
prune() {
|
|
11016
|
+
const now = Date.now();
|
|
11017
|
+
for (const [key, entry] of this.cache) {
|
|
11018
|
+
if (now > entry.staleUntil) {
|
|
11019
|
+
this.cache.delete(key);
|
|
11020
|
+
}
|
|
11021
|
+
}
|
|
11022
|
+
}
|
|
11023
|
+
/**
|
|
11024
|
+
* Clear all entries
|
|
11025
|
+
*/
|
|
11026
|
+
clear() {
|
|
11027
|
+
this.cache.clear();
|
|
11028
|
+
}
|
|
11029
|
+
/**
|
|
11030
|
+
* Check if a key exists and is not fully expired
|
|
11031
|
+
*/
|
|
11032
|
+
has(key) {
|
|
11033
|
+
const entry = this.cache.get(key);
|
|
11034
|
+
if (!entry) return false;
|
|
11035
|
+
const now = Date.now();
|
|
11036
|
+
if (now > entry.staleUntil) {
|
|
11037
|
+
this.cache.delete(key);
|
|
11038
|
+
return false;
|
|
11039
|
+
}
|
|
11040
|
+
return now <= entry.freshUntil;
|
|
11041
|
+
}
|
|
11042
|
+
};
|
|
11043
|
+
|
|
11044
|
+
// src/version.ts
|
|
11045
|
+
var SDK_VERSION = "0.8.0";
|
|
11046
|
+
|
|
11047
|
+
// src/client/error.ts
|
|
11048
|
+
var RiverbankApiError = class _RiverbankApiError extends Error {
|
|
11049
|
+
constructor(apiError) {
|
|
11050
|
+
super(apiError.message);
|
|
11051
|
+
this.name = "RiverbankApiError";
|
|
11052
|
+
if ("cause" in apiError && apiError.cause) {
|
|
11053
|
+
this.cause = apiError.cause;
|
|
11054
|
+
}
|
|
11055
|
+
this.code = apiError.code;
|
|
11056
|
+
this.requestId = apiError.requestId;
|
|
11057
|
+
this.status = apiError.status;
|
|
11058
|
+
this.fieldErrors = apiError.fieldErrors;
|
|
11059
|
+
this.timestamp = apiError.timestamp;
|
|
11060
|
+
this.retryAfterMs = "retryAfterMs" in apiError ? apiError.retryAfterMs : void 0;
|
|
11061
|
+
this.isRetryable = this.computeRetryable();
|
|
11062
|
+
Object.setPrototypeOf(this, _RiverbankApiError.prototype);
|
|
11063
|
+
}
|
|
11064
|
+
/**
|
|
11065
|
+
* Compute whether this error is retryable based on HTTP status code.
|
|
11066
|
+
* - 0 (network errors - no HTTP response): retryable
|
|
11067
|
+
* - 429 (rate limit): retryable
|
|
11068
|
+
* - 5xx (server errors): retryable
|
|
11069
|
+
* - 4xx (client errors, except 429): NOT retryable
|
|
11070
|
+
*/
|
|
11071
|
+
computeRetryable() {
|
|
11072
|
+
if (this.status === 0) return true;
|
|
11073
|
+
if (this.status === 429) return true;
|
|
11074
|
+
if (this.status >= 500) return true;
|
|
11075
|
+
return false;
|
|
11076
|
+
}
|
|
11077
|
+
/**
|
|
11078
|
+
* Check if this is a network error (no HTTP response received)
|
|
11079
|
+
*
|
|
11080
|
+
* Matches: network:connection_error, network:timeout, network:dns_error
|
|
11081
|
+
*/
|
|
11082
|
+
isNetworkError() {
|
|
11083
|
+
return this.code.startsWith("network:");
|
|
11084
|
+
}
|
|
11085
|
+
/**
|
|
11086
|
+
* Check if this error matches a specific error code
|
|
11087
|
+
*
|
|
11088
|
+
* @example
|
|
11089
|
+
* ```ts
|
|
11090
|
+
* if (error.is('auth:unauthenticated')) {
|
|
11091
|
+
* // Redirect to login
|
|
11092
|
+
* }
|
|
11093
|
+
* ```
|
|
11094
|
+
*/
|
|
11095
|
+
is(code) {
|
|
11096
|
+
return this.code === code;
|
|
11097
|
+
}
|
|
11098
|
+
/**
|
|
11099
|
+
* Check if this is an authentication or authorization error
|
|
11100
|
+
*
|
|
11101
|
+
* Matches: auth:unauthenticated, auth:token_expired, auth:token_invalid,
|
|
11102
|
+
* auth:forbidden, auth:mfa_required, auth:insufficient_permissions
|
|
11103
|
+
*/
|
|
11104
|
+
isAuthError() {
|
|
11105
|
+
return this.code.startsWith("auth:");
|
|
11106
|
+
}
|
|
11107
|
+
/**
|
|
11108
|
+
* Check if this is a validation error
|
|
11109
|
+
*
|
|
11110
|
+
* Matches: validation:invalid_input, validation:missing_field, validation:invalid_format
|
|
11111
|
+
*/
|
|
11112
|
+
isValidationError() {
|
|
11113
|
+
return this.code.startsWith("validation:");
|
|
11114
|
+
}
|
|
11115
|
+
/**
|
|
11116
|
+
* Check if this is a resource error (not found, conflict, etc.)
|
|
11117
|
+
*
|
|
11118
|
+
* Matches: resource:not_found, resource:already_exists, resource:conflict, resource:gone
|
|
11119
|
+
*/
|
|
11120
|
+
isResourceError() {
|
|
11121
|
+
return this.code.startsWith("resource:");
|
|
11122
|
+
}
|
|
11123
|
+
/**
|
|
11124
|
+
* Check if this is a rate limiting error
|
|
11125
|
+
*/
|
|
11126
|
+
isRateLimitError() {
|
|
11127
|
+
return this.code.startsWith("rate_limit:");
|
|
11128
|
+
}
|
|
11129
|
+
/**
|
|
11130
|
+
* Check if this is a billing/payment error
|
|
11131
|
+
*/
|
|
11132
|
+
isBillingError() {
|
|
11133
|
+
return this.code.startsWith("billing:");
|
|
11134
|
+
}
|
|
11135
|
+
/**
|
|
11136
|
+
* Check if this is a server error
|
|
11137
|
+
*/
|
|
11138
|
+
isServerError() {
|
|
11139
|
+
return this.code.startsWith("server:");
|
|
11140
|
+
}
|
|
11141
|
+
/**
|
|
11142
|
+
* Returns a human-readable string representation of the error.
|
|
11143
|
+
* Includes all key details for debugging.
|
|
11144
|
+
*
|
|
11145
|
+
* @example
|
|
11146
|
+
* "RiverbankApiError: Content keys cannot access preview content | Code: auth:forbidden | Status: 401 | RequestId: req-abc123"
|
|
11147
|
+
*/
|
|
11148
|
+
toString() {
|
|
11149
|
+
const parts = [`RiverbankApiError: ${this.message}`];
|
|
11150
|
+
if (this.code) parts.push(`Code: ${this.code}`);
|
|
11151
|
+
if (this.status) parts.push(`Status: ${this.status}`);
|
|
11152
|
+
if (this.requestId) parts.push(`RequestId: ${this.requestId}`);
|
|
11153
|
+
return parts.join(" | ");
|
|
11154
|
+
}
|
|
11155
|
+
/**
|
|
11156
|
+
* Custom Node.js inspect output for better console.log display.
|
|
11157
|
+
* This ensures that console.log(error) shows all relevant details
|
|
11158
|
+
* instead of just "[Object]" for nested properties.
|
|
11159
|
+
*/
|
|
11160
|
+
[Symbol.for("nodejs.util.inspect.custom")]() {
|
|
11161
|
+
return this.toDetailedString();
|
|
11162
|
+
}
|
|
11163
|
+
/**
|
|
11164
|
+
* Returns a detailed multi-line string for debugging.
|
|
11165
|
+
* Used by the Node.js inspect symbol for console output.
|
|
11166
|
+
*/
|
|
11167
|
+
toDetailedString() {
|
|
11168
|
+
const lines = [
|
|
11169
|
+
`RiverbankApiError: ${this.message}`,
|
|
11170
|
+
` Code: ${this.code}`,
|
|
11171
|
+
` Status: ${this.status}`,
|
|
11172
|
+
` RequestId: ${this.requestId}`,
|
|
11173
|
+
` Timestamp: ${this.timestamp}`
|
|
11174
|
+
];
|
|
11175
|
+
if (this.isRetryable) {
|
|
11176
|
+
lines.push(` Retryable: true`);
|
|
11177
|
+
if (this.retryAfterMs) {
|
|
11178
|
+
lines.push(` RetryAfter: ${this.retryAfterMs}ms`);
|
|
11179
|
+
}
|
|
11180
|
+
}
|
|
11181
|
+
if (this.fieldErrors && this.fieldErrors.length > 0) {
|
|
11182
|
+
lines.push(" FieldErrors:");
|
|
11183
|
+
this.fieldErrors.forEach((fe) => {
|
|
11184
|
+
lines.push(` - ${fe.field}: ${fe.message}`);
|
|
11185
|
+
});
|
|
11186
|
+
}
|
|
11187
|
+
return lines.join("\n");
|
|
11188
|
+
}
|
|
11189
|
+
};
|
|
11190
|
+
|
|
11191
|
+
// src/client/resilience.ts
|
|
11192
|
+
var DEFAULT_RETRY_CONFIG = {
|
|
11193
|
+
maxAttempts: 3,
|
|
11194
|
+
baseDelayMs: 200,
|
|
11195
|
+
maxDelayMs: 2e3,
|
|
11196
|
+
jitter: "full"
|
|
11197
|
+
};
|
|
11198
|
+
var DEFAULT_CIRCUIT_BREAKER_CONFIG = {
|
|
11199
|
+
failureThreshold: 5,
|
|
11200
|
+
resetTimeoutMs: 3e4,
|
|
11201
|
+
halfOpenMaxRequests: 2
|
|
11202
|
+
};
|
|
11203
|
+
var PERMANENT_NETWORK_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
11204
|
+
"ECONNREFUSED",
|
|
11205
|
+
// Server is not running / port not listening
|
|
11206
|
+
"ENOTFOUND",
|
|
11207
|
+
// DNS lookup failed - hostname doesn't exist
|
|
11208
|
+
"EAI_AGAIN"
|
|
11209
|
+
// DNS lookup timeout (usually permanent for invalid hosts)
|
|
11210
|
+
]);
|
|
11211
|
+
var TRANSIENT_NETWORK_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
11212
|
+
"ECONNRESET",
|
|
11213
|
+
// Connection was reset mid-request (server dropped it)
|
|
11214
|
+
"EPIPE",
|
|
11215
|
+
// Broken pipe (connection closed while writing)
|
|
11216
|
+
"ETIMEDOUT",
|
|
11217
|
+
// Connection timed out (could be temporary congestion)
|
|
11218
|
+
"ESOCKETTIMEDOUT"
|
|
11219
|
+
// Socket timeout
|
|
11220
|
+
]);
|
|
11221
|
+
var NODE_NETWORK_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
11222
|
+
// Permanent
|
|
11223
|
+
"ECONNREFUSED",
|
|
11224
|
+
"ENOTFOUND",
|
|
11225
|
+
"EAI_AGAIN",
|
|
11226
|
+
// Transient
|
|
11227
|
+
"ECONNRESET",
|
|
11228
|
+
"EPIPE",
|
|
11229
|
+
"ETIMEDOUT",
|
|
11230
|
+
"ESOCKETTIMEDOUT"
|
|
11231
|
+
]);
|
|
11232
|
+
function isNodeNetworkErrorCode(code) {
|
|
11233
|
+
return !code.includes(":") && NODE_NETWORK_ERROR_CODES.has(code);
|
|
11234
|
+
}
|
|
11235
|
+
function getErrorCodeFromCause(error) {
|
|
11236
|
+
let current = error;
|
|
11237
|
+
while (current) {
|
|
11238
|
+
const nodeError = current;
|
|
11239
|
+
if (nodeError.code && typeof nodeError.code === "string") {
|
|
11240
|
+
if (isNodeNetworkErrorCode(nodeError.code)) {
|
|
11241
|
+
return nodeError.code;
|
|
11242
|
+
}
|
|
11243
|
+
}
|
|
11244
|
+
const errorWithCause = current;
|
|
11245
|
+
current = errorWithCause.cause;
|
|
11246
|
+
}
|
|
11247
|
+
return void 0;
|
|
11248
|
+
}
|
|
11249
|
+
function isTransientError(error) {
|
|
11250
|
+
if (error instanceof RiverbankApiError) {
|
|
11251
|
+
const errorCode = getErrorCodeFromCause(error);
|
|
11252
|
+
if (errorCode && PERMANENT_NETWORK_ERROR_CODES.has(errorCode)) {
|
|
11253
|
+
return false;
|
|
11254
|
+
}
|
|
11255
|
+
if (error.status === 0) return true;
|
|
11256
|
+
if (error.status === 429) return true;
|
|
11257
|
+
if (error.status >= 500) return true;
|
|
11258
|
+
return false;
|
|
11259
|
+
}
|
|
11260
|
+
if (error instanceof TypeError) {
|
|
11261
|
+
const errorCode = getErrorCodeFromCause(error);
|
|
11262
|
+
if (errorCode) {
|
|
11263
|
+
if (PERMANENT_NETWORK_ERROR_CODES.has(errorCode)) {
|
|
11264
|
+
return false;
|
|
11265
|
+
}
|
|
11266
|
+
if (TRANSIENT_NETWORK_ERROR_CODES.has(errorCode)) {
|
|
11267
|
+
return true;
|
|
11268
|
+
}
|
|
11269
|
+
}
|
|
11270
|
+
return true;
|
|
11271
|
+
}
|
|
11272
|
+
return true;
|
|
11273
|
+
}
|
|
11274
|
+
function calculateBackoff(attempt, config3) {
|
|
11275
|
+
const baseDelayMs = config3.baseDelayMs ?? DEFAULT_RETRY_CONFIG.baseDelayMs;
|
|
11276
|
+
const maxDelayMs = config3.maxDelayMs ?? DEFAULT_RETRY_CONFIG.maxDelayMs;
|
|
11277
|
+
const jitter = config3.jitter ?? DEFAULT_RETRY_CONFIG.jitter;
|
|
11278
|
+
const exponential = baseDelayMs * Math.pow(2, attempt - 1);
|
|
11279
|
+
const capped = Math.min(exponential, maxDelayMs);
|
|
11280
|
+
if (jitter === "full") {
|
|
11281
|
+
return Math.random() * capped;
|
|
11282
|
+
}
|
|
11283
|
+
return capped;
|
|
11284
|
+
}
|
|
11285
|
+
var CircuitBreaker = class {
|
|
11286
|
+
constructor(config3) {
|
|
11287
|
+
this.state = "closed";
|
|
11288
|
+
this.failureCount = 0;
|
|
11289
|
+
this.successCount = 0;
|
|
11290
|
+
this.openUntil = 0;
|
|
11291
|
+
this.halfOpenRequests = 0;
|
|
11292
|
+
this.config = {
|
|
11293
|
+
failureThreshold: config3?.failureThreshold ?? DEFAULT_CIRCUIT_BREAKER_CONFIG.failureThreshold,
|
|
11294
|
+
resetTimeoutMs: config3?.resetTimeoutMs ?? DEFAULT_CIRCUIT_BREAKER_CONFIG.resetTimeoutMs,
|
|
11295
|
+
halfOpenMaxRequests: config3?.halfOpenMaxRequests ?? DEFAULT_CIRCUIT_BREAKER_CONFIG.halfOpenMaxRequests
|
|
11296
|
+
};
|
|
11297
|
+
}
|
|
11298
|
+
/**
|
|
11299
|
+
* Check if circuit is open (requests should be blocked)
|
|
11300
|
+
* Also handles automatic transition from open to half-open after timeout
|
|
11301
|
+
*/
|
|
11302
|
+
isOpen() {
|
|
11303
|
+
if (this.state === "open" && Date.now() >= this.openUntil) {
|
|
11304
|
+
this.transitionTo("half-open");
|
|
11305
|
+
}
|
|
11306
|
+
return this.state === "open";
|
|
11307
|
+
}
|
|
11308
|
+
/**
|
|
11309
|
+
* Check if a request can be attempted
|
|
11310
|
+
* - closed: always yes
|
|
11311
|
+
* - open: always no
|
|
11312
|
+
* - half-open: limited number of probes
|
|
11313
|
+
*/
|
|
11314
|
+
canAttempt() {
|
|
11315
|
+
if (this.state === "closed") return true;
|
|
11316
|
+
if (this.state === "open") return false;
|
|
11317
|
+
return this.halfOpenRequests < this.config.halfOpenMaxRequests;
|
|
11318
|
+
}
|
|
11319
|
+
/**
|
|
11320
|
+
* Increment half-open request counter (call before making request in half-open)
|
|
11321
|
+
*/
|
|
11322
|
+
incrementHalfOpenRequests() {
|
|
11323
|
+
if (this.state === "half-open") {
|
|
11324
|
+
this.halfOpenRequests++;
|
|
11325
|
+
}
|
|
11326
|
+
}
|
|
11327
|
+
/**
|
|
11328
|
+
* Record a successful request
|
|
11329
|
+
*/
|
|
11330
|
+
recordSuccess() {
|
|
11331
|
+
if (this.state === "half-open") {
|
|
11332
|
+
this.successCount++;
|
|
11333
|
+
if (this.successCount >= this.config.halfOpenMaxRequests) {
|
|
11334
|
+
this.transitionTo("closed");
|
|
11335
|
+
}
|
|
11336
|
+
} else {
|
|
11337
|
+
this.failureCount = 0;
|
|
11338
|
+
}
|
|
11339
|
+
}
|
|
11340
|
+
/**
|
|
11341
|
+
* Record a failed request
|
|
11342
|
+
* Only counts transient failures toward circuit breaker threshold
|
|
11343
|
+
*/
|
|
11344
|
+
recordFailure(error) {
|
|
11345
|
+
if (!isTransientError(error)) return;
|
|
11346
|
+
this.failureCount++;
|
|
11347
|
+
if (this.state === "half-open") {
|
|
11348
|
+
this.transitionTo("open");
|
|
11349
|
+
} else if (this.failureCount >= this.config.failureThreshold) {
|
|
11350
|
+
this.transitionTo("open");
|
|
11351
|
+
}
|
|
11352
|
+
}
|
|
11353
|
+
/**
|
|
11354
|
+
* Get current circuit state
|
|
11355
|
+
*/
|
|
11356
|
+
getState() {
|
|
11357
|
+
return {
|
|
11358
|
+
state: this.state,
|
|
11359
|
+
failureCount: this.failureCount,
|
|
11360
|
+
openUntil: this.state === "open" ? this.openUntil : void 0
|
|
11361
|
+
};
|
|
11362
|
+
}
|
|
11363
|
+
/**
|
|
11364
|
+
* Transition to a new state
|
|
11365
|
+
*/
|
|
11366
|
+
transitionTo(newState) {
|
|
11367
|
+
this.state = newState;
|
|
11368
|
+
if (newState === "open") {
|
|
11369
|
+
this.openUntil = Date.now() + this.config.resetTimeoutMs;
|
|
11370
|
+
} else if (newState === "half-open") {
|
|
11371
|
+
this.halfOpenRequests = 0;
|
|
11372
|
+
this.successCount = 0;
|
|
11373
|
+
} else if (newState === "closed") {
|
|
11374
|
+
this.failureCount = 0;
|
|
11375
|
+
this.successCount = 0;
|
|
11376
|
+
this.halfOpenRequests = 0;
|
|
11377
|
+
}
|
|
11378
|
+
}
|
|
11379
|
+
};
|
|
11380
|
+
async function fetchWithTimeoutAndRetry(fetcher, config3) {
|
|
11381
|
+
const maxAttempts = config3.maxAttempts ?? DEFAULT_RETRY_CONFIG.maxAttempts;
|
|
11382
|
+
const requestTimeoutMs = config3.requestTimeoutMs ?? 8e3;
|
|
11383
|
+
let lastError;
|
|
11384
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
11385
|
+
try {
|
|
11386
|
+
const controller = new AbortController();
|
|
11387
|
+
const timeoutId = setTimeout(() => controller.abort(), requestTimeoutMs);
|
|
11388
|
+
try {
|
|
11389
|
+
const result = await fetcher(controller.signal);
|
|
11390
|
+
return result;
|
|
11391
|
+
} finally {
|
|
11392
|
+
clearTimeout(timeoutId);
|
|
11393
|
+
}
|
|
11394
|
+
} catch (error) {
|
|
11395
|
+
lastError = error;
|
|
11396
|
+
const shouldRetry = shouldRetryError(error, config3.retryOn);
|
|
11397
|
+
if (!shouldRetry) {
|
|
11398
|
+
throw error;
|
|
11399
|
+
}
|
|
11400
|
+
if (attempt < maxAttempts) {
|
|
11401
|
+
const delay = getRetryDelay(error, attempt, config3);
|
|
11402
|
+
await sleep(delay);
|
|
11403
|
+
}
|
|
11404
|
+
}
|
|
11405
|
+
}
|
|
11406
|
+
throw lastError;
|
|
11407
|
+
}
|
|
11408
|
+
function isAbortError(error) {
|
|
11409
|
+
if (typeof DOMException !== "undefined" && error instanceof DOMException && error.name === "AbortError") {
|
|
11410
|
+
return true;
|
|
11411
|
+
}
|
|
11412
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
11413
|
+
return true;
|
|
11414
|
+
}
|
|
11415
|
+
return false;
|
|
11416
|
+
}
|
|
11417
|
+
function shouldRetryError(error, customRetryOn) {
|
|
11418
|
+
if (isAbortError(error)) {
|
|
11419
|
+
return false;
|
|
11420
|
+
}
|
|
11421
|
+
if (customRetryOn) {
|
|
11422
|
+
const statusCode = error instanceof RiverbankApiError ? error.status : void 0;
|
|
11423
|
+
return customRetryOn(error, statusCode);
|
|
11424
|
+
}
|
|
11425
|
+
return isTransientError(error);
|
|
11426
|
+
}
|
|
11427
|
+
function getRetryDelay(error, attempt, config3) {
|
|
11428
|
+
if (error instanceof RiverbankApiError && error.retryAfterMs) {
|
|
11429
|
+
return error.retryAfterMs;
|
|
11430
|
+
}
|
|
11431
|
+
return calculateBackoff(attempt, config3);
|
|
11432
|
+
}
|
|
11433
|
+
function sleep(ms) {
|
|
11434
|
+
return new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
11435
|
+
}
|
|
11436
|
+
var CircuitOpenError = class extends Error {
|
|
11437
|
+
constructor(state) {
|
|
11438
|
+
super("Circuit breaker is open");
|
|
11439
|
+
this.name = "CircuitOpenError";
|
|
11440
|
+
this.circuitState = state;
|
|
11441
|
+
}
|
|
11442
|
+
};
|
|
11443
|
+
|
|
11444
|
+
// src/client/index.ts
|
|
11445
|
+
var prebuildModule = null;
|
|
11446
|
+
function getPrebuildModule() {
|
|
11447
|
+
if (prebuildModule !== null) return prebuildModule;
|
|
11448
|
+
if (typeof process === "undefined" || !process.versions?.node) {
|
|
11449
|
+
return null;
|
|
11450
|
+
}
|
|
11451
|
+
try {
|
|
11452
|
+
prebuildModule = (init_loader(), __toCommonJS(loader_exports));
|
|
11453
|
+
return prebuildModule;
|
|
11454
|
+
} catch {
|
|
11455
|
+
return null;
|
|
11456
|
+
}
|
|
11457
|
+
}
|
|
11458
|
+
setSdkVersion(SDK_VERSION);
|
|
11459
|
+
var DEFAULT_BROWSER_TIMEOUT_MS = 5e3;
|
|
11460
|
+
var DEFAULT_SERVER_TIMEOUT_MS = 8e3;
|
|
11461
|
+
function generateRequestId2() {
|
|
11462
|
+
return `req-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
11463
|
+
}
|
|
11464
|
+
function isAbortError2(error) {
|
|
11465
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
11466
|
+
return true;
|
|
11467
|
+
}
|
|
11468
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
11469
|
+
return true;
|
|
11470
|
+
}
|
|
11471
|
+
return false;
|
|
11472
|
+
}
|
|
11473
|
+
function getNetworkErrorCode(error) {
|
|
11474
|
+
if (error.name === "TimeoutError" || error.name === "AbortError") {
|
|
11475
|
+
return "network:timeout";
|
|
11476
|
+
}
|
|
11477
|
+
const nodeError = error;
|
|
11478
|
+
if (nodeError.code) {
|
|
11479
|
+
switch (nodeError.code) {
|
|
11480
|
+
case "ETIMEDOUT":
|
|
11481
|
+
case "ESOCKETTIMEDOUT":
|
|
11482
|
+
return "network:timeout";
|
|
11483
|
+
case "ENOTFOUND":
|
|
11484
|
+
case "EAI_AGAIN":
|
|
11485
|
+
return "network:dns_error";
|
|
11486
|
+
case "ECONNREFUSED":
|
|
11487
|
+
case "ECONNRESET":
|
|
11488
|
+
case "EPIPE":
|
|
11489
|
+
return "network:connection_error";
|
|
11490
|
+
}
|
|
11491
|
+
}
|
|
11492
|
+
const message = error.message.toLowerCase();
|
|
11493
|
+
if (message.includes("timeout") || message.includes("timed out")) {
|
|
11494
|
+
return "network:timeout";
|
|
11495
|
+
}
|
|
11496
|
+
if (message.includes("dns") || message.includes("getaddrinfo") || message.includes("enotfound")) {
|
|
11497
|
+
return "network:dns_error";
|
|
11498
|
+
}
|
|
11499
|
+
return "network:connection_error";
|
|
11500
|
+
}
|
|
11501
|
+
function convertToTypedError(error) {
|
|
11502
|
+
if (isAbortError2(error)) {
|
|
11503
|
+
throw error;
|
|
11504
|
+
}
|
|
11505
|
+
if (error instanceof ApiEnvelopeError) {
|
|
11506
|
+
throw new RiverbankApiError({
|
|
11507
|
+
code: error.code,
|
|
11508
|
+
message: error.message,
|
|
11509
|
+
requestId: error.requestId,
|
|
11510
|
+
timestamp: error.timestamp,
|
|
11511
|
+
status: error.status,
|
|
11512
|
+
fieldErrors: error.fieldErrors
|
|
11513
|
+
});
|
|
11514
|
+
}
|
|
11515
|
+
if (error instanceof ApiRequestError && error.body && typeof error.body === "object") {
|
|
11516
|
+
const body = error.body;
|
|
11517
|
+
if (isApiError(body)) {
|
|
11518
|
+
const envelopeError = body.error;
|
|
11519
|
+
throw new RiverbankApiError({
|
|
11520
|
+
...envelopeError,
|
|
11521
|
+
retryAfterMs: error.retryAfterMs
|
|
11522
|
+
});
|
|
11523
|
+
}
|
|
11524
|
+
}
|
|
11525
|
+
if (error instanceof TypeError || error instanceof Error && !("status" in error)) {
|
|
11526
|
+
const networkError = error;
|
|
11527
|
+
throw new RiverbankApiError({
|
|
11528
|
+
code: getNetworkErrorCode(networkError),
|
|
11529
|
+
message: networkError.message || "Network request failed",
|
|
11530
|
+
requestId: `local-${Date.now()}`,
|
|
11531
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11532
|
+
status: 0,
|
|
11533
|
+
// No HTTP response received
|
|
11534
|
+
cause: networkError
|
|
11535
|
+
// Preserve original error for retry/circuit breaker classification
|
|
11536
|
+
});
|
|
11537
|
+
}
|
|
11538
|
+
throw error;
|
|
11539
|
+
}
|
|
11540
|
+
function detectKeyType(apiKey) {
|
|
11541
|
+
if (apiKey.startsWith("bld_live_sk_") || apiKey.startsWith("bld_test_sk_")) {
|
|
11542
|
+
return "content";
|
|
11543
|
+
}
|
|
11544
|
+
if (apiKey.startsWith("bld_preview_sk_")) {
|
|
11545
|
+
return "preview";
|
|
11546
|
+
}
|
|
11547
|
+
return "unknown";
|
|
11548
|
+
}
|
|
11549
|
+
function createRiverbankClient(config3) {
|
|
11550
|
+
if (!config3.baseUrl) {
|
|
11551
|
+
throw new Error(
|
|
11552
|
+
"baseUrl is required when creating a Riverbank client. Expected format: https://dashboard.example.com/api (must include /api path)"
|
|
11553
|
+
);
|
|
11554
|
+
}
|
|
11555
|
+
if (!config3.baseUrl.endsWith("/api")) {
|
|
11556
|
+
throw new Error(
|
|
11557
|
+
`baseUrl must end with '/api'. Received: ${config3.baseUrl}. Expected format: https://dashboard.example.com/api`
|
|
11558
|
+
);
|
|
11559
|
+
}
|
|
11560
|
+
const cacheEnabled = config3.cache?.enabled ?? true;
|
|
11561
|
+
const cacheTTL = (config3.cache?.ttl ?? 300) * 1e3;
|
|
11562
|
+
const cacheMaxSize = config3.cache?.maxSize ?? 100;
|
|
11563
|
+
const resilienceEnabled = config3.resilience?.enabled ?? true;
|
|
11564
|
+
const staleIfError = config3.resilience?.staleIfError ?? true;
|
|
11565
|
+
const staleTtlMs = (config3.resilience?.staleTtlSec ?? 300) * 1e3;
|
|
11566
|
+
const requestTimeoutMs = config3.resilience?.requestTimeoutMs ?? (typeof window !== "undefined" ? DEFAULT_BROWSER_TIMEOUT_MS : DEFAULT_SERVER_TIMEOUT_MS);
|
|
11567
|
+
const retryConfig = {
|
|
11568
|
+
maxAttempts: config3.resilience?.retry?.maxAttempts ?? DEFAULT_RETRY_CONFIG.maxAttempts,
|
|
11569
|
+
baseDelayMs: config3.resilience?.retry?.baseDelayMs ?? DEFAULT_RETRY_CONFIG.baseDelayMs,
|
|
11570
|
+
maxDelayMs: config3.resilience?.retry?.maxDelayMs ?? DEFAULT_RETRY_CONFIG.maxDelayMs,
|
|
11571
|
+
jitter: config3.resilience?.retry?.jitter ?? DEFAULT_RETRY_CONFIG.jitter,
|
|
11572
|
+
retryOn: config3.resilience?.retry?.retryOn
|
|
11573
|
+
};
|
|
11574
|
+
const circuitBreakerConfig = {
|
|
11575
|
+
failureThreshold: config3.resilience?.circuitBreaker?.failureThreshold ?? DEFAULT_CIRCUIT_BREAKER_CONFIG.failureThreshold,
|
|
11576
|
+
resetTimeoutMs: config3.resilience?.circuitBreaker?.resetTimeoutMs ?? DEFAULT_CIRCUIT_BREAKER_CONFIG.resetTimeoutMs,
|
|
11577
|
+
halfOpenMaxRequests: config3.resilience?.circuitBreaker?.halfOpenMaxRequests ?? DEFAULT_CIRCUIT_BREAKER_CONFIG.halfOpenMaxRequests
|
|
11578
|
+
};
|
|
11579
|
+
const keyType = detectKeyType(config3.apiKey);
|
|
11580
|
+
const apiClient = createBearerAPIClient(config3.apiKey, config3.baseUrl);
|
|
11581
|
+
const cache = new SimpleCache({
|
|
11582
|
+
maxSize: cacheMaxSize,
|
|
11583
|
+
ttl: cacheTTL,
|
|
11584
|
+
staleTtl: staleTtlMs
|
|
11585
|
+
});
|
|
11586
|
+
const circuitBreaker = new CircuitBreaker(circuitBreakerConfig);
|
|
11587
|
+
const prebuildDir = config3.resilience?.prebuildDir;
|
|
11588
|
+
const prebuildMod = prebuildDir ? getPrebuildModule() : null;
|
|
11589
|
+
const prebuildLoader = prebuildMod?.canUsePrebuild() && prebuildDir ? new prebuildMod.PrebuildLoader({
|
|
11590
|
+
prebuildDir,
|
|
11591
|
+
maxPrebuildAgeSec: config3.resilience?.maxPrebuildAgeSec
|
|
11592
|
+
}) : null;
|
|
11593
|
+
let lastStatus = null;
|
|
11594
|
+
let isDegraded = false;
|
|
11595
|
+
function emitStatus(source, data, details) {
|
|
11596
|
+
const status = {
|
|
11597
|
+
source,
|
|
11598
|
+
isPreview: details.isPreview,
|
|
11599
|
+
cacheKey: details.cacheKey,
|
|
11600
|
+
error: details.error,
|
|
11601
|
+
staleAgeSec: details.staleAgeSec,
|
|
11602
|
+
prebuildAgeSec: details.prebuildAgeSec,
|
|
11603
|
+
circuit: circuitBreaker.getState(),
|
|
11604
|
+
requestId: details.requestId,
|
|
11605
|
+
durationMs: details.durationMs
|
|
11606
|
+
};
|
|
11607
|
+
lastStatus = status;
|
|
11608
|
+
config3.resilience?.onStatusChange?.(status);
|
|
11609
|
+
const nowDegraded = source === "stale" || source === "error";
|
|
11610
|
+
if (nowDegraded !== isDegraded) {
|
|
11611
|
+
isDegraded = nowDegraded;
|
|
11612
|
+
config3.resilience?.onDegradedMode?.(nowDegraded, status);
|
|
11613
|
+
}
|
|
11614
|
+
return data;
|
|
11615
|
+
}
|
|
11616
|
+
async function resilientFetch(cacheKey, fetcher, options) {
|
|
11617
|
+
const requestId = generateRequestId2();
|
|
11618
|
+
const startTime = Date.now();
|
|
11619
|
+
const isPreview = options.preview ?? false;
|
|
11620
|
+
const statusDetails = (extra = {}) => ({
|
|
11621
|
+
requestId,
|
|
11622
|
+
cacheKey,
|
|
11623
|
+
isPreview,
|
|
11624
|
+
durationMs: Date.now() - startTime,
|
|
11625
|
+
...extra
|
|
11626
|
+
});
|
|
11627
|
+
if (cacheEnabled && !options.force) {
|
|
11628
|
+
const fresh = cache.getFresh(cacheKey);
|
|
11629
|
+
if (fresh !== null) {
|
|
11630
|
+
return emitStatus("cache", fresh, statusDetails());
|
|
11631
|
+
}
|
|
11632
|
+
}
|
|
11633
|
+
if (resilienceEnabled && circuitBreaker.isOpen()) {
|
|
11634
|
+
if (!isPreview && staleIfError) {
|
|
11635
|
+
const stale = cache.getStale(cacheKey);
|
|
11636
|
+
if (stale) {
|
|
11637
|
+
return emitStatus("stale", stale.value, statusDetails({
|
|
11638
|
+
staleAgeSec: stale.staleAgeSec,
|
|
11639
|
+
error: { code: "circuit_open", message: "Circuit breaker is open" }
|
|
11640
|
+
}));
|
|
11641
|
+
}
|
|
11642
|
+
}
|
|
11643
|
+
if (!isPreview && options.prebuildFallback) {
|
|
11644
|
+
const prebuildResult = options.prebuildFallback();
|
|
11645
|
+
if (prebuildResult) {
|
|
11646
|
+
return emitStatus("prebuild", prebuildResult.data, statusDetails({
|
|
11647
|
+
prebuildAgeSec: prebuildResult.prebuildAgeSec,
|
|
11648
|
+
error: { code: "circuit_open", message: "Circuit breaker is open" }
|
|
11649
|
+
}));
|
|
11650
|
+
}
|
|
11651
|
+
}
|
|
11652
|
+
const circuitState = circuitBreaker.getState();
|
|
11653
|
+
emitStatus("error", null, statusDetails({
|
|
11654
|
+
error: { code: "circuit_open", message: "Circuit breaker is open" }
|
|
11655
|
+
}));
|
|
11656
|
+
throw new CircuitOpenError(circuitState);
|
|
11657
|
+
}
|
|
11658
|
+
try {
|
|
11659
|
+
let data;
|
|
11660
|
+
if (resilienceEnabled) {
|
|
11661
|
+
if (circuitBreaker.getState().state === "half-open") {
|
|
11662
|
+
circuitBreaker.incrementHalfOpenRequests();
|
|
11663
|
+
}
|
|
11664
|
+
data = await fetchWithTimeoutAndRetry(
|
|
11665
|
+
async (timeoutSignal) => {
|
|
11666
|
+
const combinedSignal = options.signal ? combineAbortSignals(timeoutSignal, options.signal) : timeoutSignal;
|
|
11667
|
+
try {
|
|
11668
|
+
const response = await fetcher(combinedSignal);
|
|
11669
|
+
return unwrapResponse(response);
|
|
11670
|
+
} catch (error) {
|
|
11671
|
+
convertToTypedError(error);
|
|
11672
|
+
}
|
|
11673
|
+
},
|
|
11674
|
+
{
|
|
11675
|
+
...retryConfig,
|
|
11676
|
+
requestTimeoutMs
|
|
11677
|
+
}
|
|
11678
|
+
);
|
|
11679
|
+
circuitBreaker.recordSuccess();
|
|
11680
|
+
} else {
|
|
11681
|
+
try {
|
|
11682
|
+
const response = await fetcher(options.signal ?? new AbortController().signal);
|
|
11683
|
+
data = unwrapResponse(response);
|
|
11684
|
+
} catch (error) {
|
|
11685
|
+
convertToTypedError(error);
|
|
11686
|
+
}
|
|
11687
|
+
}
|
|
11688
|
+
if (cacheEnabled) {
|
|
11689
|
+
cache.set(cacheKey, data);
|
|
11690
|
+
}
|
|
11691
|
+
return emitStatus("live", data, statusDetails());
|
|
11692
|
+
} catch (error) {
|
|
11693
|
+
if (resilienceEnabled && error instanceof Error) {
|
|
11694
|
+
circuitBreaker.recordFailure(error);
|
|
11695
|
+
}
|
|
11696
|
+
if (!isPreview && staleIfError && cacheEnabled) {
|
|
11697
|
+
const stale = cache.getStale(cacheKey);
|
|
11698
|
+
if (stale) {
|
|
11699
|
+
const errorInfo2 = error instanceof RiverbankApiError ? { code: error.code, message: error.message } : { message: error.message };
|
|
11700
|
+
return emitStatus("stale", stale.value, statusDetails({
|
|
11701
|
+
staleAgeSec: stale.staleAgeSec,
|
|
11702
|
+
error: errorInfo2
|
|
11703
|
+
}));
|
|
11704
|
+
}
|
|
11705
|
+
}
|
|
11706
|
+
if (!isPreview && options.prebuildFallback) {
|
|
11707
|
+
const prebuildResult = options.prebuildFallback();
|
|
11708
|
+
if (prebuildResult) {
|
|
11709
|
+
const errorInfo2 = error instanceof RiverbankApiError ? { code: error.code, message: error.message } : { message: error.message };
|
|
11710
|
+
return emitStatus("prebuild", prebuildResult.data, statusDetails({
|
|
11711
|
+
prebuildAgeSec: prebuildResult.prebuildAgeSec,
|
|
11712
|
+
error: errorInfo2
|
|
11713
|
+
}));
|
|
11714
|
+
}
|
|
11715
|
+
}
|
|
11716
|
+
const errorInfo = error instanceof RiverbankApiError ? { code: error.code, message: error.message } : { message: error.message };
|
|
11717
|
+
emitStatus("error", null, statusDetails({ error: errorInfo }));
|
|
11718
|
+
throw error;
|
|
11719
|
+
}
|
|
11720
|
+
}
|
|
11721
|
+
function combineAbortSignals(...signals) {
|
|
11722
|
+
const controller = new AbortController();
|
|
11723
|
+
for (const signal of signals) {
|
|
11724
|
+
if (signal.aborted) {
|
|
11725
|
+
controller.abort(signal.reason);
|
|
11726
|
+
break;
|
|
11727
|
+
}
|
|
11728
|
+
signal.addEventListener("abort", () => controller.abort(signal.reason), { once: true });
|
|
11729
|
+
}
|
|
11730
|
+
return controller.signal;
|
|
11731
|
+
}
|
|
11732
|
+
return {
|
|
11733
|
+
async getSite(params) {
|
|
11734
|
+
const { slug, domain, id, signal } = params;
|
|
11735
|
+
if (!slug && !domain && !id) {
|
|
11736
|
+
throw new Error(
|
|
11737
|
+
`getSite() requires at least one identifier: slug, domain, or id. Received: ${JSON.stringify(params)}`
|
|
11738
|
+
);
|
|
11739
|
+
}
|
|
11740
|
+
const cacheKey = `site:${slug || domain || id}`;
|
|
11741
|
+
const siteId = id || slug || domain;
|
|
11742
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
11743
|
+
const apiParams = {};
|
|
11744
|
+
if (params.slug) apiParams.slug = params.slug;
|
|
11745
|
+
if (params.domain) apiParams.domain = params.domain;
|
|
11746
|
+
if (params.id) apiParams.id = params.id;
|
|
11747
|
+
return await apiClient({ endpoint: "getSite", params: apiParams, options: { signal: sig } });
|
|
11748
|
+
}, {
|
|
11749
|
+
signal,
|
|
11750
|
+
prebuildFallback: prebuildLoader && siteId ? () => prebuildLoader.loadSite(siteId) : void 0
|
|
11751
|
+
});
|
|
11752
|
+
},
|
|
11753
|
+
async getPage(params) {
|
|
11754
|
+
const { siteId, path: path13, preview = false, signal } = params;
|
|
11755
|
+
const cacheKey = `page:${siteId}:${path13}:${preview}`;
|
|
11756
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
11757
|
+
return await apiClient({ endpoint: "getContentByPath", params: { siteId }, body: { path: path13, preview }, options: { signal: sig } });
|
|
11758
|
+
}, {
|
|
11759
|
+
preview,
|
|
11760
|
+
signal,
|
|
11761
|
+
// Prebuild fallback only for published pages (not preview)
|
|
11762
|
+
prebuildFallback: prebuildLoader && !preview ? () => prebuildLoader.loadPage(siteId, path13) : void 0
|
|
11763
|
+
});
|
|
11764
|
+
},
|
|
11765
|
+
async getEntries(params) {
|
|
11766
|
+
const { siteId, contentType, limit, offset, order, preview = false, mode, entryIds, includeMeta, signal } = params;
|
|
11767
|
+
const entryIdsCacheKey = mode === "manual" && entryIds?.length ? entryIds.join(",") : "";
|
|
11768
|
+
const cacheKey = `entries:${siteId}:${contentType}:${limit ?? ""}:${offset ?? ""}:${order ?? ""}:${preview}:${mode ?? ""}:${entryIdsCacheKey}:${includeMeta ?? ""}`;
|
|
11769
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
11770
|
+
let orderParam;
|
|
11771
|
+
if (order === "newest") {
|
|
11772
|
+
orderParam = "published_at.desc";
|
|
11773
|
+
} else if (order === "oldest") {
|
|
11774
|
+
orderParam = "published_at.asc";
|
|
11775
|
+
} else if (order === "title") {
|
|
11776
|
+
orderParam = "title.asc";
|
|
11777
|
+
}
|
|
11778
|
+
const apiParams = {
|
|
11779
|
+
siteId,
|
|
11780
|
+
type: contentType,
|
|
11781
|
+
...typeof limit === "number" && { limit: String(limit) },
|
|
11782
|
+
...typeof offset === "number" && { offset: String(offset) },
|
|
11783
|
+
...includeMeta && { meta: "true" },
|
|
11784
|
+
...orderParam && { order: orderParam },
|
|
11785
|
+
...preview && { stage: "preview" },
|
|
11786
|
+
...mode === "manual" && entryIds?.length && {
|
|
11787
|
+
mode: "manual",
|
|
11788
|
+
entryIds: JSON.stringify(entryIds)
|
|
11789
|
+
}
|
|
11790
|
+
};
|
|
11791
|
+
return await apiClient({ endpoint: "listPublishedEntries", params: apiParams, options: { signal: sig } });
|
|
11792
|
+
}, {
|
|
11793
|
+
preview,
|
|
11794
|
+
signal,
|
|
11795
|
+
// Prebuild fallback only for published entries (not preview, not manual mode)
|
|
11796
|
+
prebuildFallback: prebuildLoader && !preview ? () => prebuildLoader.loadEntries(siteId, params) : void 0
|
|
11797
|
+
});
|
|
11798
|
+
},
|
|
11799
|
+
async getEntry(params) {
|
|
11800
|
+
const { siteId, contentType, slug, signal } = params;
|
|
11801
|
+
const cacheKey = `entry:${siteId}:${contentType}:${slug}`;
|
|
11802
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
11803
|
+
return await apiClient({ endpoint: "getPublishedEntryPreview", params: { siteId, type: contentType, slug }, options: { signal: sig } });
|
|
11804
|
+
}, { signal });
|
|
11805
|
+
},
|
|
11806
|
+
async getPublicFormById(params) {
|
|
11807
|
+
const { formId, signal } = params;
|
|
11808
|
+
if (!formId) {
|
|
11809
|
+
throw new Error("getPublicFormById() requires formId");
|
|
11810
|
+
}
|
|
11811
|
+
const cacheKey = `public-form:${formId}`;
|
|
11812
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
11813
|
+
return await apiClient({ endpoint: "getPublicFormById", params: { formId }, options: { signal: sig } });
|
|
11814
|
+
}, { signal });
|
|
11815
|
+
},
|
|
11816
|
+
async getPublicBookingServices(params) {
|
|
11817
|
+
const { siteId, ids, signal } = params;
|
|
11818
|
+
if (!siteId) {
|
|
11819
|
+
throw new Error("getPublicBookingServices() requires siteId");
|
|
11820
|
+
}
|
|
11821
|
+
const cacheKey = `public-booking-services:${siteId}:${ids ?? ""}`;
|
|
11822
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
11823
|
+
const apiParams = {
|
|
11824
|
+
siteId,
|
|
11825
|
+
...ids && { ids }
|
|
11826
|
+
};
|
|
11827
|
+
return await apiClient({ endpoint: "getPublicBookingServices", params: apiParams, options: { signal: sig } });
|
|
11828
|
+
}, { signal });
|
|
11829
|
+
},
|
|
11830
|
+
async listPublicEvents(params) {
|
|
11831
|
+
const { siteId, limit, from, to, stage, signal } = params;
|
|
11832
|
+
if (!siteId) {
|
|
11833
|
+
throw new Error("listPublicEvents() requires siteId");
|
|
11834
|
+
}
|
|
11835
|
+
const cacheKey = `public-events:${siteId}:${limit ?? ""}:${from ?? ""}:${to ?? ""}:${stage ?? ""}`;
|
|
11836
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
11837
|
+
const apiParams = {
|
|
11838
|
+
siteId,
|
|
11839
|
+
...typeof limit === "number" && { limit: String(limit) },
|
|
11840
|
+
...from && { from },
|
|
11841
|
+
...to && { to },
|
|
11842
|
+
...stage && { stage }
|
|
11843
|
+
};
|
|
11844
|
+
return await apiClient({ endpoint: "listPublicEvents", params: apiParams, options: { signal: sig } });
|
|
11845
|
+
}, { signal });
|
|
11846
|
+
},
|
|
11847
|
+
async resolveEventOccurrence(params) {
|
|
11848
|
+
const { siteId, entryId, segment, signal } = params;
|
|
11849
|
+
if (!siteId || !entryId || !segment) {
|
|
11850
|
+
throw new Error("resolveEventOccurrence() requires siteId, entryId, and segment");
|
|
11851
|
+
}
|
|
11852
|
+
const cacheKey = `event-occurrence:${siteId}:${entryId}:${segment}`;
|
|
11853
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
11854
|
+
return await apiClient({
|
|
11855
|
+
endpoint: "resolveEventOccurrence",
|
|
11856
|
+
params: { siteId, entryId, segment },
|
|
11857
|
+
options: { signal: sig }
|
|
11858
|
+
});
|
|
11859
|
+
}, { signal });
|
|
11860
|
+
},
|
|
11861
|
+
async checkRedirect(params) {
|
|
11862
|
+
const { siteId, path: path13, signal } = params;
|
|
11863
|
+
if (!siteId || !path13) {
|
|
11864
|
+
throw new Error("checkRedirect() requires siteId and path");
|
|
11865
|
+
}
|
|
11866
|
+
const cacheKey = `redirect:${siteId}:${path13}`;
|
|
11867
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
11868
|
+
return await apiClient({
|
|
11869
|
+
endpoint: "checkRedirect",
|
|
11870
|
+
params: { site: siteId, path: path13 },
|
|
11871
|
+
options: { signal: sig }
|
|
11872
|
+
});
|
|
11873
|
+
}, { signal });
|
|
11874
|
+
},
|
|
11875
|
+
async getAllPublishedRoutes(params) {
|
|
11876
|
+
const { siteId, signal } = params;
|
|
11877
|
+
if (!siteId) {
|
|
11878
|
+
throw new Error("getAllPublishedRoutes() requires siteId");
|
|
11879
|
+
}
|
|
11880
|
+
const cacheKey = `routable-content:${siteId}:published`;
|
|
11881
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
11882
|
+
return await apiClient({
|
|
11883
|
+
endpoint: "getPublicRoutableContent",
|
|
11884
|
+
params: { siteId, publishedOnly: "true" },
|
|
11885
|
+
options: { signal: sig }
|
|
11886
|
+
});
|
|
11887
|
+
}, { signal });
|
|
11888
|
+
},
|
|
11889
|
+
clearCache() {
|
|
11890
|
+
cache.clear();
|
|
11891
|
+
},
|
|
11892
|
+
getKeyType() {
|
|
11893
|
+
return keyType;
|
|
11894
|
+
},
|
|
11895
|
+
getLastEmittedStatus() {
|
|
11896
|
+
return lastStatus;
|
|
11897
|
+
},
|
|
11898
|
+
getCircuitState() {
|
|
11899
|
+
return circuitBreaker.getState();
|
|
11900
|
+
}
|
|
11901
|
+
};
|
|
11902
|
+
}
|
|
11903
|
+
init_constants();
|
|
11904
|
+
var MANIFEST_VERSION = "1.0.0";
|
|
11905
|
+
var MANIFEST_FILENAME = "manifest.json";
|
|
11906
|
+
function pathToFilename(routePath) {
|
|
11907
|
+
if (routePath === "/") return "_home.json";
|
|
11908
|
+
return routePath.slice(1).replace(/[^a-zA-Z0-9\-\/]/g, "_").replace(/\//g, "-") + ".json";
|
|
11909
|
+
}
|
|
11910
|
+
function ensureDir3(dirPath) {
|
|
11911
|
+
if (!fs6__namespace.existsSync(dirPath)) {
|
|
11912
|
+
fs6__namespace.mkdirSync(dirPath, { recursive: true });
|
|
11913
|
+
}
|
|
11914
|
+
}
|
|
11915
|
+
function writeJsonFile2(filePath, data) {
|
|
11916
|
+
const content = JSON.stringify(data, null, 2);
|
|
11917
|
+
fs6__namespace.writeFileSync(filePath, content, "utf-8");
|
|
11918
|
+
return Buffer.byteLength(content, "utf-8");
|
|
11919
|
+
}
|
|
11920
|
+
function calculateChecksum(data) {
|
|
11921
|
+
const { checksum: _, ...rest } = data;
|
|
11922
|
+
const content = JSON.stringify(rest);
|
|
11923
|
+
return crypto2__namespace.createHash("sha256").update(content).digest("hex");
|
|
11924
|
+
}
|
|
11925
|
+
async function fetchAllEntries(client, siteId, contentType, onProgress) {
|
|
11926
|
+
const allEntries = [];
|
|
11927
|
+
let offset = 0;
|
|
11928
|
+
let hasMore = true;
|
|
11929
|
+
while (hasMore) {
|
|
11930
|
+
onProgress?.(`${contentType} (batch ${Math.floor(offset / PREBUILD_PAGE_SIZE) + 1})`);
|
|
11931
|
+
const response = await client.getEntries({
|
|
11932
|
+
siteId,
|
|
11933
|
+
contentType,
|
|
11934
|
+
limit: PREBUILD_PAGE_SIZE,
|
|
11935
|
+
offset,
|
|
11936
|
+
preview: false
|
|
11937
|
+
// Published content only
|
|
11938
|
+
});
|
|
11939
|
+
allEntries.push(...response.entries);
|
|
11940
|
+
offset += PREBUILD_PAGE_SIZE;
|
|
11941
|
+
hasMore = response.entries.length === PREBUILD_PAGE_SIZE;
|
|
11942
|
+
}
|
|
11943
|
+
return allEntries;
|
|
11944
|
+
}
|
|
11945
|
+
async function prebuildSite(client, siteId, outputDir) {
|
|
11946
|
+
const site = await client.getSite({ id: siteId });
|
|
11947
|
+
const filename = "site.json";
|
|
11948
|
+
const filePath = path9__namespace.join(outputDir, filename);
|
|
11949
|
+
const cacheFile = {
|
|
11950
|
+
data: site,
|
|
11951
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
11952
|
+
};
|
|
11953
|
+
const size = writeJsonFile2(filePath, cacheFile);
|
|
11954
|
+
return { files: [filename], size, siteData: site };
|
|
11955
|
+
}
|
|
11956
|
+
async function prebuildPages(client, siteId, routes, outputDir, onProgress) {
|
|
11957
|
+
const pagesDir = path9__namespace.join(outputDir, "pages");
|
|
11958
|
+
ensureDir3(pagesDir);
|
|
11959
|
+
const files = [];
|
|
11960
|
+
let totalSize = 0;
|
|
11961
|
+
const publishedPaths = Object.entries(routes).filter(([_, route]) => route.status === "published").map(([_, route]) => route.path);
|
|
11962
|
+
const pageIndex = [];
|
|
11963
|
+
const total = publishedPaths.length;
|
|
11964
|
+
let current = 0;
|
|
11965
|
+
for (const pagePath of publishedPaths) {
|
|
11966
|
+
current++;
|
|
11967
|
+
onProgress?.({
|
|
11968
|
+
current,
|
|
11969
|
+
total,
|
|
11970
|
+
item: `Page: ${pagePath}`,
|
|
11971
|
+
contentType: "pages"
|
|
11972
|
+
});
|
|
11973
|
+
try {
|
|
11974
|
+
const pageData = await client.getPage({ siteId, path: pagePath, preview: false });
|
|
11975
|
+
const filename = pathToFilename(pagePath);
|
|
11976
|
+
const filePath = path9__namespace.join(pagesDir, filename);
|
|
11977
|
+
const cacheFile = {
|
|
11978
|
+
data: pageData,
|
|
11979
|
+
path: pagePath,
|
|
11980
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
11981
|
+
};
|
|
11982
|
+
totalSize += writeJsonFile2(filePath, cacheFile);
|
|
11983
|
+
files.push(`pages/${filename}`);
|
|
11984
|
+
if ("page" in pageData) {
|
|
11985
|
+
pageIndex.push({
|
|
11986
|
+
path: pagePath,
|
|
11987
|
+
pageId: pageData.page.routeId || "",
|
|
11988
|
+
title: pageData.page.name || "Untitled"
|
|
11989
|
+
});
|
|
11990
|
+
}
|
|
11991
|
+
} catch (error) {
|
|
11992
|
+
console.warn(`[Prebuild] Failed to fetch page ${pagePath}:`, error.message);
|
|
11993
|
+
}
|
|
11994
|
+
}
|
|
11995
|
+
const indexFile = {
|
|
11996
|
+
pages: pageIndex,
|
|
11997
|
+
totalCount: pageIndex.length,
|
|
11998
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
11999
|
+
};
|
|
12000
|
+
const indexPath = path9__namespace.join(pagesDir, "_index.json");
|
|
12001
|
+
totalSize += writeJsonFile2(indexPath, indexFile);
|
|
12002
|
+
files.push("pages/_index.json");
|
|
12003
|
+
return { files, size: totalSize };
|
|
12004
|
+
}
|
|
12005
|
+
async function prebuildEntries(client, siteId, contentTypes, outputDir, onProgress) {
|
|
12006
|
+
const entriesDir = path9__namespace.join(outputDir, "entries");
|
|
12007
|
+
ensureDir3(entriesDir);
|
|
12008
|
+
const files = [];
|
|
12009
|
+
let totalSize = 0;
|
|
12010
|
+
const total = contentTypes.length;
|
|
12011
|
+
let current = 0;
|
|
12012
|
+
for (const contentType of contentTypes) {
|
|
12013
|
+
current++;
|
|
12014
|
+
const entries = await fetchAllEntries(
|
|
12015
|
+
client,
|
|
12016
|
+
siteId,
|
|
12017
|
+
contentType,
|
|
12018
|
+
(item) => {
|
|
12019
|
+
onProgress?.({
|
|
12020
|
+
current,
|
|
12021
|
+
total,
|
|
12022
|
+
item: `Entries: ${item}`,
|
|
12023
|
+
contentType: "entries"
|
|
12024
|
+
});
|
|
12025
|
+
}
|
|
12026
|
+
);
|
|
12027
|
+
const typeDir = path9__namespace.join(entriesDir, contentType);
|
|
12028
|
+
ensureDir3(typeDir);
|
|
12029
|
+
const cacheFile = {
|
|
12030
|
+
entries,
|
|
12031
|
+
contentType,
|
|
12032
|
+
totalCount: entries.length,
|
|
12033
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
12034
|
+
};
|
|
12035
|
+
const filename = `entries/${contentType}/all.json`;
|
|
12036
|
+
const filePath = path9__namespace.join(entriesDir, contentType, "all.json");
|
|
12037
|
+
totalSize += writeJsonFile2(filePath, cacheFile);
|
|
12038
|
+
files.push(filename);
|
|
12039
|
+
}
|
|
12040
|
+
return { files, size: totalSize };
|
|
12041
|
+
}
|
|
12042
|
+
async function prebuildNavigation(siteData, outputDir, onProgress) {
|
|
12043
|
+
const navDir = path9__namespace.join(outputDir, "navigation");
|
|
12044
|
+
ensureDir3(navDir);
|
|
12045
|
+
const files = [];
|
|
12046
|
+
let totalSize = 0;
|
|
12047
|
+
const menus = siteData.navigation || [];
|
|
12048
|
+
onProgress?.({
|
|
12049
|
+
current: 1,
|
|
12050
|
+
total: 1,
|
|
12051
|
+
item: "Navigation menus",
|
|
12052
|
+
contentType: "navigation"
|
|
12053
|
+
});
|
|
12054
|
+
const cacheFile = {
|
|
12055
|
+
menus: menus.map((menu) => ({
|
|
12056
|
+
identifier: menu.identifier,
|
|
12057
|
+
id: menu.id,
|
|
12058
|
+
name: menu.name,
|
|
12059
|
+
items: menu.items
|
|
12060
|
+
})),
|
|
12061
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
12062
|
+
};
|
|
12063
|
+
const filename = "navigation/menus.json";
|
|
12064
|
+
const filePath = path9__namespace.join(navDir, "menus.json");
|
|
12065
|
+
totalSize += writeJsonFile2(filePath, cacheFile);
|
|
12066
|
+
files.push(filename);
|
|
12067
|
+
return { files, size: totalSize };
|
|
12068
|
+
}
|
|
12069
|
+
async function prebuildCache(options) {
|
|
12070
|
+
const {
|
|
12071
|
+
client,
|
|
12072
|
+
siteId,
|
|
12073
|
+
outputDir = DEFAULT_PREBUILD_DIR,
|
|
12074
|
+
include = ["site", "pages", "entries", "navigation"],
|
|
12075
|
+
contentTypes,
|
|
12076
|
+
onProgress
|
|
12077
|
+
} = options;
|
|
12078
|
+
const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
12079
|
+
const files = [];
|
|
12080
|
+
let totalSize = 0;
|
|
12081
|
+
const errors = [];
|
|
12082
|
+
let siteData = null;
|
|
12083
|
+
ensureDir3(outputDir);
|
|
12084
|
+
if (include.includes("site") || include.includes("pages") || include.includes("navigation")) {
|
|
12085
|
+
try {
|
|
12086
|
+
const result = await prebuildSite(client, siteId, outputDir);
|
|
12087
|
+
siteData = result.siteData;
|
|
12088
|
+
if (include.includes("site")) {
|
|
12089
|
+
files.push(...result.files);
|
|
12090
|
+
totalSize += result.size;
|
|
12091
|
+
}
|
|
12092
|
+
onProgress?.({ current: 1, total: 4, item: "Site data", contentType: "site" });
|
|
12093
|
+
} catch (error) {
|
|
12094
|
+
errors.push(`Site prebuild failed: ${error.message}`);
|
|
12095
|
+
}
|
|
12096
|
+
}
|
|
12097
|
+
if (include.includes("pages") && siteData) {
|
|
12098
|
+
try {
|
|
12099
|
+
const result = await prebuildPages(
|
|
12100
|
+
client,
|
|
12101
|
+
siteId,
|
|
12102
|
+
siteData.routes,
|
|
12103
|
+
outputDir,
|
|
12104
|
+
onProgress
|
|
12105
|
+
);
|
|
12106
|
+
files.push(...result.files);
|
|
12107
|
+
totalSize += result.size;
|
|
12108
|
+
} catch (error) {
|
|
12109
|
+
errors.push(`Pages prebuild failed: ${error.message}`);
|
|
12110
|
+
}
|
|
12111
|
+
}
|
|
12112
|
+
if (include.includes("entries")) {
|
|
12113
|
+
try {
|
|
12114
|
+
const typesToPrebuild = contentTypes || [];
|
|
12115
|
+
if (typesToPrebuild.length > 0) {
|
|
12116
|
+
const result = await prebuildEntries(
|
|
12117
|
+
client,
|
|
12118
|
+
siteId,
|
|
12119
|
+
typesToPrebuild,
|
|
12120
|
+
outputDir,
|
|
12121
|
+
onProgress
|
|
12122
|
+
);
|
|
12123
|
+
files.push(...result.files);
|
|
12124
|
+
totalSize += result.size;
|
|
12125
|
+
} else {
|
|
12126
|
+
console.warn("[Prebuild] No contentTypes provided - skipping entries prebuild");
|
|
12127
|
+
}
|
|
12128
|
+
} catch (error) {
|
|
12129
|
+
errors.push(`Entries prebuild failed: ${error.message}`);
|
|
12130
|
+
}
|
|
12131
|
+
}
|
|
12132
|
+
if (include.includes("navigation") && siteData) {
|
|
12133
|
+
try {
|
|
12134
|
+
const result = await prebuildNavigation(siteData, outputDir, onProgress);
|
|
12135
|
+
files.push(...result.files);
|
|
12136
|
+
totalSize += result.size;
|
|
12137
|
+
} catch (error) {
|
|
12138
|
+
errors.push(`Navigation prebuild failed: ${error.message}`);
|
|
12139
|
+
}
|
|
12140
|
+
}
|
|
12141
|
+
const keyToFile = {};
|
|
12142
|
+
if (files.includes("site.json")) {
|
|
12143
|
+
keyToFile[`site:${siteId}`] = "site.json";
|
|
12144
|
+
}
|
|
12145
|
+
for (const file of files) {
|
|
12146
|
+
if (file.startsWith("pages/") && file !== "pages/_index.json") {
|
|
12147
|
+
const filename = file.replace("pages/", "").replace(".json", "");
|
|
12148
|
+
const pagePath = filename === "_home" ? "/" : "/" + filename.replace(/-/g, "/");
|
|
12149
|
+
keyToFile[`page:${siteId}:${pagePath}:false`] = file;
|
|
12150
|
+
}
|
|
12151
|
+
if (file.startsWith("entries/") && file.endsWith("/all.json")) {
|
|
12152
|
+
const contentType = file.split("/")[1];
|
|
12153
|
+
keyToFile[`entries-all:${siteId}:${contentType}`] = file;
|
|
12154
|
+
}
|
|
12155
|
+
}
|
|
12156
|
+
const manifest = {
|
|
12157
|
+
version: MANIFEST_VERSION,
|
|
12158
|
+
generatedAt,
|
|
12159
|
+
siteId,
|
|
12160
|
+
sdkVersion: SDK_VERSION,
|
|
12161
|
+
keyToFile,
|
|
12162
|
+
includedTypes: include,
|
|
12163
|
+
fileCount: files.length,
|
|
12164
|
+
totalSize
|
|
12165
|
+
};
|
|
12166
|
+
const checksum = calculateChecksum(manifest);
|
|
12167
|
+
manifest.checksum = checksum;
|
|
12168
|
+
const manifestPath = path9__namespace.join(outputDir, MANIFEST_FILENAME);
|
|
12169
|
+
writeJsonFile2(manifestPath, manifest);
|
|
12170
|
+
return {
|
|
12171
|
+
success: errors.length === 0,
|
|
12172
|
+
outputDir,
|
|
12173
|
+
files,
|
|
12174
|
+
totalSize,
|
|
12175
|
+
generatedAt,
|
|
12176
|
+
checksum,
|
|
12177
|
+
errors: errors.length > 0 ? errors : void 0
|
|
12178
|
+
};
|
|
12179
|
+
}
|
|
12180
|
+
|
|
12181
|
+
// src/cli/commands/deploy.ts
|
|
12182
|
+
init_constants();
|
|
12183
|
+
async function loadDeployConfig() {
|
|
12184
|
+
const rawConfig = await loadConfigFile();
|
|
12185
|
+
const config3 = rawConfig;
|
|
12186
|
+
if (!config3.siteId) {
|
|
12187
|
+
throw new Error("siteId is required in riverbank.config.ts");
|
|
12188
|
+
}
|
|
12189
|
+
const contentTypes = config3.content?.contentTypes?.map((ct) => ct.key);
|
|
12190
|
+
return {
|
|
12191
|
+
siteId: config3.siteId,
|
|
12192
|
+
deploy: config3.deploy ?? {},
|
|
12193
|
+
contentTypes
|
|
12194
|
+
};
|
|
12195
|
+
}
|
|
12196
|
+
async function checkWorkingDirectoryClean(git, prebuildOutput) {
|
|
12197
|
+
const status = await git.status();
|
|
12198
|
+
const dirtyFiles = status.files.map((f) => f.path).filter((path13) => !path13.startsWith(prebuildOutput));
|
|
12199
|
+
return {
|
|
12200
|
+
clean: dirtyFiles.length === 0,
|
|
12201
|
+
dirtyFiles
|
|
12202
|
+
};
|
|
12203
|
+
}
|
|
12204
|
+
async function commitCacheIfChanged(git, prebuildOutput) {
|
|
12205
|
+
const status = await git.status();
|
|
12206
|
+
const cacheChanges = status.files.filter((f) => f.path.startsWith(prebuildOutput));
|
|
12207
|
+
if (cacheChanges.length === 0) {
|
|
12208
|
+
return false;
|
|
12209
|
+
}
|
|
12210
|
+
await git.add(prebuildOutput);
|
|
12211
|
+
const log = await git.log({ maxCount: 1 });
|
|
12212
|
+
const lastCommit = log.latest;
|
|
12213
|
+
const isLastCommitCache = lastCommit?.message.startsWith("chore: update prebuild cache");
|
|
12214
|
+
let isUnpushed = false;
|
|
12215
|
+
if (isLastCommitCache && lastCommit) {
|
|
12216
|
+
try {
|
|
12217
|
+
const branches = await git.branch(["-r", "--contains", lastCommit.hash]);
|
|
12218
|
+
isUnpushed = branches.all.length === 0;
|
|
12219
|
+
} catch (error) {
|
|
12220
|
+
if (process.env.DEBUG) {
|
|
12221
|
+
console.debug("[deploy] Could not check remote branches:", error);
|
|
12222
|
+
}
|
|
12223
|
+
isUnpushed = true;
|
|
12224
|
+
}
|
|
12225
|
+
}
|
|
12226
|
+
if (isLastCommitCache && isUnpushed) {
|
|
12227
|
+
await git.commit([], { "--amend": null, "--no-edit": null });
|
|
12228
|
+
} else {
|
|
12229
|
+
await git.commit("chore: update prebuild cache");
|
|
12230
|
+
}
|
|
12231
|
+
return true;
|
|
12232
|
+
}
|
|
12233
|
+
var deployCommand = new commander.Command("deploy").description("Deploy site with prebuild cache generation").option("--preview", "Preview deploy - skip prebuild cache generation").addHelpText("after", `
|
|
12234
|
+
Examples:
|
|
12235
|
+
$ riverbankcms deploy # Full deploy with cache generation
|
|
12236
|
+
$ riverbankcms deploy --preview # Deploy without regenerating cache
|
|
12237
|
+
|
|
12238
|
+
Configuration (riverbank.config.ts):
|
|
12239
|
+
deploy: {
|
|
12240
|
+
verifyCommand: 'pnpm verify', // Command to run before deploy
|
|
12241
|
+
prebuildOutput: '.riverbank-cache', // Prebuild output directory
|
|
12242
|
+
}
|
|
12243
|
+
|
|
12244
|
+
Workflow:
|
|
12245
|
+
1. Run verifyCommand (if configured)
|
|
12246
|
+
2. Check working directory is clean
|
|
12247
|
+
3. Generate prebuild cache (unless --preview)
|
|
12248
|
+
4. Commit cache changes (squashes consecutive unpushed commits)
|
|
12249
|
+
5. Push to remote
|
|
12250
|
+
|
|
12251
|
+
Notes:
|
|
12252
|
+
- Requires git repository with remote configured
|
|
12253
|
+
- CMS failure during prebuild continues with existing cache
|
|
12254
|
+
- Uses --remote environment variables for API access
|
|
12255
|
+
`).action(async (options, command) => {
|
|
12256
|
+
const { output } = getOutputContext(command);
|
|
12257
|
+
const git = simpleGit__default.default();
|
|
12258
|
+
try {
|
|
12259
|
+
if (!await git.checkIsRepo()) {
|
|
12260
|
+
return output.error("Not a git repository", {
|
|
12261
|
+
suggestion: "Run this command from your project root directory"
|
|
12262
|
+
});
|
|
12263
|
+
}
|
|
12264
|
+
output.info("Loading configuration...");
|
|
12265
|
+
const config3 = await loadDeployConfig();
|
|
12266
|
+
const prebuildOutput = config3.deploy.prebuildOutput ?? DEFAULT_PREBUILD_DIR;
|
|
12267
|
+
if (config3.deploy.verifyCommand) {
|
|
12268
|
+
output.info(`Running verification: ${config3.deploy.verifyCommand}`);
|
|
12269
|
+
try {
|
|
12270
|
+
child_process.execSync(config3.deploy.verifyCommand, { stdio: "inherit" });
|
|
12271
|
+
output.success("Verification passed");
|
|
12272
|
+
} catch {
|
|
12273
|
+
return output.error("Verification failed", {
|
|
12274
|
+
suggestion: "Fix the issues reported by the verify command and try again"
|
|
12275
|
+
});
|
|
12276
|
+
}
|
|
12277
|
+
} else {
|
|
12278
|
+
output.warn("No verifyCommand configured, skipping verification");
|
|
12279
|
+
}
|
|
12280
|
+
const { clean, dirtyFiles } = await checkWorkingDirectoryClean(git, prebuildOutput);
|
|
12281
|
+
if (!clean) {
|
|
12282
|
+
output.warn("Uncommitted changes detected:");
|
|
12283
|
+
dirtyFiles.slice(0, 5).forEach((f) => output.warn(` - ${f}`));
|
|
12284
|
+
if (dirtyFiles.length > 5) {
|
|
12285
|
+
output.warn(` ... and ${dirtyFiles.length - 5} more files`);
|
|
12286
|
+
}
|
|
12287
|
+
return output.error("Working directory not clean", {
|
|
12288
|
+
suggestion: "Commit or stash your changes before deploying"
|
|
12289
|
+
});
|
|
12290
|
+
}
|
|
12291
|
+
if (!options.preview) {
|
|
12292
|
+
output.info("Generating prebuild cache...");
|
|
12293
|
+
try {
|
|
12294
|
+
const env = loadEnvironment(true);
|
|
12295
|
+
const client = createRiverbankClient({
|
|
12296
|
+
apiKey: env.managementApiKey,
|
|
12297
|
+
baseUrl: env.dashboardUrl
|
|
12298
|
+
});
|
|
12299
|
+
const result = await prebuildCache({
|
|
12300
|
+
client,
|
|
12301
|
+
siteId: config3.siteId,
|
|
12302
|
+
outputDir: prebuildOutput,
|
|
12303
|
+
contentTypes: config3.contentTypes,
|
|
12304
|
+
onProgress: (p) => {
|
|
12305
|
+
output.info(` ${p.item}`);
|
|
12306
|
+
}
|
|
12307
|
+
});
|
|
12308
|
+
if (result.success) {
|
|
12309
|
+
output.success(`Prebuild complete: ${result.files.length} files (${formatBytes(result.totalSize)})`);
|
|
12310
|
+
} else {
|
|
12311
|
+
output.warn("Prebuild completed with errors:");
|
|
12312
|
+
result.errors?.forEach((e) => output.warn(` - ${e}`));
|
|
12313
|
+
}
|
|
12314
|
+
const committed = await commitCacheIfChanged(git, prebuildOutput);
|
|
12315
|
+
if (committed) {
|
|
12316
|
+
output.success("Cache committed");
|
|
12317
|
+
} else {
|
|
12318
|
+
output.info("Cache unchanged, no commit needed");
|
|
12319
|
+
}
|
|
12320
|
+
} catch (error) {
|
|
12321
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
12322
|
+
output.warn(`Prebuild failed: ${message}`);
|
|
12323
|
+
output.warn("Continuing with existing cache...");
|
|
12324
|
+
}
|
|
12325
|
+
} else {
|
|
12326
|
+
output.info("Skipping prebuild cache (--preview mode)");
|
|
12327
|
+
}
|
|
12328
|
+
output.info("Pushing to remote...");
|
|
12329
|
+
try {
|
|
12330
|
+
await git.push();
|
|
12331
|
+
output.success("Deploy triggered successfully!");
|
|
12332
|
+
} catch (error) {
|
|
12333
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
12334
|
+
return output.error(`Push failed: ${message}`, {
|
|
12335
|
+
suggestion: "Check your git remote configuration and permissions"
|
|
12336
|
+
});
|
|
12337
|
+
}
|
|
12338
|
+
} catch (error) {
|
|
12339
|
+
handleCommandError(error, output);
|
|
12340
|
+
}
|
|
12341
|
+
});
|
|
12342
|
+
function formatBytes(bytes) {
|
|
12343
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
12344
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
12345
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
12346
|
+
}
|
|
12347
|
+
|
|
8695
12348
|
// src/cli/index.ts
|
|
8696
12349
|
dotenv.config({ path: ".env.local" });
|
|
8697
12350
|
dotenv.config({ path: ".env" });
|
|
@@ -8729,6 +12382,7 @@ program.addCommand(deleteCommand);
|
|
|
8729
12382
|
program.addCommand(previewCommand);
|
|
8730
12383
|
program.addCommand(initDocsCommand);
|
|
8731
12384
|
program.addCommand(identifiersCommand);
|
|
12385
|
+
program.addCommand(deployCommand);
|
|
8732
12386
|
program.parse();
|
|
8733
12387
|
//# sourceMappingURL=index.js.map
|
|
8734
12388
|
//# sourceMappingURL=index.js.map
|