@cmssy/core 12.10.0 → 12.11.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/dist/{content-client-COeyYJl1.d.cts → content-client-65N8ZRq9.d.cts} +11 -4
- package/dist/{content-client-COeyYJl1.d.ts → content-client-65N8ZRq9.d.ts} +11 -4
- package/dist/{csp-BDE0cAZL.d.ts → csp-BnOiGUhR.d.ts} +1 -1
- package/dist/{csp-BMP9bAZ9.d.cts → csp-RaStdD2i.d.cts} +1 -1
- package/dist/index.cjs +88 -23
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +88 -24
- package/dist/internal/locale.cjs +86 -22
- package/dist/internal/locale.d.cts +2 -2
- package/dist/internal/locale.d.ts +2 -2
- package/dist/internal/locale.js +86 -22
- package/dist/internal.cjs +92 -28
- package/dist/internal.d.cts +5 -5
- package/dist/internal.d.ts +5 -5
- package/dist/internal.js +92 -28
- package/dist/{locale-jxsO_8YF.d.ts → locale-D9KI4bND.d.ts} +2 -2
- package/dist/{locale-BM2fwE3O.d.cts → locale-JyBHqpAQ.d.cts} +2 -2
- package/dist/preflight.d.cts +1 -1
- package/dist/preflight.d.ts +1 -1
- package/package.json +1 -1
|
@@ -3,16 +3,23 @@ import { CmssyClientConfig, CmssyLayoutGroup, CmssyPageData, CmssyPageMeta, Cmss
|
|
|
3
3
|
declare class CmssyRequestError extends Error {
|
|
4
4
|
readonly status: number;
|
|
5
5
|
readonly retryAfterMs?: number;
|
|
6
|
-
|
|
6
|
+
readonly waitedMs?: number;
|
|
7
|
+
constructor(message: string, status: number, retryAfterMs?: number, waitedMs?: number);
|
|
7
8
|
}
|
|
8
9
|
interface RetryPolicy {
|
|
9
10
|
maxRetries?: number;
|
|
10
11
|
baseDelayMs?: number;
|
|
12
|
+
throttleBaseDelayMs?: number;
|
|
11
13
|
maxDelayMs?: number;
|
|
12
14
|
maxRetryAfterMs?: number;
|
|
13
|
-
|
|
15
|
+
maxTotalWaitMs?: number;
|
|
16
|
+
retryStatuses?: readonly number[];
|
|
14
17
|
}
|
|
18
|
+
type CmssyRetryMode = "build" | "interactive";
|
|
19
|
+
type RetryOption = CmssyRetryMode | RetryPolicy | false;
|
|
15
20
|
declare const CMSSY_RATE_LIMIT_WINDOW_MS = 60000;
|
|
21
|
+
type ResolvedRetryPolicy = Readonly<Required<RetryPolicy>>;
|
|
22
|
+
declare const CMSSY_RETRY_MODES: Record<CmssyRetryMode, ResolvedRetryPolicy>;
|
|
16
23
|
|
|
17
24
|
declare const DEFAULT_CMSSY_API_URL = "https://api.cmssy.io/graphql";
|
|
18
25
|
declare function resolveApiUrl(apiUrl: string | undefined): string;
|
|
@@ -37,7 +44,7 @@ interface FetchPageOptions {
|
|
|
37
44
|
workspaceId?: string;
|
|
38
45
|
fetch?: FetchLike;
|
|
39
46
|
signal?: AbortSignal;
|
|
40
|
-
retry?:
|
|
47
|
+
retry?: RetryOption;
|
|
41
48
|
}
|
|
42
49
|
declare function fetchPage(config: CmssyClientConfig, path: string | string[] | undefined, options?: FetchPageOptions): Promise<CmssyPageData | null>;
|
|
43
50
|
declare function fetchPageById(config: CmssyClientConfig, pageId: string, options?: Pick<FetchPageOptions, "fetch" | "signal" | "retry">): Promise<CmssyPageData | null>;
|
|
@@ -45,4 +52,4 @@ declare function fetchPages(config: CmssyClientConfig, options?: Pick<FetchPageO
|
|
|
45
52
|
declare function fetchPageMeta(config: CmssyClientConfig, path: string | string[] | undefined, options?: Pick<FetchPageOptions, "fetch" | "signal" | "retry">): Promise<CmssyPageMeta | null>;
|
|
46
53
|
declare function fetchLayouts(config: CmssyClientConfig, path: string | string[] | undefined, options?: FetchPageOptions): Promise<CmssyLayoutGroup[]>;
|
|
47
54
|
|
|
48
|
-
export { CMSSY_RATE_LIMIT_WINDOW_MS as C, DEFAULT_CMSSY_API_URL as D, type FetchLike as F, type
|
|
55
|
+
export { CMSSY_RATE_LIMIT_WINDOW_MS as C, DEFAULT_CMSSY_API_URL as D, type FetchLike as F, type RetryOption as R, CMSSY_RETRY_MODES as a, CmssyRequestError as b, type CmssyRetryMode as c, type FetchLikeResponse as d, type FetchPageOptions as e, type RetryPolicy as f, fetchLayouts as g, fetchPage as h, fetchPageById as i, fetchPageMeta as j, fetchPages as k, resolveApiUrl as r };
|
|
@@ -3,16 +3,23 @@ import { CmssyClientConfig, CmssyLayoutGroup, CmssyPageData, CmssyPageMeta, Cmss
|
|
|
3
3
|
declare class CmssyRequestError extends Error {
|
|
4
4
|
readonly status: number;
|
|
5
5
|
readonly retryAfterMs?: number;
|
|
6
|
-
|
|
6
|
+
readonly waitedMs?: number;
|
|
7
|
+
constructor(message: string, status: number, retryAfterMs?: number, waitedMs?: number);
|
|
7
8
|
}
|
|
8
9
|
interface RetryPolicy {
|
|
9
10
|
maxRetries?: number;
|
|
10
11
|
baseDelayMs?: number;
|
|
12
|
+
throttleBaseDelayMs?: number;
|
|
11
13
|
maxDelayMs?: number;
|
|
12
14
|
maxRetryAfterMs?: number;
|
|
13
|
-
|
|
15
|
+
maxTotalWaitMs?: number;
|
|
16
|
+
retryStatuses?: readonly number[];
|
|
14
17
|
}
|
|
18
|
+
type CmssyRetryMode = "build" | "interactive";
|
|
19
|
+
type RetryOption = CmssyRetryMode | RetryPolicy | false;
|
|
15
20
|
declare const CMSSY_RATE_LIMIT_WINDOW_MS = 60000;
|
|
21
|
+
type ResolvedRetryPolicy = Readonly<Required<RetryPolicy>>;
|
|
22
|
+
declare const CMSSY_RETRY_MODES: Record<CmssyRetryMode, ResolvedRetryPolicy>;
|
|
16
23
|
|
|
17
24
|
declare const DEFAULT_CMSSY_API_URL = "https://api.cmssy.io/graphql";
|
|
18
25
|
declare function resolveApiUrl(apiUrl: string | undefined): string;
|
|
@@ -37,7 +44,7 @@ interface FetchPageOptions {
|
|
|
37
44
|
workspaceId?: string;
|
|
38
45
|
fetch?: FetchLike;
|
|
39
46
|
signal?: AbortSignal;
|
|
40
|
-
retry?:
|
|
47
|
+
retry?: RetryOption;
|
|
41
48
|
}
|
|
42
49
|
declare function fetchPage(config: CmssyClientConfig, path: string | string[] | undefined, options?: FetchPageOptions): Promise<CmssyPageData | null>;
|
|
43
50
|
declare function fetchPageById(config: CmssyClientConfig, pageId: string, options?: Pick<FetchPageOptions, "fetch" | "signal" | "retry">): Promise<CmssyPageData | null>;
|
|
@@ -45,4 +52,4 @@ declare function fetchPages(config: CmssyClientConfig, options?: Pick<FetchPageO
|
|
|
45
52
|
declare function fetchPageMeta(config: CmssyClientConfig, path: string | string[] | undefined, options?: Pick<FetchPageOptions, "fetch" | "signal" | "retry">): Promise<CmssyPageMeta | null>;
|
|
46
53
|
declare function fetchLayouts(config: CmssyClientConfig, path: string | string[] | undefined, options?: FetchPageOptions): Promise<CmssyLayoutGroup[]>;
|
|
47
54
|
|
|
48
|
-
export { CMSSY_RATE_LIMIT_WINDOW_MS as C, DEFAULT_CMSSY_API_URL as D, type FetchLike as F, type
|
|
55
|
+
export { CMSSY_RATE_LIMIT_WINDOW_MS as C, DEFAULT_CMSSY_API_URL as D, type FetchLike as F, type RetryOption as R, CMSSY_RETRY_MODES as a, CmssyRequestError as b, type CmssyRetryMode as c, type FetchLikeResponse as d, type FetchPageOptions as e, type RetryPolicy as f, fetchLayouts as g, fetchPage as h, fetchPageById as i, fetchPageMeta as j, fetchPages as k, resolveApiUrl as r };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CmssyClientConfig, BlockRect, BlockSchema, BlockMeta } from '@cmssy/types';
|
|
2
|
-
import { G as GraphqlRequestOptions } from './locale-
|
|
2
|
+
import { G as GraphqlRequestOptions } from './locale-D9KI4bND.js';
|
|
3
3
|
|
|
4
4
|
declare const DEFAULT_CMSSY_EDITOR_ORIGINS: string[];
|
|
5
5
|
declare function isDevelopment(): boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CmssyClientConfig, BlockRect, BlockSchema, BlockMeta } from '@cmssy/types';
|
|
2
|
-
import { G as GraphqlRequestOptions } from './locale-
|
|
2
|
+
import { G as GraphqlRequestOptions } from './locale-JyBHqpAQ.cjs';
|
|
3
3
|
|
|
4
4
|
declare const DEFAULT_CMSSY_EDITOR_ORIGINS: string[];
|
|
5
5
|
declare function isDevelopment(): boolean;
|
package/dist/index.cjs
CHANGED
|
@@ -77,15 +77,64 @@ Set the listed environment variables (e.g. in .env.local) and restart the dev se
|
|
|
77
77
|
var CmssyRequestError = class extends Error {
|
|
78
78
|
status;
|
|
79
79
|
retryAfterMs;
|
|
80
|
-
|
|
80
|
+
waitedMs;
|
|
81
|
+
constructor(message, status, retryAfterMs2, waitedMs) {
|
|
81
82
|
super(message);
|
|
82
83
|
this.name = "CmssyRequestError";
|
|
83
84
|
this.status = status;
|
|
84
85
|
if (retryAfterMs2 !== void 0) this.retryAfterMs = retryAfterMs2;
|
|
86
|
+
if (waitedMs !== void 0) this.waitedMs = waitedMs;
|
|
85
87
|
}
|
|
86
88
|
};
|
|
87
|
-
var
|
|
89
|
+
var THROTTLE_STATUS = 429;
|
|
88
90
|
var CMSSY_RATE_LIMIT_WINDOW_MS = 6e4;
|
|
91
|
+
var CMSSY_RETRY_MODES = {
|
|
92
|
+
build: {
|
|
93
|
+
maxRetries: 4,
|
|
94
|
+
baseDelayMs: 300,
|
|
95
|
+
throttleBaseDelayMs: 1e3,
|
|
96
|
+
maxDelayMs: 2e4,
|
|
97
|
+
maxRetryAfterMs: CMSSY_RATE_LIMIT_WINDOW_MS,
|
|
98
|
+
maxTotalWaitMs: 18e4,
|
|
99
|
+
retryStatuses: Object.freeze([429, 503])
|
|
100
|
+
},
|
|
101
|
+
interactive: {
|
|
102
|
+
maxRetries: 2,
|
|
103
|
+
baseDelayMs: 50,
|
|
104
|
+
throttleBaseDelayMs: 500,
|
|
105
|
+
maxDelayMs: 1e3,
|
|
106
|
+
maxRetryAfterMs: 1e3,
|
|
107
|
+
maxTotalWaitMs: 2e3,
|
|
108
|
+
retryStatuses: Object.freeze([429, 503])
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
Object.freeze(CMSSY_RETRY_MODES.build);
|
|
112
|
+
Object.freeze(CMSSY_RETRY_MODES.interactive);
|
|
113
|
+
Object.freeze(CMSSY_RETRY_MODES);
|
|
114
|
+
function resolveRetryPolicy(retry) {
|
|
115
|
+
if (retry === false || retry === void 0) return null;
|
|
116
|
+
if (typeof retry === "string") {
|
|
117
|
+
const mode = CMSSY_RETRY_MODES[retry];
|
|
118
|
+
if (!mode) {
|
|
119
|
+
throw new Error(
|
|
120
|
+
`cmssy: unknown retry mode "${retry}" - use ${Object.keys(
|
|
121
|
+
CMSSY_RETRY_MODES
|
|
122
|
+
).map((name2) => `"${name2}"`).join(" or ")}, false, or a retry policy object`
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
return mode;
|
|
126
|
+
}
|
|
127
|
+
const base = CMSSY_RETRY_MODES.build;
|
|
128
|
+
return {
|
|
129
|
+
maxRetries: retry.maxRetries ?? base.maxRetries,
|
|
130
|
+
baseDelayMs: retry.baseDelayMs ?? base.baseDelayMs,
|
|
131
|
+
throttleBaseDelayMs: retry.throttleBaseDelayMs ?? base.throttleBaseDelayMs,
|
|
132
|
+
maxDelayMs: retry.maxDelayMs ?? base.maxDelayMs,
|
|
133
|
+
maxRetryAfterMs: retry.maxRetryAfterMs ?? base.maxRetryAfterMs,
|
|
134
|
+
maxTotalWaitMs: retry.maxTotalWaitMs ?? base.maxTotalWaitMs,
|
|
135
|
+
retryStatuses: retry.retryStatuses ?? base.retryStatuses
|
|
136
|
+
};
|
|
137
|
+
}
|
|
89
138
|
function retryAfterMs(response) {
|
|
90
139
|
const raw = response.headers?.get("retry-after");
|
|
91
140
|
if (!raw) return null;
|
|
@@ -112,28 +161,40 @@ function sleep(ms, signal) {
|
|
|
112
161
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
113
162
|
});
|
|
114
163
|
}
|
|
115
|
-
async function fetchWithRetry(doFetch, url, init, retry) {
|
|
116
|
-
|
|
117
|
-
|
|
164
|
+
async function fetchWithRetry(doFetch, url, init, retry, label) {
|
|
165
|
+
const policy = resolveRetryPolicy(retry);
|
|
166
|
+
if (policy === null) {
|
|
167
|
+
return { response: await doFetch(url, init), waitedMs: 0 };
|
|
118
168
|
}
|
|
119
|
-
const maxRetries = retry.maxRetries ?? 3;
|
|
120
|
-
const baseDelayMs = retry.baseDelayMs ?? 300;
|
|
121
|
-
const maxDelayMs = retry.maxDelayMs ?? 3e3;
|
|
122
|
-
const maxRetryAfterMs = retry.maxRetryAfterMs ?? CMSSY_RATE_LIMIT_WINDOW_MS;
|
|
123
|
-
const retryStatuses = retry.retryStatuses ?? DEFAULT_RETRY_STATUSES;
|
|
124
169
|
let response = await doFetch(url, init);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
170
|
+
let waitedMs = 0;
|
|
171
|
+
for (let attempt = 0; attempt < policy.maxRetries; attempt++) {
|
|
172
|
+
if (response.ok || !policy.retryStatuses.includes(response.status)) {
|
|
173
|
+
return { response, waitedMs };
|
|
128
174
|
}
|
|
175
|
+
const throttled = response.status === THROTTLE_STATUS;
|
|
129
176
|
const asked = retryAfterMs(response);
|
|
130
|
-
if (asked !== null && asked > maxRetryAfterMs)
|
|
131
|
-
|
|
132
|
-
|
|
177
|
+
if (asked !== null && asked > policy.maxRetryAfterMs) {
|
|
178
|
+
return { response, waitedMs };
|
|
179
|
+
}
|
|
180
|
+
const base = throttled ? policy.throttleBaseDelayMs : policy.baseDelayMs;
|
|
181
|
+
const wait = Math.round(
|
|
182
|
+
asked !== null ? Math.min(
|
|
183
|
+
asked + Math.random() * policy.throttleBaseDelayMs,
|
|
184
|
+
policy.maxRetryAfterMs
|
|
185
|
+
) : Math.random() * Math.min(base * 2 ** attempt, policy.maxDelayMs)
|
|
186
|
+
);
|
|
187
|
+
if (waitedMs + wait > policy.maxTotalWaitMs) {
|
|
188
|
+
return { response, waitedMs };
|
|
189
|
+
}
|
|
190
|
+
console.warn(
|
|
191
|
+
`[cmssy] ${label} got ${response.status}, retrying in ${wait}ms (attempt ${attempt + 1}/${policy.maxRetries})`
|
|
192
|
+
);
|
|
133
193
|
await sleep(wait, init.signal);
|
|
194
|
+
waitedMs += wait;
|
|
134
195
|
response = await doFetch(url, init);
|
|
135
196
|
}
|
|
136
|
-
return response;
|
|
197
|
+
return { response, waitedMs };
|
|
137
198
|
}
|
|
138
199
|
async function postGraphql(url, query, variables, options) {
|
|
139
200
|
const doFetch = options.fetch ?? globalThis.fetch;
|
|
@@ -142,7 +203,7 @@ async function postGraphql(url, query, variables, options) {
|
|
|
142
203
|
"cmssy: no fetch implementation available - pass options.fetch"
|
|
143
204
|
);
|
|
144
205
|
}
|
|
145
|
-
const response = await fetchWithRetry(
|
|
206
|
+
const { response, waitedMs } = await fetchWithRetry(
|
|
146
207
|
doFetch,
|
|
147
208
|
url,
|
|
148
209
|
{
|
|
@@ -151,7 +212,8 @@ async function postGraphql(url, query, variables, options) {
|
|
|
151
212
|
body: JSON.stringify({ query, variables }),
|
|
152
213
|
signal: options.signal
|
|
153
214
|
},
|
|
154
|
-
options.retry
|
|
215
|
+
options.retry,
|
|
216
|
+
options.label
|
|
155
217
|
);
|
|
156
218
|
if (!response.ok) {
|
|
157
219
|
let detail = "";
|
|
@@ -165,10 +227,12 @@ async function postGraphql(url, query, variables, options) {
|
|
|
165
227
|
}
|
|
166
228
|
const asked = retryAfterMs(response);
|
|
167
229
|
const wait = asked !== null ? ` - retry after ${Math.ceil(asked / 1e3)}s` : "";
|
|
230
|
+
const spent = waitedMs > 0 ? ` - gave up after waiting ${waitedMs}ms` : "";
|
|
168
231
|
throw new CmssyRequestError(
|
|
169
|
-
`cmssy: ${options.label} failed (${response.status})${detail}${wait}`,
|
|
232
|
+
`cmssy: ${options.label} failed (${response.status})${detail}${wait}${spent}`,
|
|
170
233
|
response.status,
|
|
171
|
-
asked ?? void 0
|
|
234
|
+
asked ?? void 0,
|
|
235
|
+
waitedMs > 0 ? waitedMs : void 0
|
|
172
236
|
);
|
|
173
237
|
}
|
|
174
238
|
let json;
|
|
@@ -387,7 +451,7 @@ async function fetchSiteConfig(config, options = {}) {
|
|
|
387
451
|
config,
|
|
388
452
|
SITE_CONFIG_QUERY,
|
|
389
453
|
{ workspaceSlug: config.workspaceSlug },
|
|
390
|
-
{ ...options, public: true, retry: options.retry ??
|
|
454
|
+
{ ...options, public: true, retry: options.retry ?? "build" },
|
|
391
455
|
"site config query"
|
|
392
456
|
);
|
|
393
457
|
return data.public?.siteConfig ?? null;
|
|
@@ -575,7 +639,7 @@ async function loadSiteLocales(config, options) {
|
|
|
575
639
|
config,
|
|
576
640
|
SITE_CONFIG_QUERY,
|
|
577
641
|
{ workspaceSlug: config.workspaceSlug },
|
|
578
|
-
{ ...options, public: true, retry: options?.retry ??
|
|
642
|
+
{ ...options, public: true, retry: options?.retry ?? "build" },
|
|
579
643
|
"site config"
|
|
580
644
|
);
|
|
581
645
|
value = localesFromSiteConfig(data.public?.siteConfig ?? null);
|
|
@@ -902,6 +966,7 @@ exports.CMSSY_EDIT_HEADER = CMSSY_EDIT_HEADER;
|
|
|
902
966
|
exports.CMSSY_EDIT_QUERY_PARAM = CMSSY_EDIT_QUERY_PARAM;
|
|
903
967
|
exports.CMSSY_LOCALE_HEADER = CMSSY_LOCALE_HEADER;
|
|
904
968
|
exports.CMSSY_RATE_LIMIT_WINDOW_MS = CMSSY_RATE_LIMIT_WINDOW_MS;
|
|
969
|
+
exports.CMSSY_RETRY_MODES = CMSSY_RETRY_MODES;
|
|
905
970
|
exports.CMSSY_SECRET_QUERY_PARAM = CMSSY_SECRET_QUERY_PARAM;
|
|
906
971
|
exports.CmssyRequestError = CmssyRequestError;
|
|
907
972
|
exports.CmssyWebhookError = CmssyWebhookError;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { A as AppToEditorMessage, B as BoundsMessage, C as ClickMessage, a as CmssyClient, b as CmssyConfig, c as CmssyCspOptions, d as CmssyEnvConfig, e as CmssyTypedDocument, D as DEFAULT_CMSSY_EDITOR_ORIGINS, E as EditorToAppMessage, I as InvisibleBlock, f as InvisibleBlocksMessage, P as PROTOCOL_VERSION, g as ParentReadyMessage, h as PatchMessage, i as PostTarget, Q as QueryScopedOptions, R as ReadyMessage, S as SHORTCUT_ACTIONS, j as SelectMessage, k as ShortcutAction, l as ShortcutMessage, V as ViewportMessage, m as applyCmssyCsp, n as createCmssyClient, o as defineCmssyConfig, p as isProtocolCompatible, q as normalizeOrigin, r as parseEditorMessage, s as postToEditor, t as resolveEditorOrigin } from './csp-
|
|
2
|
-
export { C as CMSSY_LOCALE_HEADER, G as GraphqlRequestOptions, g as graphqlRequest, l as localizeHref, r as resolveCmssyLocale } from './locale-
|
|
3
|
-
export { C as CMSSY_RATE_LIMIT_WINDOW_MS, a as CmssyRequestError, D as DEFAULT_CMSSY_API_URL, F as FetchLike,
|
|
1
|
+
export { A as AppToEditorMessage, B as BoundsMessage, C as ClickMessage, a as CmssyClient, b as CmssyConfig, c as CmssyCspOptions, d as CmssyEnvConfig, e as CmssyTypedDocument, D as DEFAULT_CMSSY_EDITOR_ORIGINS, E as EditorToAppMessage, I as InvisibleBlock, f as InvisibleBlocksMessage, P as PROTOCOL_VERSION, g as ParentReadyMessage, h as PatchMessage, i as PostTarget, Q as QueryScopedOptions, R as ReadyMessage, S as SHORTCUT_ACTIONS, j as SelectMessage, k as ShortcutAction, l as ShortcutMessage, V as ViewportMessage, m as applyCmssyCsp, n as createCmssyClient, o as defineCmssyConfig, p as isProtocolCompatible, q as normalizeOrigin, r as parseEditorMessage, s as postToEditor, t as resolveEditorOrigin } from './csp-RaStdD2i.cjs';
|
|
2
|
+
export { C as CMSSY_LOCALE_HEADER, G as GraphqlRequestOptions, g as graphqlRequest, l as localizeHref, r as resolveCmssyLocale } from './locale-JyBHqpAQ.cjs';
|
|
3
|
+
export { C as CMSSY_RATE_LIMIT_WINDOW_MS, a as CMSSY_RETRY_MODES, b as CmssyRequestError, c as CmssyRetryMode, D as DEFAULT_CMSSY_API_URL, F as FetchLike, d as FetchLikeResponse, e as FetchPageOptions, R as RetryOption, f as RetryPolicy } from './content-client-65N8ZRq9.cjs';
|
|
4
4
|
import * as _cmssy_types from '@cmssy/types';
|
|
5
5
|
import { FieldOptions, TypedField, ResolvedMediaValue, PageRef, BlockPropsSchema, InferBlockContent, RelationMode, CmssyModelRecord, ResolvedMedia, VerifyCmssyWebhookOptions, CmssyWebhookEvent } from '@cmssy/types';
|
|
6
6
|
export { BlockMeta, BlockPropsSchema, BlockRect, BlockSchema, BuildBlockContextExtra, CmssyBlockAuthContext, CmssyBlockContext, CmssyBlockMember, CmssyBlockPage, CmssyBlockWorkspace, CmssyBranding, CmssyClientConfig, CmssyFormDefinition, CmssyFormField, CmssyFormSettings, CmssyFormSubmitResponse, CmssyLayoutGroup, CmssyLayoutSettings, CmssyLocaleContext, CmssyLocalizedValue, CmssyModelDefinition, CmssyModelRecord, CmssyPageData, CmssyPageMeta, CmssyPageSummary, CmssyRecordList, CmssySiteConfig, CmssyWebhookEvent, CmssyWebhookOrder, FieldCondition, FieldConditionGroup, FieldConditionLogic, FieldControl, FieldDefinition, FieldOptions, FieldType, InferBlockContent, LayoutPosition, RawBlock, RawLayoutBlock, SubmitFormInput, TypedField, VerifyCmssyWebhookOptions, evaluateFieldConditionGroup, layoutPositionValues } from '@cmssy/types';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { A as AppToEditorMessage, B as BoundsMessage, C as ClickMessage, a as CmssyClient, b as CmssyConfig, c as CmssyCspOptions, d as CmssyEnvConfig, e as CmssyTypedDocument, D as DEFAULT_CMSSY_EDITOR_ORIGINS, E as EditorToAppMessage, I as InvisibleBlock, f as InvisibleBlocksMessage, P as PROTOCOL_VERSION, g as ParentReadyMessage, h as PatchMessage, i as PostTarget, Q as QueryScopedOptions, R as ReadyMessage, S as SHORTCUT_ACTIONS, j as SelectMessage, k as ShortcutAction, l as ShortcutMessage, V as ViewportMessage, m as applyCmssyCsp, n as createCmssyClient, o as defineCmssyConfig, p as isProtocolCompatible, q as normalizeOrigin, r as parseEditorMessage, s as postToEditor, t as resolveEditorOrigin } from './csp-
|
|
2
|
-
export { C as CMSSY_LOCALE_HEADER, G as GraphqlRequestOptions, g as graphqlRequest, l as localizeHref, r as resolveCmssyLocale } from './locale-
|
|
3
|
-
export { C as CMSSY_RATE_LIMIT_WINDOW_MS, a as CmssyRequestError, D as DEFAULT_CMSSY_API_URL, F as FetchLike,
|
|
1
|
+
export { A as AppToEditorMessage, B as BoundsMessage, C as ClickMessage, a as CmssyClient, b as CmssyConfig, c as CmssyCspOptions, d as CmssyEnvConfig, e as CmssyTypedDocument, D as DEFAULT_CMSSY_EDITOR_ORIGINS, E as EditorToAppMessage, I as InvisibleBlock, f as InvisibleBlocksMessage, P as PROTOCOL_VERSION, g as ParentReadyMessage, h as PatchMessage, i as PostTarget, Q as QueryScopedOptions, R as ReadyMessage, S as SHORTCUT_ACTIONS, j as SelectMessage, k as ShortcutAction, l as ShortcutMessage, V as ViewportMessage, m as applyCmssyCsp, n as createCmssyClient, o as defineCmssyConfig, p as isProtocolCompatible, q as normalizeOrigin, r as parseEditorMessage, s as postToEditor, t as resolveEditorOrigin } from './csp-BnOiGUhR.js';
|
|
2
|
+
export { C as CMSSY_LOCALE_HEADER, G as GraphqlRequestOptions, g as graphqlRequest, l as localizeHref, r as resolveCmssyLocale } from './locale-D9KI4bND.js';
|
|
3
|
+
export { C as CMSSY_RATE_LIMIT_WINDOW_MS, a as CMSSY_RETRY_MODES, b as CmssyRequestError, c as CmssyRetryMode, D as DEFAULT_CMSSY_API_URL, F as FetchLike, d as FetchLikeResponse, e as FetchPageOptions, R as RetryOption, f as RetryPolicy } from './content-client-65N8ZRq9.js';
|
|
4
4
|
import * as _cmssy_types from '@cmssy/types';
|
|
5
5
|
import { FieldOptions, TypedField, ResolvedMediaValue, PageRef, BlockPropsSchema, InferBlockContent, RelationMode, CmssyModelRecord, ResolvedMedia, VerifyCmssyWebhookOptions, CmssyWebhookEvent } from '@cmssy/types';
|
|
6
6
|
export { BlockMeta, BlockPropsSchema, BlockRect, BlockSchema, BuildBlockContextExtra, CmssyBlockAuthContext, CmssyBlockContext, CmssyBlockMember, CmssyBlockPage, CmssyBlockWorkspace, CmssyBranding, CmssyClientConfig, CmssyFormDefinition, CmssyFormField, CmssyFormSettings, CmssyFormSubmitResponse, CmssyLayoutGroup, CmssyLayoutSettings, CmssyLocaleContext, CmssyLocalizedValue, CmssyModelDefinition, CmssyModelRecord, CmssyPageData, CmssyPageMeta, CmssyPageSummary, CmssyRecordList, CmssySiteConfig, CmssyWebhookEvent, CmssyWebhookOrder, FieldCondition, FieldConditionGroup, FieldConditionLogic, FieldControl, FieldDefinition, FieldOptions, FieldType, InferBlockContent, LayoutPosition, RawBlock, RawLayoutBlock, SubmitFormInput, TypedField, VerifyCmssyWebhookOptions, evaluateFieldConditionGroup, layoutPositionValues } from '@cmssy/types';
|
package/dist/index.js
CHANGED
|
@@ -75,15 +75,64 @@ Set the listed environment variables (e.g. in .env.local) and restart the dev se
|
|
|
75
75
|
var CmssyRequestError = class extends Error {
|
|
76
76
|
status;
|
|
77
77
|
retryAfterMs;
|
|
78
|
-
|
|
78
|
+
waitedMs;
|
|
79
|
+
constructor(message, status, retryAfterMs2, waitedMs) {
|
|
79
80
|
super(message);
|
|
80
81
|
this.name = "CmssyRequestError";
|
|
81
82
|
this.status = status;
|
|
82
83
|
if (retryAfterMs2 !== void 0) this.retryAfterMs = retryAfterMs2;
|
|
84
|
+
if (waitedMs !== void 0) this.waitedMs = waitedMs;
|
|
83
85
|
}
|
|
84
86
|
};
|
|
85
|
-
var
|
|
87
|
+
var THROTTLE_STATUS = 429;
|
|
86
88
|
var CMSSY_RATE_LIMIT_WINDOW_MS = 6e4;
|
|
89
|
+
var CMSSY_RETRY_MODES = {
|
|
90
|
+
build: {
|
|
91
|
+
maxRetries: 4,
|
|
92
|
+
baseDelayMs: 300,
|
|
93
|
+
throttleBaseDelayMs: 1e3,
|
|
94
|
+
maxDelayMs: 2e4,
|
|
95
|
+
maxRetryAfterMs: CMSSY_RATE_LIMIT_WINDOW_MS,
|
|
96
|
+
maxTotalWaitMs: 18e4,
|
|
97
|
+
retryStatuses: Object.freeze([429, 503])
|
|
98
|
+
},
|
|
99
|
+
interactive: {
|
|
100
|
+
maxRetries: 2,
|
|
101
|
+
baseDelayMs: 50,
|
|
102
|
+
throttleBaseDelayMs: 500,
|
|
103
|
+
maxDelayMs: 1e3,
|
|
104
|
+
maxRetryAfterMs: 1e3,
|
|
105
|
+
maxTotalWaitMs: 2e3,
|
|
106
|
+
retryStatuses: Object.freeze([429, 503])
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
Object.freeze(CMSSY_RETRY_MODES.build);
|
|
110
|
+
Object.freeze(CMSSY_RETRY_MODES.interactive);
|
|
111
|
+
Object.freeze(CMSSY_RETRY_MODES);
|
|
112
|
+
function resolveRetryPolicy(retry) {
|
|
113
|
+
if (retry === false || retry === void 0) return null;
|
|
114
|
+
if (typeof retry === "string") {
|
|
115
|
+
const mode = CMSSY_RETRY_MODES[retry];
|
|
116
|
+
if (!mode) {
|
|
117
|
+
throw new Error(
|
|
118
|
+
`cmssy: unknown retry mode "${retry}" - use ${Object.keys(
|
|
119
|
+
CMSSY_RETRY_MODES
|
|
120
|
+
).map((name2) => `"${name2}"`).join(" or ")}, false, or a retry policy object`
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
return mode;
|
|
124
|
+
}
|
|
125
|
+
const base = CMSSY_RETRY_MODES.build;
|
|
126
|
+
return {
|
|
127
|
+
maxRetries: retry.maxRetries ?? base.maxRetries,
|
|
128
|
+
baseDelayMs: retry.baseDelayMs ?? base.baseDelayMs,
|
|
129
|
+
throttleBaseDelayMs: retry.throttleBaseDelayMs ?? base.throttleBaseDelayMs,
|
|
130
|
+
maxDelayMs: retry.maxDelayMs ?? base.maxDelayMs,
|
|
131
|
+
maxRetryAfterMs: retry.maxRetryAfterMs ?? base.maxRetryAfterMs,
|
|
132
|
+
maxTotalWaitMs: retry.maxTotalWaitMs ?? base.maxTotalWaitMs,
|
|
133
|
+
retryStatuses: retry.retryStatuses ?? base.retryStatuses
|
|
134
|
+
};
|
|
135
|
+
}
|
|
87
136
|
function retryAfterMs(response) {
|
|
88
137
|
const raw = response.headers?.get("retry-after");
|
|
89
138
|
if (!raw) return null;
|
|
@@ -110,28 +159,40 @@ function sleep(ms, signal) {
|
|
|
110
159
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
111
160
|
});
|
|
112
161
|
}
|
|
113
|
-
async function fetchWithRetry(doFetch, url, init, retry) {
|
|
114
|
-
|
|
115
|
-
|
|
162
|
+
async function fetchWithRetry(doFetch, url, init, retry, label) {
|
|
163
|
+
const policy = resolveRetryPolicy(retry);
|
|
164
|
+
if (policy === null) {
|
|
165
|
+
return { response: await doFetch(url, init), waitedMs: 0 };
|
|
116
166
|
}
|
|
117
|
-
const maxRetries = retry.maxRetries ?? 3;
|
|
118
|
-
const baseDelayMs = retry.baseDelayMs ?? 300;
|
|
119
|
-
const maxDelayMs = retry.maxDelayMs ?? 3e3;
|
|
120
|
-
const maxRetryAfterMs = retry.maxRetryAfterMs ?? CMSSY_RATE_LIMIT_WINDOW_MS;
|
|
121
|
-
const retryStatuses = retry.retryStatuses ?? DEFAULT_RETRY_STATUSES;
|
|
122
167
|
let response = await doFetch(url, init);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
168
|
+
let waitedMs = 0;
|
|
169
|
+
for (let attempt = 0; attempt < policy.maxRetries; attempt++) {
|
|
170
|
+
if (response.ok || !policy.retryStatuses.includes(response.status)) {
|
|
171
|
+
return { response, waitedMs };
|
|
126
172
|
}
|
|
173
|
+
const throttled = response.status === THROTTLE_STATUS;
|
|
127
174
|
const asked = retryAfterMs(response);
|
|
128
|
-
if (asked !== null && asked > maxRetryAfterMs)
|
|
129
|
-
|
|
130
|
-
|
|
175
|
+
if (asked !== null && asked > policy.maxRetryAfterMs) {
|
|
176
|
+
return { response, waitedMs };
|
|
177
|
+
}
|
|
178
|
+
const base = throttled ? policy.throttleBaseDelayMs : policy.baseDelayMs;
|
|
179
|
+
const wait = Math.round(
|
|
180
|
+
asked !== null ? Math.min(
|
|
181
|
+
asked + Math.random() * policy.throttleBaseDelayMs,
|
|
182
|
+
policy.maxRetryAfterMs
|
|
183
|
+
) : Math.random() * Math.min(base * 2 ** attempt, policy.maxDelayMs)
|
|
184
|
+
);
|
|
185
|
+
if (waitedMs + wait > policy.maxTotalWaitMs) {
|
|
186
|
+
return { response, waitedMs };
|
|
187
|
+
}
|
|
188
|
+
console.warn(
|
|
189
|
+
`[cmssy] ${label} got ${response.status}, retrying in ${wait}ms (attempt ${attempt + 1}/${policy.maxRetries})`
|
|
190
|
+
);
|
|
131
191
|
await sleep(wait, init.signal);
|
|
192
|
+
waitedMs += wait;
|
|
132
193
|
response = await doFetch(url, init);
|
|
133
194
|
}
|
|
134
|
-
return response;
|
|
195
|
+
return { response, waitedMs };
|
|
135
196
|
}
|
|
136
197
|
async function postGraphql(url, query, variables, options) {
|
|
137
198
|
const doFetch = options.fetch ?? globalThis.fetch;
|
|
@@ -140,7 +201,7 @@ async function postGraphql(url, query, variables, options) {
|
|
|
140
201
|
"cmssy: no fetch implementation available - pass options.fetch"
|
|
141
202
|
);
|
|
142
203
|
}
|
|
143
|
-
const response = await fetchWithRetry(
|
|
204
|
+
const { response, waitedMs } = await fetchWithRetry(
|
|
144
205
|
doFetch,
|
|
145
206
|
url,
|
|
146
207
|
{
|
|
@@ -149,7 +210,8 @@ async function postGraphql(url, query, variables, options) {
|
|
|
149
210
|
body: JSON.stringify({ query, variables }),
|
|
150
211
|
signal: options.signal
|
|
151
212
|
},
|
|
152
|
-
options.retry
|
|
213
|
+
options.retry,
|
|
214
|
+
options.label
|
|
153
215
|
);
|
|
154
216
|
if (!response.ok) {
|
|
155
217
|
let detail = "";
|
|
@@ -163,10 +225,12 @@ async function postGraphql(url, query, variables, options) {
|
|
|
163
225
|
}
|
|
164
226
|
const asked = retryAfterMs(response);
|
|
165
227
|
const wait = asked !== null ? ` - retry after ${Math.ceil(asked / 1e3)}s` : "";
|
|
228
|
+
const spent = waitedMs > 0 ? ` - gave up after waiting ${waitedMs}ms` : "";
|
|
166
229
|
throw new CmssyRequestError(
|
|
167
|
-
`cmssy: ${options.label} failed (${response.status})${detail}${wait}`,
|
|
230
|
+
`cmssy: ${options.label} failed (${response.status})${detail}${wait}${spent}`,
|
|
168
231
|
response.status,
|
|
169
|
-
asked ?? void 0
|
|
232
|
+
asked ?? void 0,
|
|
233
|
+
waitedMs > 0 ? waitedMs : void 0
|
|
170
234
|
);
|
|
171
235
|
}
|
|
172
236
|
let json;
|
|
@@ -385,7 +449,7 @@ async function fetchSiteConfig(config, options = {}) {
|
|
|
385
449
|
config,
|
|
386
450
|
SITE_CONFIG_QUERY,
|
|
387
451
|
{ workspaceSlug: config.workspaceSlug },
|
|
388
|
-
{ ...options, public: true, retry: options.retry ??
|
|
452
|
+
{ ...options, public: true, retry: options.retry ?? "build" },
|
|
389
453
|
"site config query"
|
|
390
454
|
);
|
|
391
455
|
return data.public?.siteConfig ?? null;
|
|
@@ -573,7 +637,7 @@ async function loadSiteLocales(config, options) {
|
|
|
573
637
|
config,
|
|
574
638
|
SITE_CONFIG_QUERY,
|
|
575
639
|
{ workspaceSlug: config.workspaceSlug },
|
|
576
|
-
{ ...options, public: true, retry: options?.retry ??
|
|
640
|
+
{ ...options, public: true, retry: options?.retry ?? "build" },
|
|
577
641
|
"site config"
|
|
578
642
|
);
|
|
579
643
|
value = localesFromSiteConfig(data.public?.siteConfig ?? null);
|
|
@@ -888,4 +952,4 @@ async function verifyCmssyWebhook(options) {
|
|
|
888
952
|
return parsed;
|
|
889
953
|
}
|
|
890
954
|
|
|
891
|
-
export { CMSSY_EDIT_HEADER, CMSSY_EDIT_QUERY_PARAM, CMSSY_LOCALE_HEADER, CMSSY_RATE_LIMIT_WINDOW_MS, CMSSY_SECRET_QUERY_PARAM, CmssyRequestError, CmssyWebhookError, DEFAULT_CMSSY_API_URL, DEFAULT_CMSSY_EDITOR_ORIGINS, PROTOCOL_VERSION, SHORTCUT_ACTIONS, applyCmssyCsp, createCmssyClient, defineCmssyConfig, fields, graphqlRequest, isProtocolCompatible, isVerifiedEditUrl, localizeHref, mediaAlt, mediaUrl, mediaUrls, normalizeOrigin, parseEditorMessage, postToEditor, resolveCmssyLocale, resolveEditorOrigin, verifyCmssyWebhook };
|
|
955
|
+
export { CMSSY_EDIT_HEADER, CMSSY_EDIT_QUERY_PARAM, CMSSY_LOCALE_HEADER, CMSSY_RATE_LIMIT_WINDOW_MS, CMSSY_RETRY_MODES, CMSSY_SECRET_QUERY_PARAM, CmssyRequestError, CmssyWebhookError, DEFAULT_CMSSY_API_URL, DEFAULT_CMSSY_EDITOR_ORIGINS, PROTOCOL_VERSION, SHORTCUT_ACTIONS, applyCmssyCsp, createCmssyClient, defineCmssyConfig, fields, graphqlRequest, isProtocolCompatible, isVerifiedEditUrl, localizeHref, mediaAlt, mediaUrl, mediaUrls, normalizeOrigin, parseEditorMessage, postToEditor, resolveCmssyLocale, resolveEditorOrigin, verifyCmssyWebhook };
|
package/dist/internal/locale.cjs
CHANGED
|
@@ -4,15 +4,64 @@
|
|
|
4
4
|
var CmssyRequestError = class extends Error {
|
|
5
5
|
status;
|
|
6
6
|
retryAfterMs;
|
|
7
|
-
|
|
7
|
+
waitedMs;
|
|
8
|
+
constructor(message, status, retryAfterMs2, waitedMs) {
|
|
8
9
|
super(message);
|
|
9
10
|
this.name = "CmssyRequestError";
|
|
10
11
|
this.status = status;
|
|
11
12
|
if (retryAfterMs2 !== void 0) this.retryAfterMs = retryAfterMs2;
|
|
13
|
+
if (waitedMs !== void 0) this.waitedMs = waitedMs;
|
|
12
14
|
}
|
|
13
15
|
};
|
|
14
|
-
var
|
|
16
|
+
var THROTTLE_STATUS = 429;
|
|
15
17
|
var CMSSY_RATE_LIMIT_WINDOW_MS = 6e4;
|
|
18
|
+
var CMSSY_RETRY_MODES = {
|
|
19
|
+
build: {
|
|
20
|
+
maxRetries: 4,
|
|
21
|
+
baseDelayMs: 300,
|
|
22
|
+
throttleBaseDelayMs: 1e3,
|
|
23
|
+
maxDelayMs: 2e4,
|
|
24
|
+
maxRetryAfterMs: CMSSY_RATE_LIMIT_WINDOW_MS,
|
|
25
|
+
maxTotalWaitMs: 18e4,
|
|
26
|
+
retryStatuses: Object.freeze([429, 503])
|
|
27
|
+
},
|
|
28
|
+
interactive: {
|
|
29
|
+
maxRetries: 2,
|
|
30
|
+
baseDelayMs: 50,
|
|
31
|
+
throttleBaseDelayMs: 500,
|
|
32
|
+
maxDelayMs: 1e3,
|
|
33
|
+
maxRetryAfterMs: 1e3,
|
|
34
|
+
maxTotalWaitMs: 2e3,
|
|
35
|
+
retryStatuses: Object.freeze([429, 503])
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.freeze(CMSSY_RETRY_MODES.build);
|
|
39
|
+
Object.freeze(CMSSY_RETRY_MODES.interactive);
|
|
40
|
+
Object.freeze(CMSSY_RETRY_MODES);
|
|
41
|
+
function resolveRetryPolicy(retry) {
|
|
42
|
+
if (retry === false || retry === void 0) return null;
|
|
43
|
+
if (typeof retry === "string") {
|
|
44
|
+
const mode = CMSSY_RETRY_MODES[retry];
|
|
45
|
+
if (!mode) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`cmssy: unknown retry mode "${retry}" - use ${Object.keys(
|
|
48
|
+
CMSSY_RETRY_MODES
|
|
49
|
+
).map((name) => `"${name}"`).join(" or ")}, false, or a retry policy object`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
return mode;
|
|
53
|
+
}
|
|
54
|
+
const base = CMSSY_RETRY_MODES.build;
|
|
55
|
+
return {
|
|
56
|
+
maxRetries: retry.maxRetries ?? base.maxRetries,
|
|
57
|
+
baseDelayMs: retry.baseDelayMs ?? base.baseDelayMs,
|
|
58
|
+
throttleBaseDelayMs: retry.throttleBaseDelayMs ?? base.throttleBaseDelayMs,
|
|
59
|
+
maxDelayMs: retry.maxDelayMs ?? base.maxDelayMs,
|
|
60
|
+
maxRetryAfterMs: retry.maxRetryAfterMs ?? base.maxRetryAfterMs,
|
|
61
|
+
maxTotalWaitMs: retry.maxTotalWaitMs ?? base.maxTotalWaitMs,
|
|
62
|
+
retryStatuses: retry.retryStatuses ?? base.retryStatuses
|
|
63
|
+
};
|
|
64
|
+
}
|
|
16
65
|
function retryAfterMs(response) {
|
|
17
66
|
const raw = response.headers?.get("retry-after");
|
|
18
67
|
if (!raw) return null;
|
|
@@ -39,28 +88,40 @@ function sleep(ms, signal) {
|
|
|
39
88
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
40
89
|
});
|
|
41
90
|
}
|
|
42
|
-
async function fetchWithRetry(doFetch, url, init, retry) {
|
|
43
|
-
|
|
44
|
-
|
|
91
|
+
async function fetchWithRetry(doFetch, url, init, retry, label) {
|
|
92
|
+
const policy = resolveRetryPolicy(retry);
|
|
93
|
+
if (policy === null) {
|
|
94
|
+
return { response: await doFetch(url, init), waitedMs: 0 };
|
|
45
95
|
}
|
|
46
|
-
const maxRetries = retry.maxRetries ?? 3;
|
|
47
|
-
const baseDelayMs = retry.baseDelayMs ?? 300;
|
|
48
|
-
const maxDelayMs = retry.maxDelayMs ?? 3e3;
|
|
49
|
-
const maxRetryAfterMs = retry.maxRetryAfterMs ?? CMSSY_RATE_LIMIT_WINDOW_MS;
|
|
50
|
-
const retryStatuses = retry.retryStatuses ?? DEFAULT_RETRY_STATUSES;
|
|
51
96
|
let response = await doFetch(url, init);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
97
|
+
let waitedMs = 0;
|
|
98
|
+
for (let attempt = 0; attempt < policy.maxRetries; attempt++) {
|
|
99
|
+
if (response.ok || !policy.retryStatuses.includes(response.status)) {
|
|
100
|
+
return { response, waitedMs };
|
|
55
101
|
}
|
|
102
|
+
const throttled = response.status === THROTTLE_STATUS;
|
|
56
103
|
const asked = retryAfterMs(response);
|
|
57
|
-
if (asked !== null && asked > maxRetryAfterMs)
|
|
58
|
-
|
|
59
|
-
|
|
104
|
+
if (asked !== null && asked > policy.maxRetryAfterMs) {
|
|
105
|
+
return { response, waitedMs };
|
|
106
|
+
}
|
|
107
|
+
const base = throttled ? policy.throttleBaseDelayMs : policy.baseDelayMs;
|
|
108
|
+
const wait = Math.round(
|
|
109
|
+
asked !== null ? Math.min(
|
|
110
|
+
asked + Math.random() * policy.throttleBaseDelayMs,
|
|
111
|
+
policy.maxRetryAfterMs
|
|
112
|
+
) : Math.random() * Math.min(base * 2 ** attempt, policy.maxDelayMs)
|
|
113
|
+
);
|
|
114
|
+
if (waitedMs + wait > policy.maxTotalWaitMs) {
|
|
115
|
+
return { response, waitedMs };
|
|
116
|
+
}
|
|
117
|
+
console.warn(
|
|
118
|
+
`[cmssy] ${label} got ${response.status}, retrying in ${wait}ms (attempt ${attempt + 1}/${policy.maxRetries})`
|
|
119
|
+
);
|
|
60
120
|
await sleep(wait, init.signal);
|
|
121
|
+
waitedMs += wait;
|
|
61
122
|
response = await doFetch(url, init);
|
|
62
123
|
}
|
|
63
|
-
return response;
|
|
124
|
+
return { response, waitedMs };
|
|
64
125
|
}
|
|
65
126
|
async function postGraphql(url, query, variables, options) {
|
|
66
127
|
const doFetch = options.fetch ?? globalThis.fetch;
|
|
@@ -69,7 +130,7 @@ async function postGraphql(url, query, variables, options) {
|
|
|
69
130
|
"cmssy: no fetch implementation available - pass options.fetch"
|
|
70
131
|
);
|
|
71
132
|
}
|
|
72
|
-
const response = await fetchWithRetry(
|
|
133
|
+
const { response, waitedMs } = await fetchWithRetry(
|
|
73
134
|
doFetch,
|
|
74
135
|
url,
|
|
75
136
|
{
|
|
@@ -78,7 +139,8 @@ async function postGraphql(url, query, variables, options) {
|
|
|
78
139
|
body: JSON.stringify({ query, variables }),
|
|
79
140
|
signal: options.signal
|
|
80
141
|
},
|
|
81
|
-
options.retry
|
|
142
|
+
options.retry,
|
|
143
|
+
options.label
|
|
82
144
|
);
|
|
83
145
|
if (!response.ok) {
|
|
84
146
|
let detail = "";
|
|
@@ -92,10 +154,12 @@ async function postGraphql(url, query, variables, options) {
|
|
|
92
154
|
}
|
|
93
155
|
const asked = retryAfterMs(response);
|
|
94
156
|
const wait = asked !== null ? ` - retry after ${Math.ceil(asked / 1e3)}s` : "";
|
|
157
|
+
const spent = waitedMs > 0 ? ` - gave up after waiting ${waitedMs}ms` : "";
|
|
95
158
|
throw new CmssyRequestError(
|
|
96
|
-
`cmssy: ${options.label} failed (${response.status})${detail}${wait}`,
|
|
159
|
+
`cmssy: ${options.label} failed (${response.status})${detail}${wait}${spent}`,
|
|
97
160
|
response.status,
|
|
98
|
-
asked ?? void 0
|
|
161
|
+
asked ?? void 0,
|
|
162
|
+
waitedMs > 0 ? waitedMs : void 0
|
|
99
163
|
);
|
|
100
164
|
}
|
|
101
165
|
let json;
|
|
@@ -184,7 +248,7 @@ async function loadSiteLocales(config, options) {
|
|
|
184
248
|
config,
|
|
185
249
|
SITE_CONFIG_QUERY,
|
|
186
250
|
{ workspaceSlug: config.workspaceSlug },
|
|
187
|
-
{ ...options, public: true, retry: options?.retry ??
|
|
251
|
+
{ ...options, public: true, retry: options?.retry ?? "build" },
|
|
188
252
|
"site config"
|
|
189
253
|
);
|
|
190
254
|
value = localesFromSiteConfig(data.public?.siteConfig ?? null);
|