@riverbankcms/sdk 0.7.0 → 0.7.3
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 +229 -0
- package/dist/cli/index.js +42 -95
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init-docs/content/agents-section.md +50 -0
- package/dist/cli/init-docs/content/cli-reference.md +574 -0
- package/dist/cli/init-docs/content/content-management.md +384 -0
- package/dist/cli/init-docs/content/context-brand.md +125 -0
- package/dist/cli/init-docs/content/context-brief.md +77 -0
- package/dist/cli/init-docs/content/context-knowledge.md +111 -0
- package/dist/cli/init-docs/content/getting-started.md +130 -0
- package/dist/cli/init-docs/content/site-workflows-readme.md +96 -0
- package/dist/cli/init-docs/content/workflow-add-block.md +228 -0
- package/dist/cli/init-docs/content/workflow-create-page.md +193 -0
- package/dist/cli/init-docs/content/workflow-publish.md +280 -0
- package/dist/client/bookings.d.mts +2 -0
- package/dist/client/bookings.d.ts +2 -0
- package/dist/client/bookings.js +2956 -104
- package/dist/client/bookings.js.map +1 -1
- package/dist/client/bookings.mjs +2929 -70
- package/dist/client/bookings.mjs.map +1 -1
- package/dist/client/client.d.mts +2 -2
- package/dist/client/client.d.ts +2 -2
- package/dist/client/client.js +602 -68
- package/dist/client/client.js.map +1 -1
- package/dist/client/client.mjs +602 -68
- 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/rendering/client.js +3070 -259
- package/dist/client/rendering/client.js.map +1 -1
- package/dist/client/rendering/client.mjs +3212 -395
- package/dist/client/rendering/client.mjs.map +1 -1
- package/dist/client/spam-protection.d.mts +55 -0
- package/dist/client/spam-protection.d.ts +55 -0
- package/dist/client/spam-protection.js +2915 -0
- package/dist/client/spam-protection.js.map +1 -0
- package/dist/client/spam-protection.mjs +2893 -0
- package/dist/client/spam-protection.mjs.map +1 -0
- package/dist/client/{usePage-BiOReg0_.d.ts → usePage-BYmJCCm1.d.ts} +132 -11
- package/dist/client/{usePage-BXjk8BhD.d.mts → usePage-DZtrWajy.d.mts} +132 -11
- package/dist/server/{Layout-wBtJLTVX.d.ts → Layout-Yluyb6sK.d.ts} +1 -1
- package/dist/server/{Layout-B7cvis7r.d.mts → Layout-qWLdVm5-.d.mts} +1 -1
- package/dist/server/chunk-2IZ6S225.js +122 -0
- package/dist/server/chunk-2IZ6S225.js.map +1 -0
- package/dist/server/chunk-4CV4JOE5.js +27 -0
- package/dist/server/chunk-4CV4JOE5.js.map +1 -0
- package/dist/server/chunk-5LRR64Y6.mjs +72 -0
- package/dist/server/chunk-5LRR64Y6.mjs.map +1 -0
- package/dist/server/chunk-NBTRDLCM.js +72 -0
- package/dist/server/chunk-NBTRDLCM.js.map +1 -0
- package/dist/server/chunk-NFEGQTCC.mjs +27 -0
- package/dist/server/{chunk-7FIJSGHU.mjs → chunk-NFQLH5IA.mjs} +856 -74
- package/dist/server/chunk-NFQLH5IA.mjs.map +1 -0
- package/dist/server/chunk-PPHZV6YD.mjs +122 -0
- package/dist/server/chunk-PPHZV6YD.mjs.map +1 -0
- package/dist/server/{chunk-P7UVAMK6.js → chunk-VLXTNB2C.js} +866 -84
- package/dist/server/chunk-VLXTNB2C.js.map +1 -0
- package/dist/server/{components-CMMwDXTW.d.mts → components-DNHfSCML.d.mts} +3 -3
- package/dist/server/{components-CICSJyp_.d.ts → components-Di5ME6He.d.ts} +3 -3
- package/dist/server/components.d.mts +5 -5
- package/dist/server/components.d.ts +5 -5
- package/dist/server/components.js +1 -1
- package/dist/server/components.mjs +1 -1
- package/dist/server/config-validation.js +1 -1
- package/dist/server/config-validation.mjs +1 -1
- package/dist/server/config.js +1 -1
- package/dist/server/config.mjs +1 -1
- package/dist/server/data.d.mts +2 -2
- package/dist/server/data.d.ts +2 -2
- package/dist/server/data.js +1 -1
- package/dist/server/data.mjs +1 -1
- package/dist/server/env.d.mts +109 -0
- package/dist/server/env.d.ts +109 -0
- package/dist/server/env.js +14 -0
- package/dist/server/env.js.map +1 -0
- package/dist/server/env.mjs +14 -0
- package/dist/server/{index-DI_qlYx3.d.mts → index--Oyunk_B.d.mts} +2 -2
- package/dist/server/{index-BTwWvSBu.d.ts → index-C9Ra8dza.d.ts} +2 -2
- package/dist/server/{index-Bucs6UqG.d.mts → index-Clm3skz_.d.mts} +1 -1
- package/dist/server/{index-Cp7tJuRt.d.ts → index-DLvNddi-.d.ts} +1 -1
- package/dist/server/index.d.mts +216 -5
- package/dist/server/index.d.ts +216 -5
- package/dist/server/index.js +301 -4
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +301 -4
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/{loadContent-DmgpFcFC.d.ts → loadContent-D7LQwI0o.d.ts} +3 -3
- package/dist/server/{loadContent-C-YYUKQa.d.mts → loadContent-DVfuBLiZ.d.mts} +3 -3
- package/dist/server/{loadPage-IDGVDFBB.js → loadPage-AXNAERDS.js} +2 -2
- package/dist/server/{loadPage-IDGVDFBB.js.map → loadPage-AXNAERDS.js.map} +1 -1
- package/dist/server/{loadPage-DP3nrHBi.d.ts → loadPage-BmYJCe_V.d.ts} +2 -2
- package/dist/server/{loadPage-B8mQUUSo.d.mts → loadPage-BucnLHmE.d.mts} +2 -2
- package/dist/server/{loadPage-DNQTTRHL.mjs → loadPage-XR7ORQ2E.mjs} +2 -2
- package/dist/server/loadPage-XR7ORQ2E.mjs.map +1 -0
- package/dist/server/metadata.d.mts +4 -4
- package/dist/server/metadata.d.ts +4 -4
- package/dist/server/metadata.js +1 -1
- package/dist/server/metadata.mjs +1 -1
- package/dist/server/navigation.d.mts +2 -2
- package/dist/server/navigation.d.ts +2 -2
- package/dist/server/navigation.js +1 -1
- package/dist/server/navigation.mjs +1 -1
- package/dist/server/next/revalidate.d.mts +66 -0
- package/dist/server/next/revalidate.d.ts +66 -0
- package/dist/server/next/revalidate.js +60 -0
- package/dist/server/next/revalidate.js.map +1 -0
- package/dist/server/next/revalidate.mjs +60 -0
- package/dist/server/next/revalidate.mjs.map +1 -0
- package/dist/server/next/tags.d.mts +81 -0
- package/dist/server/next/tags.d.ts +81 -0
- package/dist/server/next/tags.js +36 -0
- package/dist/server/next/tags.js.map +1 -0
- package/dist/server/next/tags.mjs +36 -0
- package/dist/server/next/tags.mjs.map +1 -0
- package/dist/server/next.d.mts +164 -6
- package/dist/server/next.d.ts +164 -6
- package/dist/server/next.js +79 -11
- package/dist/server/next.js.map +1 -1
- package/dist/server/next.mjs +76 -8
- 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/server.js +1 -1
- package/dist/server/rendering/server.mjs +1 -1
- package/dist/server/rendering.d.mts +7 -7
- package/dist/server/rendering.d.ts +7 -7
- package/dist/server/rendering.js +3 -3
- package/dist/server/rendering.js.map +1 -1
- package/dist/server/rendering.mjs +4 -4
- package/dist/server/routing.d.mts +3 -3
- package/dist/server/routing.d.ts +3 -3
- package/dist/server/routing.js +2 -2
- package/dist/server/routing.mjs +2 -2
- package/dist/server/server.d.mts +5 -5
- package/dist/server/server.d.ts +5 -5
- package/dist/server/server.js +5 -5
- package/dist/server/server.js.map +1 -1
- package/dist/server/server.mjs +5 -5
- package/dist/server/theme-bridge.js +1 -1
- package/dist/server/theme-bridge.mjs +1 -1
- package/dist/server/theme.js +1 -1
- package/dist/server/theme.mjs +1 -1
- package/dist/server/{types-BvcJU7zk.d.ts → types-BRQyLrQU.d.ts} +132 -11
- package/dist/server/{types-Dsu9wsUh.d.mts → types-BSV6Vc-P.d.mts} +2 -2
- package/dist/server/{types-1cLz0vnq.d.mts → types-C-LShyIg.d.mts} +132 -11
- package/dist/server/{types-CVykEqXN.d.ts → types-Dt98DeYa.d.ts} +2 -2
- package/dist/server/webhooks.d.mts +81 -0
- package/dist/server/webhooks.d.ts +81 -0
- package/dist/server/webhooks.js +12 -0
- package/dist/server/webhooks.js.map +1 -0
- package/dist/server/webhooks.mjs +12 -0
- package/dist/server/webhooks.mjs.map +1 -0
- package/package.json +29 -3
- package/dist/client/resolver-BhueZVxZ.d.mts +0 -61
- package/dist/client/resolver-BhueZVxZ.d.ts +0 -61
- package/dist/client/usePage--fGlyrgj.d.mts +0 -6439
- package/dist/client/usePage-BBcFCxOU.d.ts +0 -6297
- package/dist/client/usePage-BC8Q2E3t.d.mts +0 -6431
- package/dist/client/usePage-BTPnCuWC.d.mts +0 -6511
- package/dist/client/usePage-BafOS9UT.d.mts +0 -6512
- package/dist/client/usePage-BcjWPXvh.d.mts +0 -6388
- package/dist/client/usePage-Bnx-kA6x.d.mts +0 -6670
- package/dist/client/usePage-BvKAa3Zw.d.mts +0 -366
- package/dist/client/usePage-BvKAa3Zw.d.ts +0 -366
- package/dist/client/usePage-BydHcMYB.d.mts +0 -6297
- package/dist/client/usePage-C3ZKNwY7.d.mts +0 -6393
- package/dist/client/usePage-CE7X5NcN.d.ts +0 -6439
- package/dist/client/usePage-CHEybPMD.d.ts +0 -6429
- package/dist/client/usePage-CrKw1H6Y.d.ts +0 -6338
- package/dist/client/usePage-CyYpOJud.d.ts +0 -6388
- package/dist/client/usePage-D4fxZbRR.d.mts +0 -6429
- package/dist/client/usePage-DMI8ImsU.d.mts +0 -6338
- package/dist/client/usePage-DoPI6b8V.d.ts +0 -6511
- package/dist/client/usePage-DpRNZUtP.d.ts +0 -6431
- package/dist/client/usePage-QNWArrVO.d.ts +0 -6670
- package/dist/client/usePage-fBgPB6Oq.d.ts +0 -6512
- package/dist/client/usePage-gpVaeWDy.d.ts +0 -6393
- package/dist/server/chunk-7FIJSGHU.mjs.map +0 -1
- package/dist/server/chunk-BJTO5JO5.mjs +0 -11
- package/dist/server/chunk-DGUM43GV.js +0 -11
- package/dist/server/chunk-DGUM43GV.js.map +0 -1
- package/dist/server/chunk-P7UVAMK6.js.map +0 -1
- /package/dist/server/{chunk-BJTO5JO5.mjs.map → chunk-NFEGQTCC.mjs.map} +0 -0
- /package/dist/server/{loadPage-DNQTTRHL.mjs.map → env.mjs.map} +0 -0
|
@@ -1,6 +1,246 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
__esm,
|
|
3
|
+
__export,
|
|
4
|
+
__toCommonJS
|
|
5
|
+
} from "./chunk-NFEGQTCC.mjs";
|
|
6
|
+
|
|
7
|
+
// src/constants.ts
|
|
8
|
+
var PREBUILD_PAGE_SIZE, DEFAULT_MAX_PREBUILD_AGE_SEC, DEFAULT_PREBUILD_DIR;
|
|
9
|
+
var init_constants = __esm({
|
|
10
|
+
"src/constants.ts"() {
|
|
11
|
+
"use strict";
|
|
12
|
+
PREBUILD_PAGE_SIZE = 50;
|
|
13
|
+
DEFAULT_MAX_PREBUILD_AGE_SEC = 86400;
|
|
14
|
+
DEFAULT_PREBUILD_DIR = ".riverbank-cache";
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// src/prebuild/loader.ts
|
|
19
|
+
var loader_exports = {};
|
|
20
|
+
__export(loader_exports, {
|
|
21
|
+
PrebuildLoader: () => PrebuildLoader,
|
|
22
|
+
canUsePrebuild: () => canUsePrebuild,
|
|
23
|
+
createPrebuildLoader: () => createPrebuildLoader
|
|
24
|
+
});
|
|
25
|
+
import * as fs from "fs";
|
|
26
|
+
import * as path from "path";
|
|
27
|
+
function loadManifest(prebuildDir) {
|
|
28
|
+
if (cachedManifest?.dir === prebuildDir) {
|
|
29
|
+
return cachedManifest.manifest;
|
|
30
|
+
}
|
|
31
|
+
const manifestPath = path.join(prebuildDir, "manifest.json");
|
|
32
|
+
if (!fs.existsSync(manifestPath)) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const content = fs.readFileSync(manifestPath, "utf-8");
|
|
37
|
+
const manifest = JSON.parse(content);
|
|
38
|
+
cachedManifest = { manifest, dir: prebuildDir };
|
|
39
|
+
return manifest;
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function loadJsonFile(prebuildDir, relativePath) {
|
|
45
|
+
const filePath = path.join(prebuildDir, relativePath);
|
|
46
|
+
if (!fs.existsSync(filePath)) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
51
|
+
return JSON.parse(content);
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function isPrebuildExpired(manifest, maxAgeSec) {
|
|
57
|
+
const ageMs = Date.now() - new Date(manifest.generatedAt).getTime();
|
|
58
|
+
return ageMs > maxAgeSec * 1e3;
|
|
59
|
+
}
|
|
60
|
+
function getPrebuildAgeSec(manifest) {
|
|
61
|
+
const ageMs = Date.now() - new Date(manifest.generatedAt).getTime();
|
|
62
|
+
return Math.floor(ageMs / 1e3);
|
|
63
|
+
}
|
|
64
|
+
function canUsePrebuild() {
|
|
65
|
+
if (typeof process === "undefined" || !process.versions?.node) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
return typeof fs.existsSync === "function";
|
|
70
|
+
} catch {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function createPrebuildLoader(config) {
|
|
75
|
+
return new PrebuildLoader(config);
|
|
76
|
+
}
|
|
77
|
+
var cachedManifest, PrebuildLoader;
|
|
78
|
+
var init_loader = __esm({
|
|
79
|
+
"src/prebuild/loader.ts"() {
|
|
80
|
+
"use strict";
|
|
81
|
+
init_constants();
|
|
82
|
+
cachedManifest = null;
|
|
83
|
+
PrebuildLoader = class {
|
|
84
|
+
constructor(config) {
|
|
85
|
+
this.prebuildDir = config.prebuildDir ?? DEFAULT_PREBUILD_DIR;
|
|
86
|
+
this.maxPrebuildAgeSec = config.maxPrebuildAgeSec ?? DEFAULT_MAX_PREBUILD_AGE_SEC;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Check if prebuild is available and not expired.
|
|
90
|
+
*/
|
|
91
|
+
isAvailable() {
|
|
92
|
+
if (!canUsePrebuild()) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
const manifest = loadManifest(this.prebuildDir);
|
|
96
|
+
if (!manifest) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
return !isPrebuildExpired(manifest, this.maxPrebuildAgeSec);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Load site data from prebuild cache.
|
|
103
|
+
*/
|
|
104
|
+
loadSite(siteId) {
|
|
105
|
+
const manifest = loadManifest(this.prebuildDir);
|
|
106
|
+
if (!manifest || isPrebuildExpired(manifest, this.maxPrebuildAgeSec)) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
const cacheFile = loadJsonFile(this.prebuildDir, "site.json");
|
|
110
|
+
if (!cacheFile || cacheFile.data.site.id !== siteId) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
data: cacheFile.data,
|
|
115
|
+
prebuildAgeSec: getPrebuildAgeSec(manifest)
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Load page data from prebuild cache.
|
|
120
|
+
*/
|
|
121
|
+
loadPage(siteId, pagePath) {
|
|
122
|
+
const manifest = loadManifest(this.prebuildDir);
|
|
123
|
+
if (!manifest || isPrebuildExpired(manifest, this.maxPrebuildAgeSec)) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
const cacheKey = `page:${siteId}:${pagePath}:false`;
|
|
127
|
+
const relativePath = manifest.keyToFile[cacheKey];
|
|
128
|
+
if (!relativePath) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
const cacheFile = loadJsonFile(this.prebuildDir, relativePath);
|
|
132
|
+
if (!cacheFile) {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
data: cacheFile.data,
|
|
137
|
+
prebuildAgeSec: getPrebuildAgeSec(manifest)
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Load entries from prebuild cache with runtime filtering.
|
|
142
|
+
*
|
|
143
|
+
* The prebuild stores ALL entries for each content type.
|
|
144
|
+
* Filtering, ordering, and pagination are applied at runtime.
|
|
145
|
+
*/
|
|
146
|
+
loadEntries(siteId, params) {
|
|
147
|
+
if (params.preview) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
if (params.mode === "manual" && params.entryIds?.length) {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
const manifest = loadManifest(this.prebuildDir);
|
|
154
|
+
if (!manifest || isPrebuildExpired(manifest, this.maxPrebuildAgeSec)) {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
const cacheKey = `entries-all:${siteId}:${params.contentType}`;
|
|
158
|
+
const relativePath = manifest.keyToFile[cacheKey];
|
|
159
|
+
if (!relativePath) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
const cacheFile = loadJsonFile(this.prebuildDir, relativePath);
|
|
163
|
+
if (!cacheFile) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
let entries = [...cacheFile.entries];
|
|
167
|
+
if (params.order === "newest") {
|
|
168
|
+
entries.sort((a, b) => {
|
|
169
|
+
const aTime = a.publishedAt ? new Date(a.publishedAt).getTime() : 0;
|
|
170
|
+
const bTime = b.publishedAt ? new Date(b.publishedAt).getTime() : 0;
|
|
171
|
+
return bTime - aTime;
|
|
172
|
+
});
|
|
173
|
+
} else if (params.order === "oldest") {
|
|
174
|
+
entries.sort((a, b) => {
|
|
175
|
+
const aTime = a.publishedAt ? new Date(a.publishedAt).getTime() : 0;
|
|
176
|
+
const bTime = b.publishedAt ? new Date(b.publishedAt).getTime() : 0;
|
|
177
|
+
return aTime - bTime;
|
|
178
|
+
});
|
|
179
|
+
} else if (params.order === "title") {
|
|
180
|
+
entries.sort((a, b) => (a.title || "").localeCompare(b.title || ""));
|
|
181
|
+
}
|
|
182
|
+
const total = entries.length;
|
|
183
|
+
const offset = params.offset ?? 0;
|
|
184
|
+
const limit = params.limit ?? 10;
|
|
185
|
+
if (offset > 0) {
|
|
186
|
+
entries = entries.slice(offset);
|
|
187
|
+
}
|
|
188
|
+
entries = entries.slice(0, limit);
|
|
189
|
+
const prebuildAgeSec = getPrebuildAgeSec(manifest);
|
|
190
|
+
if (params.includeMeta) {
|
|
191
|
+
return {
|
|
192
|
+
data: {
|
|
193
|
+
entries,
|
|
194
|
+
total,
|
|
195
|
+
hasMore: offset + entries.length < total,
|
|
196
|
+
limit,
|
|
197
|
+
offset,
|
|
198
|
+
totalPages: Math.ceil(total / limit),
|
|
199
|
+
currentPage: Math.floor(offset / limit) + 1
|
|
200
|
+
},
|
|
201
|
+
prebuildAgeSec
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
data: { entries },
|
|
206
|
+
prebuildAgeSec
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Load navigation data from prebuild cache.
|
|
211
|
+
*/
|
|
212
|
+
loadNavigation() {
|
|
213
|
+
const manifest = loadManifest(this.prebuildDir);
|
|
214
|
+
if (!manifest || isPrebuildExpired(manifest, this.maxPrebuildAgeSec)) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
const cacheFile = loadJsonFile(
|
|
218
|
+
this.prebuildDir,
|
|
219
|
+
"navigation/menus.json"
|
|
220
|
+
);
|
|
221
|
+
if (!cacheFile) {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
data: cacheFile.menus,
|
|
226
|
+
prebuildAgeSec: getPrebuildAgeSec(manifest)
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Get the manifest for inspection.
|
|
231
|
+
*/
|
|
232
|
+
getManifest() {
|
|
233
|
+
return loadManifest(this.prebuildDir);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Clear the cached manifest (for testing).
|
|
237
|
+
*/
|
|
238
|
+
clearCache() {
|
|
239
|
+
cachedManifest = null;
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
});
|
|
4
244
|
|
|
5
245
|
// ../api/src/endpoints.ts
|
|
6
246
|
var ENDPOINT_DEFINITIONS = {
|
|
@@ -1659,10 +1899,10 @@ function resolveApiBaseUrl() {
|
|
|
1659
1899
|
var revalidateTag = null;
|
|
1660
1900
|
if (typeof window === "undefined") {
|
|
1661
1901
|
try {
|
|
1662
|
-
const
|
|
1663
|
-
|
|
1902
|
+
const dynamicRequire = new Function("modulePath", "return require(modulePath)");
|
|
1903
|
+
const nextCache = dynamicRequire("next/cache");
|
|
1904
|
+
revalidateTag = nextCache.revalidateTag ?? null;
|
|
1664
1905
|
} catch {
|
|
1665
|
-
revalidateTag = null;
|
|
1666
1906
|
}
|
|
1667
1907
|
}
|
|
1668
1908
|
var sdkVersion;
|
|
@@ -1691,8 +1931,22 @@ var ApiRequestError = class extends Error {
|
|
|
1691
1931
|
this.body = options.body;
|
|
1692
1932
|
this.cause = options.cause;
|
|
1693
1933
|
this.errorCode = options.errorCode;
|
|
1934
|
+
this.retryAfterMs = options.retryAfterMs;
|
|
1694
1935
|
}
|
|
1695
1936
|
};
|
|
1937
|
+
function parseRetryAfterHeader(headerValue) {
|
|
1938
|
+
if (!headerValue) return void 0;
|
|
1939
|
+
if (/^\d+$/.test(headerValue)) {
|
|
1940
|
+
const seconds = parseInt(headerValue, 10);
|
|
1941
|
+
return seconds * 1e3;
|
|
1942
|
+
}
|
|
1943
|
+
const date = new Date(headerValue);
|
|
1944
|
+
if (!isNaN(date.getTime())) {
|
|
1945
|
+
const delayMs = date.getTime() - Date.now();
|
|
1946
|
+
return delayMs > 0 ? delayMs : void 0;
|
|
1947
|
+
}
|
|
1948
|
+
return void 0;
|
|
1949
|
+
}
|
|
1696
1950
|
function buildEndpointURL2(baseURL, endpoint) {
|
|
1697
1951
|
return baseURL + API_ENDPOINTS[endpoint].path;
|
|
1698
1952
|
}
|
|
@@ -1909,6 +2163,7 @@ function createParsedClient(rawClient) {
|
|
|
1909
2163
|
if (!response.ok) {
|
|
1910
2164
|
const body = await parseErrorBody(response);
|
|
1911
2165
|
const requestId = response.headers.get("x-request-id") ?? void 0;
|
|
2166
|
+
const retryAfterMs = parseRetryAfterHeader(response.headers.get("retry-after"));
|
|
1912
2167
|
throw new ApiRequestError(
|
|
1913
2168
|
`Request to ${String(endpoint)} failed with status ${response.status}`,
|
|
1914
2169
|
{
|
|
@@ -1917,7 +2172,8 @@ function createParsedClient(rawClient) {
|
|
|
1917
2172
|
method: config.method,
|
|
1918
2173
|
auth,
|
|
1919
2174
|
requestId,
|
|
1920
|
-
body
|
|
2175
|
+
body,
|
|
2176
|
+
retryAfterMs
|
|
1921
2177
|
}
|
|
1922
2178
|
);
|
|
1923
2179
|
}
|
|
@@ -1965,38 +2221,117 @@ var SimpleCache = class {
|
|
|
1965
2221
|
this.cache = /* @__PURE__ */ new Map();
|
|
1966
2222
|
this.maxSize = options.maxSize ?? 100;
|
|
1967
2223
|
this.ttl = options.ttl ?? 3e5;
|
|
2224
|
+
this.staleTtl = options.staleTtl ?? 3e5;
|
|
1968
2225
|
}
|
|
1969
|
-
|
|
2226
|
+
/**
|
|
2227
|
+
* Get a fresh value (within TTL)
|
|
2228
|
+
* @returns The value if fresh, null otherwise
|
|
2229
|
+
*/
|
|
2230
|
+
getFresh(key) {
|
|
1970
2231
|
const entry = this.cache.get(key);
|
|
1971
|
-
if (!entry) return
|
|
1972
|
-
|
|
2232
|
+
if (!entry) return null;
|
|
2233
|
+
const now = Date.now();
|
|
2234
|
+
if (now <= entry.freshUntil) {
|
|
2235
|
+
return entry.value;
|
|
2236
|
+
}
|
|
2237
|
+
return null;
|
|
2238
|
+
}
|
|
2239
|
+
/**
|
|
2240
|
+
* Get a value that may be stale (past TTL but within staleTtl)
|
|
2241
|
+
* @returns Object with value and stale age, or null if expired
|
|
2242
|
+
*/
|
|
2243
|
+
getStale(key) {
|
|
2244
|
+
const entry = this.cache.get(key);
|
|
2245
|
+
if (!entry) return null;
|
|
2246
|
+
const now = Date.now();
|
|
2247
|
+
if (now > entry.staleUntil) {
|
|
1973
2248
|
this.cache.delete(key);
|
|
1974
|
-
return
|
|
2249
|
+
return null;
|
|
1975
2250
|
}
|
|
1976
|
-
|
|
2251
|
+
const staleAgeSec = now <= entry.freshUntil ? 0 : Math.floor((now - entry.freshUntil) / 1e3);
|
|
2252
|
+
return {
|
|
2253
|
+
value: entry.value,
|
|
2254
|
+
staleAgeSec
|
|
2255
|
+
};
|
|
1977
2256
|
}
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
2257
|
+
/**
|
|
2258
|
+
* Store a value with TTL and stale window
|
|
2259
|
+
*/
|
|
2260
|
+
set(key, value, options) {
|
|
2261
|
+
const ttl = options?.ttl ?? this.ttl;
|
|
2262
|
+
const staleTtl = options?.staleTtl ?? this.staleTtl;
|
|
2263
|
+
const now = Date.now();
|
|
2264
|
+
while (this.cache.size >= this.maxSize && !this.cache.has(key)) {
|
|
2265
|
+
this.evictOne(now);
|
|
1984
2266
|
}
|
|
1985
2267
|
this.cache.set(key, {
|
|
1986
2268
|
value,
|
|
1987
|
-
|
|
2269
|
+
createdAt: now,
|
|
2270
|
+
freshUntil: now + ttl,
|
|
2271
|
+
staleUntil: now + ttl + staleTtl
|
|
1988
2272
|
});
|
|
1989
2273
|
}
|
|
2274
|
+
/**
|
|
2275
|
+
* Evict one entry to make room for a new one
|
|
2276
|
+
* Priority: oldest stale entry, then oldest fresh entry
|
|
2277
|
+
*/
|
|
2278
|
+
evictOne(now) {
|
|
2279
|
+
let oldestStaleKey = null;
|
|
2280
|
+
let oldestStaleTime = Infinity;
|
|
2281
|
+
let oldestFreshKey = null;
|
|
2282
|
+
let oldestFreshTime = Infinity;
|
|
2283
|
+
for (const [key, entry] of this.cache) {
|
|
2284
|
+
if (now > entry.freshUntil) {
|
|
2285
|
+
if (entry.createdAt < oldestStaleTime) {
|
|
2286
|
+
oldestStaleTime = entry.createdAt;
|
|
2287
|
+
oldestStaleKey = key;
|
|
2288
|
+
}
|
|
2289
|
+
} else {
|
|
2290
|
+
if (entry.createdAt < oldestFreshTime) {
|
|
2291
|
+
oldestFreshTime = entry.createdAt;
|
|
2292
|
+
oldestFreshKey = key;
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
const keyToEvict = oldestStaleKey ?? oldestFreshKey;
|
|
2297
|
+
if (keyToEvict) {
|
|
2298
|
+
this.cache.delete(keyToEvict);
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
/**
|
|
2302
|
+
* Remove all fully expired entries (past staleUntil)
|
|
2303
|
+
*/
|
|
2304
|
+
prune() {
|
|
2305
|
+
const now = Date.now();
|
|
2306
|
+
for (const [key, entry] of this.cache) {
|
|
2307
|
+
if (now > entry.staleUntil) {
|
|
2308
|
+
this.cache.delete(key);
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
/**
|
|
2313
|
+
* Clear all entries
|
|
2314
|
+
*/
|
|
1990
2315
|
clear() {
|
|
1991
2316
|
this.cache.clear();
|
|
1992
2317
|
}
|
|
2318
|
+
/**
|
|
2319
|
+
* Check if a key exists and is not fully expired
|
|
2320
|
+
*/
|
|
1993
2321
|
has(key) {
|
|
1994
|
-
|
|
2322
|
+
const entry = this.cache.get(key);
|
|
2323
|
+
if (!entry) return false;
|
|
2324
|
+
const now = Date.now();
|
|
2325
|
+
if (now > entry.staleUntil) {
|
|
2326
|
+
this.cache.delete(key);
|
|
2327
|
+
return false;
|
|
2328
|
+
}
|
|
2329
|
+
return now <= entry.freshUntil;
|
|
1995
2330
|
}
|
|
1996
2331
|
};
|
|
1997
2332
|
|
|
1998
2333
|
// src/version.ts
|
|
1999
|
-
var SDK_VERSION = "0.7.
|
|
2334
|
+
var SDK_VERSION = "0.7.3";
|
|
2000
2335
|
|
|
2001
2336
|
// src/client/error.ts
|
|
2002
2337
|
var RiverbankApiError = class _RiverbankApiError extends Error {
|
|
@@ -2008,8 +2343,31 @@ var RiverbankApiError = class _RiverbankApiError extends Error {
|
|
|
2008
2343
|
this.status = apiError.status;
|
|
2009
2344
|
this.fieldErrors = apiError.fieldErrors;
|
|
2010
2345
|
this.timestamp = apiError.timestamp;
|
|
2346
|
+
this.retryAfterMs = "retryAfterMs" in apiError ? apiError.retryAfterMs : void 0;
|
|
2347
|
+
this.isRetryable = this.computeRetryable();
|
|
2011
2348
|
Object.setPrototypeOf(this, _RiverbankApiError.prototype);
|
|
2012
2349
|
}
|
|
2350
|
+
/**
|
|
2351
|
+
* Compute whether this error is retryable based on HTTP status code.
|
|
2352
|
+
* - 0 (network errors - no HTTP response): retryable
|
|
2353
|
+
* - 429 (rate limit): retryable
|
|
2354
|
+
* - 5xx (server errors): retryable
|
|
2355
|
+
* - 4xx (client errors, except 429): NOT retryable
|
|
2356
|
+
*/
|
|
2357
|
+
computeRetryable() {
|
|
2358
|
+
if (this.status === 0) return true;
|
|
2359
|
+
if (this.status === 429) return true;
|
|
2360
|
+
if (this.status >= 500) return true;
|
|
2361
|
+
return false;
|
|
2362
|
+
}
|
|
2363
|
+
/**
|
|
2364
|
+
* Check if this is a network error (no HTTP response received)
|
|
2365
|
+
*
|
|
2366
|
+
* Matches: network:connection_error, network:timeout, network:dns_error
|
|
2367
|
+
*/
|
|
2368
|
+
isNetworkError() {
|
|
2369
|
+
return this.code.startsWith("network:");
|
|
2370
|
+
}
|
|
2013
2371
|
/**
|
|
2014
2372
|
* Check if this error matches a specific error code
|
|
2015
2373
|
*
|
|
@@ -2068,9 +2426,246 @@ var RiverbankApiError = class _RiverbankApiError extends Error {
|
|
|
2068
2426
|
}
|
|
2069
2427
|
};
|
|
2070
2428
|
|
|
2429
|
+
// src/client/resilience.ts
|
|
2430
|
+
var DEFAULT_RETRY_CONFIG = {
|
|
2431
|
+
maxAttempts: 3,
|
|
2432
|
+
baseDelayMs: 200,
|
|
2433
|
+
maxDelayMs: 2e3,
|
|
2434
|
+
jitter: "full"
|
|
2435
|
+
};
|
|
2436
|
+
var DEFAULT_CIRCUIT_BREAKER_CONFIG = {
|
|
2437
|
+
failureThreshold: 5,
|
|
2438
|
+
resetTimeoutMs: 3e4,
|
|
2439
|
+
halfOpenMaxRequests: 2
|
|
2440
|
+
};
|
|
2441
|
+
function isTransientError(error) {
|
|
2442
|
+
if (error instanceof RiverbankApiError) {
|
|
2443
|
+
if (error.status === 0) return true;
|
|
2444
|
+
if (error.status === 429) return true;
|
|
2445
|
+
if (error.status >= 500) return true;
|
|
2446
|
+
return false;
|
|
2447
|
+
}
|
|
2448
|
+
return true;
|
|
2449
|
+
}
|
|
2450
|
+
function calculateBackoff(attempt, config) {
|
|
2451
|
+
const baseDelayMs = config.baseDelayMs ?? DEFAULT_RETRY_CONFIG.baseDelayMs;
|
|
2452
|
+
const maxDelayMs = config.maxDelayMs ?? DEFAULT_RETRY_CONFIG.maxDelayMs;
|
|
2453
|
+
const jitter = config.jitter ?? DEFAULT_RETRY_CONFIG.jitter;
|
|
2454
|
+
const exponential = baseDelayMs * Math.pow(2, attempt - 1);
|
|
2455
|
+
const capped = Math.min(exponential, maxDelayMs);
|
|
2456
|
+
if (jitter === "full") {
|
|
2457
|
+
return Math.random() * capped;
|
|
2458
|
+
}
|
|
2459
|
+
return capped;
|
|
2460
|
+
}
|
|
2461
|
+
var CircuitBreaker = class {
|
|
2462
|
+
constructor(config) {
|
|
2463
|
+
this.state = "closed";
|
|
2464
|
+
this.failureCount = 0;
|
|
2465
|
+
this.successCount = 0;
|
|
2466
|
+
this.openUntil = 0;
|
|
2467
|
+
this.halfOpenRequests = 0;
|
|
2468
|
+
this.config = {
|
|
2469
|
+
failureThreshold: config?.failureThreshold ?? DEFAULT_CIRCUIT_BREAKER_CONFIG.failureThreshold,
|
|
2470
|
+
resetTimeoutMs: config?.resetTimeoutMs ?? DEFAULT_CIRCUIT_BREAKER_CONFIG.resetTimeoutMs,
|
|
2471
|
+
halfOpenMaxRequests: config?.halfOpenMaxRequests ?? DEFAULT_CIRCUIT_BREAKER_CONFIG.halfOpenMaxRequests
|
|
2472
|
+
};
|
|
2473
|
+
}
|
|
2474
|
+
/**
|
|
2475
|
+
* Check if circuit is open (requests should be blocked)
|
|
2476
|
+
* Also handles automatic transition from open to half-open after timeout
|
|
2477
|
+
*/
|
|
2478
|
+
isOpen() {
|
|
2479
|
+
if (this.state === "open" && Date.now() >= this.openUntil) {
|
|
2480
|
+
this.transitionTo("half-open");
|
|
2481
|
+
}
|
|
2482
|
+
return this.state === "open";
|
|
2483
|
+
}
|
|
2484
|
+
/**
|
|
2485
|
+
* Check if a request can be attempted
|
|
2486
|
+
* - closed: always yes
|
|
2487
|
+
* - open: always no
|
|
2488
|
+
* - half-open: limited number of probes
|
|
2489
|
+
*/
|
|
2490
|
+
canAttempt() {
|
|
2491
|
+
if (this.state === "closed") return true;
|
|
2492
|
+
if (this.state === "open") return false;
|
|
2493
|
+
return this.halfOpenRequests < this.config.halfOpenMaxRequests;
|
|
2494
|
+
}
|
|
2495
|
+
/**
|
|
2496
|
+
* Increment half-open request counter (call before making request in half-open)
|
|
2497
|
+
*/
|
|
2498
|
+
incrementHalfOpenRequests() {
|
|
2499
|
+
if (this.state === "half-open") {
|
|
2500
|
+
this.halfOpenRequests++;
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
/**
|
|
2504
|
+
* Record a successful request
|
|
2505
|
+
*/
|
|
2506
|
+
recordSuccess() {
|
|
2507
|
+
if (this.state === "half-open") {
|
|
2508
|
+
this.successCount++;
|
|
2509
|
+
if (this.successCount >= this.config.halfOpenMaxRequests) {
|
|
2510
|
+
this.transitionTo("closed");
|
|
2511
|
+
}
|
|
2512
|
+
} else {
|
|
2513
|
+
this.failureCount = 0;
|
|
2514
|
+
}
|
|
2515
|
+
}
|
|
2516
|
+
/**
|
|
2517
|
+
* Record a failed request
|
|
2518
|
+
* Only counts transient failures toward circuit breaker threshold
|
|
2519
|
+
*/
|
|
2520
|
+
recordFailure(error) {
|
|
2521
|
+
if (!isTransientError(error)) return;
|
|
2522
|
+
this.failureCount++;
|
|
2523
|
+
if (this.state === "half-open") {
|
|
2524
|
+
this.transitionTo("open");
|
|
2525
|
+
} else if (this.failureCount >= this.config.failureThreshold) {
|
|
2526
|
+
this.transitionTo("open");
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
/**
|
|
2530
|
+
* Get current circuit state
|
|
2531
|
+
*/
|
|
2532
|
+
getState() {
|
|
2533
|
+
return {
|
|
2534
|
+
state: this.state,
|
|
2535
|
+
failureCount: this.failureCount,
|
|
2536
|
+
openUntil: this.state === "open" ? this.openUntil : void 0
|
|
2537
|
+
};
|
|
2538
|
+
}
|
|
2539
|
+
/**
|
|
2540
|
+
* Transition to a new state
|
|
2541
|
+
*/
|
|
2542
|
+
transitionTo(newState) {
|
|
2543
|
+
this.state = newState;
|
|
2544
|
+
if (newState === "open") {
|
|
2545
|
+
this.openUntil = Date.now() + this.config.resetTimeoutMs;
|
|
2546
|
+
} else if (newState === "half-open") {
|
|
2547
|
+
this.halfOpenRequests = 0;
|
|
2548
|
+
this.successCount = 0;
|
|
2549
|
+
} else if (newState === "closed") {
|
|
2550
|
+
this.failureCount = 0;
|
|
2551
|
+
this.successCount = 0;
|
|
2552
|
+
this.halfOpenRequests = 0;
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
};
|
|
2556
|
+
async function fetchWithTimeoutAndRetry(fetcher, config) {
|
|
2557
|
+
const maxAttempts = config.maxAttempts ?? DEFAULT_RETRY_CONFIG.maxAttempts;
|
|
2558
|
+
const requestTimeoutMs = config.requestTimeoutMs ?? 8e3;
|
|
2559
|
+
let lastError;
|
|
2560
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
2561
|
+
try {
|
|
2562
|
+
const controller = new AbortController();
|
|
2563
|
+
const timeoutId = setTimeout(() => controller.abort(), requestTimeoutMs);
|
|
2564
|
+
try {
|
|
2565
|
+
const result = await fetcher(controller.signal);
|
|
2566
|
+
return result;
|
|
2567
|
+
} finally {
|
|
2568
|
+
clearTimeout(timeoutId);
|
|
2569
|
+
}
|
|
2570
|
+
} catch (error) {
|
|
2571
|
+
lastError = error;
|
|
2572
|
+
const shouldRetry = shouldRetryError(error, config.retryOn);
|
|
2573
|
+
if (!shouldRetry) {
|
|
2574
|
+
throw error;
|
|
2575
|
+
}
|
|
2576
|
+
if (attempt < maxAttempts) {
|
|
2577
|
+
const delay = getRetryDelay(error, attempt, config);
|
|
2578
|
+
await sleep(delay);
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2582
|
+
throw lastError;
|
|
2583
|
+
}
|
|
2584
|
+
function shouldRetryError(error, customRetryOn) {
|
|
2585
|
+
if (customRetryOn) {
|
|
2586
|
+
const statusCode = error instanceof RiverbankApiError ? error.status : void 0;
|
|
2587
|
+
return customRetryOn(error, statusCode);
|
|
2588
|
+
}
|
|
2589
|
+
return isTransientError(error);
|
|
2590
|
+
}
|
|
2591
|
+
function getRetryDelay(error, attempt, config) {
|
|
2592
|
+
if (error instanceof RiverbankApiError && error.retryAfterMs) {
|
|
2593
|
+
return error.retryAfterMs;
|
|
2594
|
+
}
|
|
2595
|
+
return calculateBackoff(attempt, config);
|
|
2596
|
+
}
|
|
2597
|
+
function sleep(ms) {
|
|
2598
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2599
|
+
}
|
|
2600
|
+
var CircuitOpenError = class extends Error {
|
|
2601
|
+
constructor(state) {
|
|
2602
|
+
super("Circuit breaker is open");
|
|
2603
|
+
this.name = "CircuitOpenError";
|
|
2604
|
+
this.circuitState = state;
|
|
2605
|
+
}
|
|
2606
|
+
};
|
|
2607
|
+
|
|
2071
2608
|
// src/client/index.ts
|
|
2609
|
+
var prebuildModule = null;
|
|
2610
|
+
function getPrebuildModule() {
|
|
2611
|
+
if (prebuildModule !== null) return prebuildModule;
|
|
2612
|
+
if (typeof process === "undefined" || !process.versions?.node) {
|
|
2613
|
+
return null;
|
|
2614
|
+
}
|
|
2615
|
+
try {
|
|
2616
|
+
prebuildModule = (init_loader(), __toCommonJS(loader_exports));
|
|
2617
|
+
return prebuildModule;
|
|
2618
|
+
} catch {
|
|
2619
|
+
return null;
|
|
2620
|
+
}
|
|
2621
|
+
}
|
|
2072
2622
|
setSdkVersion(SDK_VERSION);
|
|
2623
|
+
var DEFAULT_BROWSER_TIMEOUT_MS = 5e3;
|
|
2624
|
+
var DEFAULT_SERVER_TIMEOUT_MS = 8e3;
|
|
2625
|
+
function generateRequestId2() {
|
|
2626
|
+
return `req-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
2627
|
+
}
|
|
2628
|
+
function isAbortError(error) {
|
|
2629
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
2630
|
+
return true;
|
|
2631
|
+
}
|
|
2632
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
2633
|
+
return true;
|
|
2634
|
+
}
|
|
2635
|
+
return false;
|
|
2636
|
+
}
|
|
2637
|
+
function getNetworkErrorCode(error) {
|
|
2638
|
+
if (error.name === "TimeoutError" || error.name === "AbortError") {
|
|
2639
|
+
return "network:timeout";
|
|
2640
|
+
}
|
|
2641
|
+
const nodeError = error;
|
|
2642
|
+
if (nodeError.code) {
|
|
2643
|
+
switch (nodeError.code) {
|
|
2644
|
+
case "ETIMEDOUT":
|
|
2645
|
+
case "ESOCKETTIMEDOUT":
|
|
2646
|
+
return "network:timeout";
|
|
2647
|
+
case "ENOTFOUND":
|
|
2648
|
+
case "EAI_AGAIN":
|
|
2649
|
+
return "network:dns_error";
|
|
2650
|
+
case "ECONNREFUSED":
|
|
2651
|
+
case "ECONNRESET":
|
|
2652
|
+
case "EPIPE":
|
|
2653
|
+
return "network:connection_error";
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
2656
|
+
const message = error.message.toLowerCase();
|
|
2657
|
+
if (message.includes("timeout") || message.includes("timed out")) {
|
|
2658
|
+
return "network:timeout";
|
|
2659
|
+
}
|
|
2660
|
+
if (message.includes("dns") || message.includes("getaddrinfo") || message.includes("enotfound")) {
|
|
2661
|
+
return "network:dns_error";
|
|
2662
|
+
}
|
|
2663
|
+
return "network:connection_error";
|
|
2664
|
+
}
|
|
2073
2665
|
function convertToTypedError(error) {
|
|
2666
|
+
if (isAbortError(error)) {
|
|
2667
|
+
throw error;
|
|
2668
|
+
}
|
|
2074
2669
|
if (error instanceof ApiEnvelopeError) {
|
|
2075
2670
|
throw new RiverbankApiError({
|
|
2076
2671
|
code: error.code,
|
|
@@ -2084,15 +2679,30 @@ function convertToTypedError(error) {
|
|
|
2084
2679
|
if (error instanceof ApiRequestError && error.body && typeof error.body === "object") {
|
|
2085
2680
|
const body = error.body;
|
|
2086
2681
|
if (isApiError(body)) {
|
|
2087
|
-
|
|
2682
|
+
const envelopeError = body.error;
|
|
2683
|
+
throw new RiverbankApiError({
|
|
2684
|
+
...envelopeError,
|
|
2685
|
+
retryAfterMs: error.retryAfterMs
|
|
2686
|
+
});
|
|
2088
2687
|
}
|
|
2089
2688
|
}
|
|
2689
|
+
if (error instanceof TypeError || error instanceof Error && !("status" in error)) {
|
|
2690
|
+
const networkError = error;
|
|
2691
|
+
throw new RiverbankApiError({
|
|
2692
|
+
code: getNetworkErrorCode(networkError),
|
|
2693
|
+
message: networkError.message || "Network request failed",
|
|
2694
|
+
requestId: `local-${Date.now()}`,
|
|
2695
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2696
|
+
status: 0
|
|
2697
|
+
// No HTTP response received
|
|
2698
|
+
});
|
|
2699
|
+
}
|
|
2090
2700
|
throw error;
|
|
2091
2701
|
}
|
|
2092
2702
|
function createRiverbankClient(config) {
|
|
2093
2703
|
if (!config.baseUrl) {
|
|
2094
2704
|
throw new Error(
|
|
2095
|
-
"baseUrl is required when creating a
|
|
2705
|
+
"baseUrl is required when creating a Riverbank client. Expected format: https://dashboard.example.com/api (must include /api path)"
|
|
2096
2706
|
);
|
|
2097
2707
|
}
|
|
2098
2708
|
if (!config.baseUrl.endsWith("/api")) {
|
|
@@ -2103,59 +2713,212 @@ function createRiverbankClient(config) {
|
|
|
2103
2713
|
const cacheEnabled = config.cache?.enabled ?? true;
|
|
2104
2714
|
const cacheTTL = (config.cache?.ttl ?? 300) * 1e3;
|
|
2105
2715
|
const cacheMaxSize = config.cache?.maxSize ?? 100;
|
|
2716
|
+
const resilienceEnabled = config.resilience?.enabled ?? true;
|
|
2717
|
+
const staleIfError = config.resilience?.staleIfError ?? true;
|
|
2718
|
+
const staleTtlMs = (config.resilience?.staleTtlSec ?? 300) * 1e3;
|
|
2719
|
+
const requestTimeoutMs = config.resilience?.requestTimeoutMs ?? (typeof window !== "undefined" ? DEFAULT_BROWSER_TIMEOUT_MS : DEFAULT_SERVER_TIMEOUT_MS);
|
|
2720
|
+
const retryConfig = {
|
|
2721
|
+
maxAttempts: config.resilience?.retry?.maxAttempts ?? DEFAULT_RETRY_CONFIG.maxAttempts,
|
|
2722
|
+
baseDelayMs: config.resilience?.retry?.baseDelayMs ?? DEFAULT_RETRY_CONFIG.baseDelayMs,
|
|
2723
|
+
maxDelayMs: config.resilience?.retry?.maxDelayMs ?? DEFAULT_RETRY_CONFIG.maxDelayMs,
|
|
2724
|
+
jitter: config.resilience?.retry?.jitter ?? DEFAULT_RETRY_CONFIG.jitter,
|
|
2725
|
+
retryOn: config.resilience?.retry?.retryOn
|
|
2726
|
+
};
|
|
2727
|
+
const circuitBreakerConfig = {
|
|
2728
|
+
failureThreshold: config.resilience?.circuitBreaker?.failureThreshold ?? DEFAULT_CIRCUIT_BREAKER_CONFIG.failureThreshold,
|
|
2729
|
+
resetTimeoutMs: config.resilience?.circuitBreaker?.resetTimeoutMs ?? DEFAULT_CIRCUIT_BREAKER_CONFIG.resetTimeoutMs,
|
|
2730
|
+
halfOpenMaxRequests: config.resilience?.circuitBreaker?.halfOpenMaxRequests ?? DEFAULT_CIRCUIT_BREAKER_CONFIG.halfOpenMaxRequests
|
|
2731
|
+
};
|
|
2106
2732
|
const apiClient = createBearerAPIClient(config.apiKey, config.baseUrl);
|
|
2107
2733
|
const cache = new SimpleCache({
|
|
2108
2734
|
maxSize: cacheMaxSize,
|
|
2109
|
-
ttl: cacheTTL
|
|
2735
|
+
ttl: cacheTTL,
|
|
2736
|
+
staleTtl: staleTtlMs
|
|
2110
2737
|
});
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2738
|
+
const circuitBreaker = new CircuitBreaker(circuitBreakerConfig);
|
|
2739
|
+
const prebuildDir = config.resilience?.prebuildDir;
|
|
2740
|
+
const prebuildMod = prebuildDir ? getPrebuildModule() : null;
|
|
2741
|
+
const prebuildLoader = prebuildMod?.canUsePrebuild() && prebuildDir ? new prebuildMod.PrebuildLoader({
|
|
2742
|
+
prebuildDir,
|
|
2743
|
+
maxPrebuildAgeSec: config.resilience?.maxPrebuildAgeSec
|
|
2744
|
+
}) : null;
|
|
2745
|
+
let lastStatus = null;
|
|
2746
|
+
let isDegraded = false;
|
|
2747
|
+
function emitStatus(source, data, details) {
|
|
2748
|
+
const status = {
|
|
2749
|
+
source,
|
|
2750
|
+
isPreview: details.isPreview,
|
|
2751
|
+
cacheKey: details.cacheKey,
|
|
2752
|
+
error: details.error,
|
|
2753
|
+
staleAgeSec: details.staleAgeSec,
|
|
2754
|
+
prebuildAgeSec: details.prebuildAgeSec,
|
|
2755
|
+
circuit: circuitBreaker.getState(),
|
|
2756
|
+
requestId: details.requestId,
|
|
2757
|
+
durationMs: details.durationMs
|
|
2758
|
+
};
|
|
2759
|
+
lastStatus = status;
|
|
2760
|
+
config.resilience?.onStatusChange?.(status);
|
|
2761
|
+
const nowDegraded = source === "stale" || source === "error";
|
|
2762
|
+
if (nowDegraded !== isDegraded) {
|
|
2763
|
+
isDegraded = nowDegraded;
|
|
2764
|
+
config.resilience?.onDegradedMode?.(nowDegraded, status);
|
|
2765
|
+
}
|
|
2766
|
+
return data;
|
|
2767
|
+
}
|
|
2768
|
+
async function resilientFetch(cacheKey, fetcher, options) {
|
|
2769
|
+
const requestId = generateRequestId2();
|
|
2770
|
+
const startTime = Date.now();
|
|
2771
|
+
const isPreview = options.preview ?? false;
|
|
2772
|
+
const statusDetails = (extra = {}) => ({
|
|
2773
|
+
requestId,
|
|
2774
|
+
cacheKey,
|
|
2775
|
+
isPreview,
|
|
2776
|
+
durationMs: Date.now() - startTime,
|
|
2777
|
+
...extra
|
|
2778
|
+
});
|
|
2779
|
+
if (cacheEnabled && !options.force) {
|
|
2780
|
+
const fresh = cache.getFresh(cacheKey);
|
|
2781
|
+
if (fresh !== null) {
|
|
2782
|
+
return emitStatus("cache", fresh, statusDetails());
|
|
2116
2783
|
}
|
|
2117
2784
|
}
|
|
2118
|
-
|
|
2785
|
+
if (resilienceEnabled && circuitBreaker.isOpen()) {
|
|
2786
|
+
if (!isPreview && staleIfError) {
|
|
2787
|
+
const stale = cache.getStale(cacheKey);
|
|
2788
|
+
if (stale) {
|
|
2789
|
+
return emitStatus("stale", stale.value, statusDetails({
|
|
2790
|
+
staleAgeSec: stale.staleAgeSec,
|
|
2791
|
+
error: { code: "circuit_open", message: "Circuit breaker is open" }
|
|
2792
|
+
}));
|
|
2793
|
+
}
|
|
2794
|
+
}
|
|
2795
|
+
if (!isPreview && options.prebuildFallback) {
|
|
2796
|
+
const prebuildResult = options.prebuildFallback();
|
|
2797
|
+
if (prebuildResult) {
|
|
2798
|
+
return emitStatus("prebuild", prebuildResult.data, statusDetails({
|
|
2799
|
+
prebuildAgeSec: prebuildResult.prebuildAgeSec,
|
|
2800
|
+
error: { code: "circuit_open", message: "Circuit breaker is open" }
|
|
2801
|
+
}));
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
const circuitState = circuitBreaker.getState();
|
|
2805
|
+
emitStatus("error", null, statusDetails({
|
|
2806
|
+
error: { code: "circuit_open", message: "Circuit breaker is open" }
|
|
2807
|
+
}));
|
|
2808
|
+
throw new CircuitOpenError(circuitState);
|
|
2809
|
+
}
|
|
2119
2810
|
try {
|
|
2120
|
-
|
|
2121
|
-
|
|
2811
|
+
let data;
|
|
2812
|
+
if (resilienceEnabled) {
|
|
2813
|
+
if (circuitBreaker.getState().state === "half-open") {
|
|
2814
|
+
circuitBreaker.incrementHalfOpenRequests();
|
|
2815
|
+
}
|
|
2816
|
+
data = await fetchWithTimeoutAndRetry(
|
|
2817
|
+
async (timeoutSignal) => {
|
|
2818
|
+
const combinedSignal = options.signal ? combineAbortSignals(timeoutSignal, options.signal) : timeoutSignal;
|
|
2819
|
+
try {
|
|
2820
|
+
const response = await fetcher(combinedSignal);
|
|
2821
|
+
return unwrapResponse(response);
|
|
2822
|
+
} catch (error) {
|
|
2823
|
+
convertToTypedError(error);
|
|
2824
|
+
}
|
|
2825
|
+
},
|
|
2826
|
+
{
|
|
2827
|
+
...retryConfig,
|
|
2828
|
+
requestTimeoutMs
|
|
2829
|
+
}
|
|
2830
|
+
);
|
|
2831
|
+
circuitBreaker.recordSuccess();
|
|
2832
|
+
} else {
|
|
2833
|
+
try {
|
|
2834
|
+
const response = await fetcher(options.signal ?? new AbortController().signal);
|
|
2835
|
+
data = unwrapResponse(response);
|
|
2836
|
+
} catch (error) {
|
|
2837
|
+
convertToTypedError(error);
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2840
|
+
if (cacheEnabled) {
|
|
2841
|
+
cache.set(cacheKey, data);
|
|
2842
|
+
}
|
|
2843
|
+
return emitStatus("live", data, statusDetails());
|
|
2122
2844
|
} catch (error) {
|
|
2123
|
-
|
|
2845
|
+
if (resilienceEnabled && error instanceof Error) {
|
|
2846
|
+
circuitBreaker.recordFailure(error);
|
|
2847
|
+
}
|
|
2848
|
+
if (!isPreview && staleIfError && cacheEnabled) {
|
|
2849
|
+
const stale = cache.getStale(cacheKey);
|
|
2850
|
+
if (stale) {
|
|
2851
|
+
const errorInfo2 = error instanceof RiverbankApiError ? { code: error.code, message: error.message } : { message: error.message };
|
|
2852
|
+
return emitStatus("stale", stale.value, statusDetails({
|
|
2853
|
+
staleAgeSec: stale.staleAgeSec,
|
|
2854
|
+
error: errorInfo2
|
|
2855
|
+
}));
|
|
2856
|
+
}
|
|
2857
|
+
}
|
|
2858
|
+
if (!isPreview && options.prebuildFallback) {
|
|
2859
|
+
const prebuildResult = options.prebuildFallback();
|
|
2860
|
+
if (prebuildResult) {
|
|
2861
|
+
const errorInfo2 = error instanceof RiverbankApiError ? { code: error.code, message: error.message } : { message: error.message };
|
|
2862
|
+
return emitStatus("prebuild", prebuildResult.data, statusDetails({
|
|
2863
|
+
prebuildAgeSec: prebuildResult.prebuildAgeSec,
|
|
2864
|
+
error: errorInfo2
|
|
2865
|
+
}));
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
const errorInfo = error instanceof RiverbankApiError ? { code: error.code, message: error.message } : { message: error.message };
|
|
2869
|
+
emitStatus("error", null, statusDetails({ error: errorInfo }));
|
|
2870
|
+
throw error;
|
|
2124
2871
|
}
|
|
2125
|
-
|
|
2126
|
-
|
|
2872
|
+
}
|
|
2873
|
+
function combineAbortSignals(...signals) {
|
|
2874
|
+
const controller = new AbortController();
|
|
2875
|
+
for (const signal of signals) {
|
|
2876
|
+
if (signal.aborted) {
|
|
2877
|
+
controller.abort(signal.reason);
|
|
2878
|
+
break;
|
|
2879
|
+
}
|
|
2880
|
+
signal.addEventListener("abort", () => controller.abort(signal.reason), { once: true });
|
|
2127
2881
|
}
|
|
2128
|
-
return
|
|
2882
|
+
return controller.signal;
|
|
2129
2883
|
}
|
|
2130
2884
|
return {
|
|
2131
2885
|
async getSite(params) {
|
|
2132
|
-
const { slug, domain, id } = params;
|
|
2886
|
+
const { slug, domain, id, signal } = params;
|
|
2133
2887
|
if (!slug && !domain && !id) {
|
|
2134
2888
|
throw new Error(
|
|
2135
2889
|
`getSite() requires at least one identifier: slug, domain, or id. Received: ${JSON.stringify(params)}`
|
|
2136
2890
|
);
|
|
2137
2891
|
}
|
|
2138
2892
|
const cacheKey = `site:${slug || domain || id}`;
|
|
2139
|
-
|
|
2893
|
+
const siteId = id || slug || domain;
|
|
2894
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
2140
2895
|
const apiParams = {};
|
|
2141
2896
|
if (params.slug) apiParams.slug = params.slug;
|
|
2142
2897
|
if (params.domain) apiParams.domain = params.domain;
|
|
2143
2898
|
if (params.id) apiParams.id = params.id;
|
|
2144
|
-
return await apiClient({ endpoint: "getSite", params: apiParams });
|
|
2899
|
+
return await apiClient({ endpoint: "getSite", params: apiParams, options: { signal: sig } });
|
|
2900
|
+
}, {
|
|
2901
|
+
signal,
|
|
2902
|
+
prebuildFallback: prebuildLoader && siteId ? () => prebuildLoader.loadSite(siteId) : void 0
|
|
2145
2903
|
});
|
|
2146
2904
|
},
|
|
2147
2905
|
async getPage(params) {
|
|
2148
|
-
const { siteId, path, preview = false } = params;
|
|
2149
|
-
const cacheKey = `page:${siteId}:${
|
|
2150
|
-
return
|
|
2151
|
-
return await apiClient({ endpoint: "getContentByPath", params: { siteId }, body: { path, preview } });
|
|
2906
|
+
const { siteId, path: path2, preview = false, signal } = params;
|
|
2907
|
+
const cacheKey = `page:${siteId}:${path2}:${preview}`;
|
|
2908
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
2909
|
+
return await apiClient({ endpoint: "getContentByPath", params: { siteId }, body: { path: path2, preview }, options: { signal: sig } });
|
|
2910
|
+
}, {
|
|
2911
|
+
preview,
|
|
2912
|
+
signal,
|
|
2913
|
+
// Prebuild fallback only for published pages (not preview)
|
|
2914
|
+
prebuildFallback: prebuildLoader && !preview ? () => prebuildLoader.loadPage(siteId, path2) : void 0
|
|
2152
2915
|
});
|
|
2153
2916
|
},
|
|
2154
2917
|
async getEntries(params) {
|
|
2155
|
-
const { siteId, contentType, limit, offset, order, preview = false, mode, entryIds, includeMeta } = params;
|
|
2918
|
+
const { siteId, contentType, limit, offset, order, preview = false, mode, entryIds, includeMeta, signal } = params;
|
|
2156
2919
|
const entryIdsCacheKey = mode === "manual" && entryIds?.length ? entryIds.join(",") : "";
|
|
2157
2920
|
const cacheKey = `entries:${siteId}:${contentType}:${limit ?? ""}:${offset ?? ""}:${order ?? ""}:${preview}:${mode ?? ""}:${entryIdsCacheKey}:${includeMeta ?? ""}`;
|
|
2158
|
-
return
|
|
2921
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
2159
2922
|
let orderParam;
|
|
2160
2923
|
if (order === "newest") {
|
|
2161
2924
|
orderParam = "published_at.desc";
|
|
@@ -2177,47 +2940,52 @@ function createRiverbankClient(config) {
|
|
|
2177
2940
|
entryIds: JSON.stringify(entryIds)
|
|
2178
2941
|
}
|
|
2179
2942
|
};
|
|
2180
|
-
return await apiClient({ endpoint: "listPublishedEntries", params: apiParams });
|
|
2943
|
+
return await apiClient({ endpoint: "listPublishedEntries", params: apiParams, options: { signal: sig } });
|
|
2944
|
+
}, {
|
|
2945
|
+
preview,
|
|
2946
|
+
signal,
|
|
2947
|
+
// Prebuild fallback only for published entries (not preview, not manual mode)
|
|
2948
|
+
prebuildFallback: prebuildLoader && !preview ? () => prebuildLoader.loadEntries(siteId, params) : void 0
|
|
2181
2949
|
});
|
|
2182
2950
|
},
|
|
2183
2951
|
async getEntry(params) {
|
|
2184
|
-
const { siteId, contentType, slug } = params;
|
|
2952
|
+
const { siteId, contentType, slug, signal } = params;
|
|
2185
2953
|
const cacheKey = `entry:${siteId}:${contentType}:${slug}`;
|
|
2186
|
-
return
|
|
2187
|
-
return await apiClient({ endpoint: "getPublishedEntryPreview", params: { siteId, type: contentType, slug } });
|
|
2188
|
-
});
|
|
2954
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
2955
|
+
return await apiClient({ endpoint: "getPublishedEntryPreview", params: { siteId, type: contentType, slug }, options: { signal: sig } });
|
|
2956
|
+
}, { signal });
|
|
2189
2957
|
},
|
|
2190
2958
|
async getPublicFormById(params) {
|
|
2191
|
-
const { formId } = params;
|
|
2959
|
+
const { formId, signal } = params;
|
|
2192
2960
|
if (!formId) {
|
|
2193
2961
|
throw new Error("getPublicFormById() requires formId");
|
|
2194
2962
|
}
|
|
2195
2963
|
const cacheKey = `public-form:${formId}`;
|
|
2196
|
-
return
|
|
2197
|
-
return await apiClient({ endpoint: "getPublicFormById", params: { formId } });
|
|
2198
|
-
});
|
|
2964
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
2965
|
+
return await apiClient({ endpoint: "getPublicFormById", params: { formId }, options: { signal: sig } });
|
|
2966
|
+
}, { signal });
|
|
2199
2967
|
},
|
|
2200
2968
|
async getPublicBookingServices(params) {
|
|
2201
|
-
const { siteId, ids } = params;
|
|
2969
|
+
const { siteId, ids, signal } = params;
|
|
2202
2970
|
if (!siteId) {
|
|
2203
2971
|
throw new Error("getPublicBookingServices() requires siteId");
|
|
2204
2972
|
}
|
|
2205
2973
|
const cacheKey = `public-booking-services:${siteId}:${ids ?? ""}`;
|
|
2206
|
-
return
|
|
2974
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
2207
2975
|
const apiParams = {
|
|
2208
2976
|
siteId,
|
|
2209
2977
|
...ids && { ids }
|
|
2210
2978
|
};
|
|
2211
|
-
return await apiClient({ endpoint: "getPublicBookingServices", params: apiParams });
|
|
2212
|
-
});
|
|
2979
|
+
return await apiClient({ endpoint: "getPublicBookingServices", params: apiParams, options: { signal: sig } });
|
|
2980
|
+
}, { signal });
|
|
2213
2981
|
},
|
|
2214
2982
|
async listPublicEvents(params) {
|
|
2215
|
-
const { siteId, limit, from, to, stage } = params;
|
|
2983
|
+
const { siteId, limit, from, to, stage, signal } = params;
|
|
2216
2984
|
if (!siteId) {
|
|
2217
2985
|
throw new Error("listPublicEvents() requires siteId");
|
|
2218
2986
|
}
|
|
2219
2987
|
const cacheKey = `public-events:${siteId}:${limit ?? ""}:${from ?? ""}:${to ?? ""}:${stage ?? ""}`;
|
|
2220
|
-
return
|
|
2988
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
2221
2989
|
const apiParams = {
|
|
2222
2990
|
siteId,
|
|
2223
2991
|
...typeof limit === "number" && { limit: String(limit) },
|
|
@@ -2225,46 +2993,60 @@ function createRiverbankClient(config) {
|
|
|
2225
2993
|
...to && { to },
|
|
2226
2994
|
...stage && { stage }
|
|
2227
2995
|
};
|
|
2228
|
-
return await apiClient({ endpoint: "listPublicEvents", params: apiParams });
|
|
2229
|
-
});
|
|
2996
|
+
return await apiClient({ endpoint: "listPublicEvents", params: apiParams, options: { signal: sig } });
|
|
2997
|
+
}, { signal });
|
|
2230
2998
|
},
|
|
2231
2999
|
async resolveEventOccurrence(params) {
|
|
2232
|
-
const { siteId, entryId, segment } = params;
|
|
3000
|
+
const { siteId, entryId, segment, signal } = params;
|
|
2233
3001
|
if (!siteId || !entryId || !segment) {
|
|
2234
3002
|
throw new Error("resolveEventOccurrence() requires siteId, entryId, and segment");
|
|
2235
3003
|
}
|
|
2236
3004
|
const cacheKey = `event-occurrence:${siteId}:${entryId}:${segment}`;
|
|
2237
|
-
return
|
|
3005
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
2238
3006
|
return await apiClient({
|
|
2239
3007
|
endpoint: "resolveEventOccurrence",
|
|
2240
|
-
params: { siteId, entryId, segment }
|
|
3008
|
+
params: { siteId, entryId, segment },
|
|
3009
|
+
options: { signal: sig }
|
|
2241
3010
|
});
|
|
2242
|
-
});
|
|
3011
|
+
}, { signal });
|
|
2243
3012
|
},
|
|
2244
3013
|
async checkRedirect(params) {
|
|
2245
|
-
const { siteId, path } = params;
|
|
2246
|
-
if (!siteId || !
|
|
3014
|
+
const { siteId, path: path2, signal } = params;
|
|
3015
|
+
if (!siteId || !path2) {
|
|
2247
3016
|
throw new Error("checkRedirect() requires siteId and path");
|
|
2248
3017
|
}
|
|
2249
|
-
const cacheKey = `redirect:${siteId}:${
|
|
2250
|
-
return
|
|
3018
|
+
const cacheKey = `redirect:${siteId}:${path2}`;
|
|
3019
|
+
return resilientFetch(cacheKey, async (sig) => {
|
|
2251
3020
|
return await apiClient({
|
|
2252
3021
|
endpoint: "checkRedirect",
|
|
2253
|
-
params: { site: siteId, path }
|
|
3022
|
+
params: { site: siteId, path: path2 },
|
|
3023
|
+
options: { signal: sig }
|
|
2254
3024
|
});
|
|
2255
|
-
});
|
|
3025
|
+
}, { signal });
|
|
2256
3026
|
},
|
|
2257
3027
|
clearCache() {
|
|
2258
3028
|
cache.clear();
|
|
3029
|
+
},
|
|
3030
|
+
getLastEmittedStatus() {
|
|
3031
|
+
return lastStatus;
|
|
3032
|
+
},
|
|
3033
|
+
getCircuitState() {
|
|
3034
|
+
return circuitBreaker.getState();
|
|
2259
3035
|
}
|
|
2260
|
-
// Cast to RiverbankClient to satisfy overloaded getEntries signature
|
|
2261
|
-
// The implementation correctly returns the right type based on includeMeta
|
|
2262
3036
|
};
|
|
2263
3037
|
}
|
|
2264
3038
|
|
|
2265
3039
|
export {
|
|
2266
3040
|
API_ENDPOINTS,
|
|
2267
3041
|
buildEndpointURL,
|
|
3042
|
+
SDK_VERSION,
|
|
3043
|
+
PREBUILD_PAGE_SIZE,
|
|
3044
|
+
DEFAULT_PREBUILD_DIR,
|
|
3045
|
+
init_constants,
|
|
3046
|
+
canUsePrebuild,
|
|
3047
|
+
PrebuildLoader,
|
|
3048
|
+
createPrebuildLoader,
|
|
3049
|
+
init_loader,
|
|
2268
3050
|
createRiverbankClient
|
|
2269
3051
|
};
|
|
2270
|
-
//# sourceMappingURL=chunk-
|
|
3052
|
+
//# sourceMappingURL=chunk-NFQLH5IA.mjs.map
|