@cmssy/core 10.3.0 → 10.5.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.
@@ -3,15 +3,28 @@ import { CmssyClientConfig, CmssyLayoutGroup, CmssyPageData, CmssyPageMeta, Cmss
3
3
  /** HTTP-level failure from the cmssy API, with a machine-readable status. */
4
4
  declare class CmssyRequestError extends Error {
5
5
  readonly status: number;
6
- constructor(message: string, status: number);
6
+ /**
7
+ * How long the server asked us to wait, in ms, when it said so. Present on a
8
+ * 429 that carried `Retry-After`; a caller can serve stale content for that
9
+ * long instead of guessing.
10
+ */
11
+ readonly retryAfterMs?: number;
12
+ constructor(message: string, status: number, retryAfterMs?: number);
7
13
  }
8
14
  interface RetryPolicy {
9
15
  /** Additional attempts after the first request (default 3). */
10
16
  maxRetries?: number;
11
17
  /** Exponential backoff base in ms: base * 2^attempt (default 300). */
12
18
  baseDelayMs?: number;
13
- /** Upper bound for any single wait, including Retry-After (default 3000). */
19
+ /** Upper bound for a guessed backoff wait (default 3000). */
14
20
  maxDelayMs?: number;
21
+ /**
22
+ * Upper bound for a wait the server asked for by `Retry-After` (default
23
+ * 10000). Beyond it there is nothing to gain from holding a render open, so
24
+ * the request fails immediately and carries `retryAfterMs` - the caller is in
25
+ * a better position to decide between stale content and an error page.
26
+ */
27
+ maxRetryAfterMs?: number;
15
28
  /** HTTP statuses that trigger a retry (default [429, 503]). */
16
29
  retryStatuses?: number[];
17
30
  }
@@ -3,15 +3,28 @@ import { CmssyClientConfig, CmssyLayoutGroup, CmssyPageData, CmssyPageMeta, Cmss
3
3
  /** HTTP-level failure from the cmssy API, with a machine-readable status. */
4
4
  declare class CmssyRequestError extends Error {
5
5
  readonly status: number;
6
- constructor(message: string, status: number);
6
+ /**
7
+ * How long the server asked us to wait, in ms, when it said so. Present on a
8
+ * 429 that carried `Retry-After`; a caller can serve stale content for that
9
+ * long instead of guessing.
10
+ */
11
+ readonly retryAfterMs?: number;
12
+ constructor(message: string, status: number, retryAfterMs?: number);
7
13
  }
8
14
  interface RetryPolicy {
9
15
  /** Additional attempts after the first request (default 3). */
10
16
  maxRetries?: number;
11
17
  /** Exponential backoff base in ms: base * 2^attempt (default 300). */
12
18
  baseDelayMs?: number;
13
- /** Upper bound for any single wait, including Retry-After (default 3000). */
19
+ /** Upper bound for a guessed backoff wait (default 3000). */
14
20
  maxDelayMs?: number;
21
+ /**
22
+ * Upper bound for a wait the server asked for by `Retry-After` (default
23
+ * 10000). Beyond it there is nothing to gain from holding a render open, so
24
+ * the request fails immediately and carries `retryAfterMs` - the caller is in
25
+ * a better position to decide between stale content and an error page.
26
+ */
27
+ maxRetryAfterMs?: number;
15
28
  /** HTTP statuses that trigger a retry (default [429, 503]). */
16
29
  retryStatuses?: number[];
17
30
  }
@@ -1,5 +1,5 @@
1
1
  import { CmssyClientConfig, BlockRect, BlockSchema, BlockMeta } from '@cmssy/types';
2
- import { G as GraphqlRequestOptions } from './locale-rhYcXU5z.cjs';
2
+ import { G as GraphqlRequestOptions } from './locale-C7sA46qu.cjs';
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-XintNd0n.js';
2
+ import { G as GraphqlRequestOptions } from './locale-Ox_qVlNy.js';
3
3
 
4
4
  declare const DEFAULT_CMSSY_EDITOR_ORIGINS: string[];
5
5
  declare function isDevelopment(): boolean;
package/dist/index.cjs CHANGED
@@ -64,10 +64,17 @@ Set the listed environment variables (e.g. in .env.local) and restart the dev se
64
64
  // src/data/http.ts
65
65
  var CmssyRequestError = class extends Error {
66
66
  status;
67
- constructor(message, status) {
67
+ /**
68
+ * How long the server asked us to wait, in ms, when it said so. Present on a
69
+ * 429 that carried `Retry-After`; a caller can serve stale content for that
70
+ * long instead of guessing.
71
+ */
72
+ retryAfterMs;
73
+ constructor(message, status, retryAfterMs2) {
68
74
  super(message);
69
75
  this.name = "CmssyRequestError";
70
76
  this.status = status;
77
+ if (retryAfterMs2 !== void 0) this.retryAfterMs = retryAfterMs2;
71
78
  }
72
79
  };
73
80
  var DEFAULT_RETRY_STATUSES = [429, 503];
@@ -104,14 +111,17 @@ async function fetchWithRetry(doFetch, url, init, retry) {
104
111
  const maxRetries = retry.maxRetries ?? 3;
105
112
  const baseDelayMs = retry.baseDelayMs ?? 300;
106
113
  const maxDelayMs = retry.maxDelayMs ?? 3e3;
114
+ const maxRetryAfterMs = retry.maxRetryAfterMs ?? 1e4;
107
115
  const retryStatuses = retry.retryStatuses ?? DEFAULT_RETRY_STATUSES;
108
116
  let response = await doFetch(url, init);
109
117
  for (let attempt = 0; attempt < maxRetries; attempt++) {
110
118
  if (response.ok || !retryStatuses.includes(response.status)) {
111
119
  return response;
112
120
  }
121
+ const asked = retryAfterMs(response);
122
+ if (asked !== null && asked > maxRetryAfterMs) return response;
113
123
  const backoff = baseDelayMs * 2 ** attempt;
114
- const wait = Math.min(retryAfterMs(response) ?? backoff, maxDelayMs);
124
+ const wait = asked !== null ? asked : Math.min(backoff, maxDelayMs);
115
125
  await sleep(wait, init.signal);
116
126
  response = await doFetch(url, init);
117
127
  }
@@ -145,9 +155,12 @@ async function postGraphql(url, query, variables, options) {
145
155
  } catch {
146
156
  detail = "";
147
157
  }
158
+ const asked = retryAfterMs(response);
159
+ const wait = asked !== null ? ` - retry after ${Math.ceil(asked / 1e3)}s` : "";
148
160
  throw new CmssyRequestError(
149
- `cmssy: ${options.label} failed (${response.status})${detail}`,
150
- response.status
161
+ `cmssy: ${options.label} failed (${response.status})${detail}${wait}`,
162
+ response.status,
163
+ asked ?? void 0
151
164
  );
152
165
  }
153
166
  let json;
@@ -204,6 +217,7 @@ var SITE_CONFIG_QUERY = `query PublicSiteConfig($workspaceSlug: String!) {
204
217
  branding {
205
218
  brandName
206
219
  logoUrl
220
+ logoDarkUrl
207
221
  faviconUrl
208
222
  ogImageUrl
209
223
  }
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, D as DEFAULT_CMSSY_EDITOR_ORIGINS, E as EditorToAppMessage, P as PROTOCOL_VERSION, e as ParentReadyMessage, f as PatchMessage, g as PostTarget, Q as QueryScopedOptions, R as ReadyMessage, S as SelectMessage, h as applyCmssyCsp, i as createCmssyClient, j as defineCmssyConfig, k as isProtocolCompatible, n as normalizeOrigin, p as parseEditorMessage, l as postToEditor, r as resolveEditorOrigin } from './csp-DlAEXYjA.cjs';
2
- export { C as CMSSY_LOCALE_HEADER, G as GraphqlRequestOptions, g as graphqlRequest, l as localizeHref } from './locale-rhYcXU5z.cjs';
3
- export { C as CmssyRequestError, D as DEFAULT_CMSSY_API_URL, F as FetchLike, a as FetchLikeResponse, b as FetchPageOptions, R as RetryPolicy } from './content-client-D0EdiqbQ.cjs';
1
+ export { A as AppToEditorMessage, B as BoundsMessage, C as ClickMessage, a as CmssyClient, b as CmssyConfig, c as CmssyCspOptions, d as CmssyEnvConfig, D as DEFAULT_CMSSY_EDITOR_ORIGINS, E as EditorToAppMessage, P as PROTOCOL_VERSION, e as ParentReadyMessage, f as PatchMessage, g as PostTarget, Q as QueryScopedOptions, R as ReadyMessage, S as SelectMessage, h as applyCmssyCsp, i as createCmssyClient, j as defineCmssyConfig, k as isProtocolCompatible, n as normalizeOrigin, p as parseEditorMessage, l as postToEditor, r as resolveEditorOrigin } from './csp-BityT_ug.cjs';
2
+ export { C as CMSSY_LOCALE_HEADER, G as GraphqlRequestOptions, g as graphqlRequest, l as localizeHref } from './locale-C7sA46qu.cjs';
3
+ export { C as CmssyRequestError, D as DEFAULT_CMSSY_API_URL, F as FetchLike, a as FetchLikeResponse, b as FetchPageOptions, R as RetryPolicy } from './content-client-CJQ-nafm.cjs';
4
4
  import * as _cmssy_types from '@cmssy/types';
5
5
  import { FieldOptions, TypedField, BlockPropsSchema, InferBlockContent, RelationMode, CmssyModelRecord, 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, RawBlock, RawLayoutBlock, SubmitFormInput, TypedField, VerifyCmssyWebhookOptions, evaluateFieldConditionGroup } 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, D as DEFAULT_CMSSY_EDITOR_ORIGINS, E as EditorToAppMessage, P as PROTOCOL_VERSION, e as ParentReadyMessage, f as PatchMessage, g as PostTarget, Q as QueryScopedOptions, R as ReadyMessage, S as SelectMessage, h as applyCmssyCsp, i as createCmssyClient, j as defineCmssyConfig, k as isProtocolCompatible, n as normalizeOrigin, p as parseEditorMessage, l as postToEditor, r as resolveEditorOrigin } from './csp-Blh6P15m.js';
2
- export { C as CMSSY_LOCALE_HEADER, G as GraphqlRequestOptions, g as graphqlRequest, l as localizeHref } from './locale-XintNd0n.js';
3
- export { C as CmssyRequestError, D as DEFAULT_CMSSY_API_URL, F as FetchLike, a as FetchLikeResponse, b as FetchPageOptions, R as RetryPolicy } from './content-client-D0EdiqbQ.js';
1
+ export { A as AppToEditorMessage, B as BoundsMessage, C as ClickMessage, a as CmssyClient, b as CmssyConfig, c as CmssyCspOptions, d as CmssyEnvConfig, D as DEFAULT_CMSSY_EDITOR_ORIGINS, E as EditorToAppMessage, P as PROTOCOL_VERSION, e as ParentReadyMessage, f as PatchMessage, g as PostTarget, Q as QueryScopedOptions, R as ReadyMessage, S as SelectMessage, h as applyCmssyCsp, i as createCmssyClient, j as defineCmssyConfig, k as isProtocolCompatible, n as normalizeOrigin, p as parseEditorMessage, l as postToEditor, r as resolveEditorOrigin } from './csp-DJ17P3PN.js';
2
+ export { C as CMSSY_LOCALE_HEADER, G as GraphqlRequestOptions, g as graphqlRequest, l as localizeHref } from './locale-Ox_qVlNy.js';
3
+ export { C as CmssyRequestError, D as DEFAULT_CMSSY_API_URL, F as FetchLike, a as FetchLikeResponse, b as FetchPageOptions, R as RetryPolicy } from './content-client-CJQ-nafm.js';
4
4
  import * as _cmssy_types from '@cmssy/types';
5
5
  import { FieldOptions, TypedField, BlockPropsSchema, InferBlockContent, RelationMode, CmssyModelRecord, 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, RawBlock, RawLayoutBlock, SubmitFormInput, TypedField, VerifyCmssyWebhookOptions, evaluateFieldConditionGroup } from '@cmssy/types';
package/dist/index.js CHANGED
@@ -62,10 +62,17 @@ Set the listed environment variables (e.g. in .env.local) and restart the dev se
62
62
  // src/data/http.ts
63
63
  var CmssyRequestError = class extends Error {
64
64
  status;
65
- constructor(message, status) {
65
+ /**
66
+ * How long the server asked us to wait, in ms, when it said so. Present on a
67
+ * 429 that carried `Retry-After`; a caller can serve stale content for that
68
+ * long instead of guessing.
69
+ */
70
+ retryAfterMs;
71
+ constructor(message, status, retryAfterMs2) {
66
72
  super(message);
67
73
  this.name = "CmssyRequestError";
68
74
  this.status = status;
75
+ if (retryAfterMs2 !== void 0) this.retryAfterMs = retryAfterMs2;
69
76
  }
70
77
  };
71
78
  var DEFAULT_RETRY_STATUSES = [429, 503];
@@ -102,14 +109,17 @@ async function fetchWithRetry(doFetch, url, init, retry) {
102
109
  const maxRetries = retry.maxRetries ?? 3;
103
110
  const baseDelayMs = retry.baseDelayMs ?? 300;
104
111
  const maxDelayMs = retry.maxDelayMs ?? 3e3;
112
+ const maxRetryAfterMs = retry.maxRetryAfterMs ?? 1e4;
105
113
  const retryStatuses = retry.retryStatuses ?? DEFAULT_RETRY_STATUSES;
106
114
  let response = await doFetch(url, init);
107
115
  for (let attempt = 0; attempt < maxRetries; attempt++) {
108
116
  if (response.ok || !retryStatuses.includes(response.status)) {
109
117
  return response;
110
118
  }
119
+ const asked = retryAfterMs(response);
120
+ if (asked !== null && asked > maxRetryAfterMs) return response;
111
121
  const backoff = baseDelayMs * 2 ** attempt;
112
- const wait = Math.min(retryAfterMs(response) ?? backoff, maxDelayMs);
122
+ const wait = asked !== null ? asked : Math.min(backoff, maxDelayMs);
113
123
  await sleep(wait, init.signal);
114
124
  response = await doFetch(url, init);
115
125
  }
@@ -143,9 +153,12 @@ async function postGraphql(url, query, variables, options) {
143
153
  } catch {
144
154
  detail = "";
145
155
  }
156
+ const asked = retryAfterMs(response);
157
+ const wait = asked !== null ? ` - retry after ${Math.ceil(asked / 1e3)}s` : "";
146
158
  throw new CmssyRequestError(
147
- `cmssy: ${options.label} failed (${response.status})${detail}`,
148
- response.status
159
+ `cmssy: ${options.label} failed (${response.status})${detail}${wait}`,
160
+ response.status,
161
+ asked ?? void 0
149
162
  );
150
163
  }
151
164
  let json;
@@ -202,6 +215,7 @@ var SITE_CONFIG_QUERY = `query PublicSiteConfig($workspaceSlug: String!) {
202
215
  branding {
203
216
  brandName
204
217
  logoUrl
218
+ logoDarkUrl
205
219
  faviconUrl
206
220
  ogImageUrl
207
221
  }
@@ -3,10 +3,17 @@
3
3
  // src/data/http.ts
4
4
  var CmssyRequestError = class extends Error {
5
5
  status;
6
- constructor(message, status) {
6
+ /**
7
+ * How long the server asked us to wait, in ms, when it said so. Present on a
8
+ * 429 that carried `Retry-After`; a caller can serve stale content for that
9
+ * long instead of guessing.
10
+ */
11
+ retryAfterMs;
12
+ constructor(message, status, retryAfterMs2) {
7
13
  super(message);
8
14
  this.name = "CmssyRequestError";
9
15
  this.status = status;
16
+ if (retryAfterMs2 !== void 0) this.retryAfterMs = retryAfterMs2;
10
17
  }
11
18
  };
12
19
  var DEFAULT_RETRY_STATUSES = [429, 503];
@@ -43,14 +50,17 @@ async function fetchWithRetry(doFetch, url, init, retry) {
43
50
  const maxRetries = retry.maxRetries ?? 3;
44
51
  const baseDelayMs = retry.baseDelayMs ?? 300;
45
52
  const maxDelayMs = retry.maxDelayMs ?? 3e3;
53
+ const maxRetryAfterMs = retry.maxRetryAfterMs ?? 1e4;
46
54
  const retryStatuses = retry.retryStatuses ?? DEFAULT_RETRY_STATUSES;
47
55
  let response = await doFetch(url, init);
48
56
  for (let attempt = 0; attempt < maxRetries; attempt++) {
49
57
  if (response.ok || !retryStatuses.includes(response.status)) {
50
58
  return response;
51
59
  }
60
+ const asked = retryAfterMs(response);
61
+ if (asked !== null && asked > maxRetryAfterMs) return response;
52
62
  const backoff = baseDelayMs * 2 ** attempt;
53
- const wait = Math.min(retryAfterMs(response) ?? backoff, maxDelayMs);
63
+ const wait = asked !== null ? asked : Math.min(backoff, maxDelayMs);
54
64
  await sleep(wait, init.signal);
55
65
  response = await doFetch(url, init);
56
66
  }
@@ -84,9 +94,12 @@ async function postGraphql(url, query, variables, options) {
84
94
  } catch {
85
95
  detail = "";
86
96
  }
97
+ const asked = retryAfterMs(response);
98
+ const wait = asked !== null ? ` - retry after ${Math.ceil(asked / 1e3)}s` : "";
87
99
  throw new CmssyRequestError(
88
- `cmssy: ${options.label} failed (${response.status})${detail}`,
89
- response.status
100
+ `cmssy: ${options.label} failed (${response.status})${detail}${wait}`,
101
+ response.status,
102
+ asked ?? void 0
90
103
  );
91
104
  }
92
105
  let json;
@@ -143,6 +156,7 @@ var SITE_CONFIG_QUERY = `query PublicSiteConfig($workspaceSlug: String!) {
143
156
  branding {
144
157
  brandName
145
158
  logoUrl
159
+ logoDarkUrl
146
160
  faviconUrl
147
161
  ogImageUrl
148
162
  }
@@ -1,8 +1,8 @@
1
- import { G as GraphqlRequestOptions } from '../locale-rhYcXU5z.cjs';
2
- export { C as CMSSY_LOCALE_HEADER, b as buildLocaleSwitchHref, a as localeForPath, c as localeForPathname, l as localizeHref, d as localizeHtmlLinks, s as splitCmssyLocale } from '../locale-rhYcXU5z.cjs';
1
+ import { G as GraphqlRequestOptions } from '../locale-C7sA46qu.cjs';
2
+ export { C as CMSSY_LOCALE_HEADER, b as buildLocaleSwitchHref, a as localeForPath, c as localeForPathname, l as localizeHref, d as localizeHtmlLinks, s as splitCmssyLocale } from '../locale-C7sA46qu.cjs';
3
3
  import { CmssySiteLocales, CmssyClientConfig } from '@cmssy/types';
4
4
  export { CmssySiteLocales } from '@cmssy/types';
5
- import '../content-client-D0EdiqbQ.cjs';
5
+ import '../content-client-CJQ-nafm.cjs';
6
6
 
7
7
  /**
8
8
  * Maps a workspace site config to its locale set. The single place that
@@ -1,8 +1,8 @@
1
- import { G as GraphqlRequestOptions } from '../locale-XintNd0n.js';
2
- export { C as CMSSY_LOCALE_HEADER, b as buildLocaleSwitchHref, a as localeForPath, c as localeForPathname, l as localizeHref, d as localizeHtmlLinks, s as splitCmssyLocale } from '../locale-XintNd0n.js';
1
+ import { G as GraphqlRequestOptions } from '../locale-Ox_qVlNy.js';
2
+ export { C as CMSSY_LOCALE_HEADER, b as buildLocaleSwitchHref, a as localeForPath, c as localeForPathname, l as localizeHref, d as localizeHtmlLinks, s as splitCmssyLocale } from '../locale-Ox_qVlNy.js';
3
3
  import { CmssySiteLocales, CmssyClientConfig } from '@cmssy/types';
4
4
  export { CmssySiteLocales } from '@cmssy/types';
5
- import '../content-client-D0EdiqbQ.js';
5
+ import '../content-client-CJQ-nafm.js';
6
6
 
7
7
  /**
8
8
  * Maps a workspace site config to its locale set. The single place that
@@ -1,10 +1,17 @@
1
1
  // src/data/http.ts
2
2
  var CmssyRequestError = class extends Error {
3
3
  status;
4
- constructor(message, status) {
4
+ /**
5
+ * How long the server asked us to wait, in ms, when it said so. Present on a
6
+ * 429 that carried `Retry-After`; a caller can serve stale content for that
7
+ * long instead of guessing.
8
+ */
9
+ retryAfterMs;
10
+ constructor(message, status, retryAfterMs2) {
5
11
  super(message);
6
12
  this.name = "CmssyRequestError";
7
13
  this.status = status;
14
+ if (retryAfterMs2 !== void 0) this.retryAfterMs = retryAfterMs2;
8
15
  }
9
16
  };
10
17
  var DEFAULT_RETRY_STATUSES = [429, 503];
@@ -41,14 +48,17 @@ async function fetchWithRetry(doFetch, url, init, retry) {
41
48
  const maxRetries = retry.maxRetries ?? 3;
42
49
  const baseDelayMs = retry.baseDelayMs ?? 300;
43
50
  const maxDelayMs = retry.maxDelayMs ?? 3e3;
51
+ const maxRetryAfterMs = retry.maxRetryAfterMs ?? 1e4;
44
52
  const retryStatuses = retry.retryStatuses ?? DEFAULT_RETRY_STATUSES;
45
53
  let response = await doFetch(url, init);
46
54
  for (let attempt = 0; attempt < maxRetries; attempt++) {
47
55
  if (response.ok || !retryStatuses.includes(response.status)) {
48
56
  return response;
49
57
  }
58
+ const asked = retryAfterMs(response);
59
+ if (asked !== null && asked > maxRetryAfterMs) return response;
50
60
  const backoff = baseDelayMs * 2 ** attempt;
51
- const wait = Math.min(retryAfterMs(response) ?? backoff, maxDelayMs);
61
+ const wait = asked !== null ? asked : Math.min(backoff, maxDelayMs);
52
62
  await sleep(wait, init.signal);
53
63
  response = await doFetch(url, init);
54
64
  }
@@ -82,9 +92,12 @@ async function postGraphql(url, query, variables, options) {
82
92
  } catch {
83
93
  detail = "";
84
94
  }
95
+ const asked = retryAfterMs(response);
96
+ const wait = asked !== null ? ` - retry after ${Math.ceil(asked / 1e3)}s` : "";
85
97
  throw new CmssyRequestError(
86
- `cmssy: ${options.label} failed (${response.status})${detail}`,
87
- response.status
98
+ `cmssy: ${options.label} failed (${response.status})${detail}${wait}`,
99
+ response.status,
100
+ asked ?? void 0
88
101
  );
89
102
  }
90
103
  let json;
@@ -141,6 +154,7 @@ var SITE_CONFIG_QUERY = `query PublicSiteConfig($workspaceSlug: String!) {
141
154
  branding {
142
155
  brandName
143
156
  logoUrl
157
+ logoDarkUrl
144
158
  faviconUrl
145
159
  ogImageUrl
146
160
  }
package/dist/internal.cjs CHANGED
@@ -3,10 +3,17 @@
3
3
  // src/data/http.ts
4
4
  var CmssyRequestError = class extends Error {
5
5
  status;
6
- constructor(message, status) {
6
+ /**
7
+ * How long the server asked us to wait, in ms, when it said so. Present on a
8
+ * 429 that carried `Retry-After`; a caller can serve stale content for that
9
+ * long instead of guessing.
10
+ */
11
+ retryAfterMs;
12
+ constructor(message, status, retryAfterMs2) {
7
13
  super(message);
8
14
  this.name = "CmssyRequestError";
9
15
  this.status = status;
16
+ if (retryAfterMs2 !== void 0) this.retryAfterMs = retryAfterMs2;
10
17
  }
11
18
  };
12
19
  var DEFAULT_RETRY_STATUSES = [429, 503];
@@ -43,14 +50,17 @@ async function fetchWithRetry(doFetch, url, init, retry) {
43
50
  const maxRetries = retry.maxRetries ?? 3;
44
51
  const baseDelayMs = retry.baseDelayMs ?? 300;
45
52
  const maxDelayMs = retry.maxDelayMs ?? 3e3;
53
+ const maxRetryAfterMs = retry.maxRetryAfterMs ?? 1e4;
46
54
  const retryStatuses = retry.retryStatuses ?? DEFAULT_RETRY_STATUSES;
47
55
  let response = await doFetch(url, init);
48
56
  for (let attempt = 0; attempt < maxRetries; attempt++) {
49
57
  if (response.ok || !retryStatuses.includes(response.status)) {
50
58
  return response;
51
59
  }
60
+ const asked = retryAfterMs(response);
61
+ if (asked !== null && asked > maxRetryAfterMs) return response;
52
62
  const backoff = baseDelayMs * 2 ** attempt;
53
- const wait = Math.min(retryAfterMs(response) ?? backoff, maxDelayMs);
63
+ const wait = asked !== null ? asked : Math.min(backoff, maxDelayMs);
54
64
  await sleep(wait, init.signal);
55
65
  response = await doFetch(url, init);
56
66
  }
@@ -84,9 +94,12 @@ async function postGraphql(url, query, variables, options) {
84
94
  } catch {
85
95
  detail = "";
86
96
  }
97
+ const asked = retryAfterMs(response);
98
+ const wait = asked !== null ? ` - retry after ${Math.ceil(asked / 1e3)}s` : "";
87
99
  throw new CmssyRequestError(
88
- `cmssy: ${options.label} failed (${response.status})${detail}`,
89
- response.status
100
+ `cmssy: ${options.label} failed (${response.status})${detail}${wait}`,
101
+ response.status,
102
+ asked ?? void 0
90
103
  );
91
104
  }
92
105
  let json;
@@ -360,6 +373,7 @@ var SITE_CONFIG_QUERY = `query PublicSiteConfig($workspaceSlug: String!) {
360
373
  branding {
361
374
  brandName
362
375
  logoUrl
376
+ logoDarkUrl
363
377
  faviconUrl
364
378
  ogImageUrl
365
379
  }
@@ -1,13 +1,13 @@
1
- export { f as fetchLayouts, c as fetchPage, d as fetchPageById, e as fetchPageMeta, g as fetchPages, n as normalizeSlug, r as resolveApiUrl, h as resolvePublicUrl } from './content-client-D0EdiqbQ.cjs';
1
+ export { f as fetchLayouts, c as fetchPage, d as fetchPageById, e as fetchPageMeta, g as fetchPages, n as normalizeSlug, r as resolveApiUrl, h as resolvePublicUrl } from './content-client-CJQ-nafm.cjs';
2
2
  import { CmssyFormDefinition, BuildBlockContextExtra, CmssyBlockContext, CmssyClientConfig, CmssySiteConfig, RawBlock, FieldDefinition } from '@cmssy/types';
3
3
  export { CmssySiteLocales } from '@cmssy/types';
4
- import { G as GraphqlRequestOptions } from './locale-rhYcXU5z.cjs';
5
- export { C as CMSSY_LOCALE_HEADER, b as buildLocaleSwitchHref, a as localeForPath, c as localeForPathname, l as localizeHref, d as localizeHtmlLinks, s as splitCmssyLocale } from './locale-rhYcXU5z.cjs';
6
- import { Q as QueryScopedOptions } from './csp-DlAEXYjA.cjs';
7
- export { m as cmssyCspHeaders, o as isDevelopment, q as resolveInitialTarget, t as toCspOrigin } from './csp-DlAEXYjA.cjs';
4
+ import { G as GraphqlRequestOptions } from './locale-C7sA46qu.cjs';
5
+ export { C as CMSSY_LOCALE_HEADER, b as buildLocaleSwitchHref, a as localeForPath, c as localeForPathname, l as localizeHref, d as localizeHtmlLinks, s as splitCmssyLocale } from './locale-C7sA46qu.cjs';
6
+ import { Q as QueryScopedOptions } from './csp-BityT_ug.cjs';
7
+ export { m as cmssyCspHeaders, o as isDevelopment, q as resolveInitialTarget, t as toCspOrigin } from './csp-BityT_ug.cjs';
8
8
  export { localesFromSiteConfig, localizedPath, resolveSiteLocales, splitLocaleFromPath } from './internal/locale.cjs';
9
9
 
10
- declare const SITE_CONFIG_QUERY = "query PublicSiteConfig($workspaceSlug: String!) {\n public {\n siteConfig(workspaceSlug: $workspaceSlug) {\n id\n workspaceId\n siteName\n defaultLanguage\n enabledLanguages\n enabledFeatures\n notFoundPageId\n previewUrl\n branding {\n brandName\n logoUrl\n faviconUrl\n ogImageUrl\n }\n }\n }\n}";
10
+ declare const SITE_CONFIG_QUERY = "query PublicSiteConfig($workspaceSlug: String!) {\n public {\n siteConfig(workspaceSlug: $workspaceSlug) {\n id\n workspaceId\n siteName\n defaultLanguage\n enabledLanguages\n enabledFeatures\n notFoundPageId\n previewUrl\n branding {\n brandName\n logoUrl\n logoDarkUrl\n faviconUrl\n ogImageUrl\n }\n }\n }\n}";
11
11
  declare const MODEL_DEFINITIONS_QUERY = "query PublicModelDefinitions($workspaceId: String!) {\n public {\n model {\n definitions(workspaceId: $workspaceId) {\n id name slug description icon color displayField recordCount\n }\n }\n }\n}";
12
12
  declare const MODEL_RECORDS_QUERY = "query PublicModelRecords($workspaceId: String!, $modelSlug: String!, $filter: JSON, $sort: String, $locale: String, $limit: Int, $offset: Int, $populate: [String!]) {\n public {\n model {\n records(workspaceId: $workspaceId, modelSlug: $modelSlug, filter: $filter, sort: $sort, locale: $locale, limit: $limit, offset: $offset, populate: $populate) {\n items { id modelId data status createdAt updatedAt }\n total\n hasMore\n }\n }\n }\n}";
13
13
  declare const FORM_QUERY = "query PublicForm($formId: ID!) {\n public {\n form {\n get(formId: $formId) {\n id\n name\n slug\n description\n fields {\n id name fieldType label placeholder helpText\n defaultValue width order showWhen requiredWhen\n options { value label disabled }\n validation { required minLength maxLength minValue maxValue pattern customMessage }\n }\n settings {\n actionType submitButtonLabel successMessage errorMessage\n redirectUrl requireLogin enableCaptcha\n }\n }\n }\n }\n}";
@@ -1,13 +1,13 @@
1
- export { f as fetchLayouts, c as fetchPage, d as fetchPageById, e as fetchPageMeta, g as fetchPages, n as normalizeSlug, r as resolveApiUrl, h as resolvePublicUrl } from './content-client-D0EdiqbQ.js';
1
+ export { f as fetchLayouts, c as fetchPage, d as fetchPageById, e as fetchPageMeta, g as fetchPages, n as normalizeSlug, r as resolveApiUrl, h as resolvePublicUrl } from './content-client-CJQ-nafm.js';
2
2
  import { CmssyFormDefinition, BuildBlockContextExtra, CmssyBlockContext, CmssyClientConfig, CmssySiteConfig, RawBlock, FieldDefinition } from '@cmssy/types';
3
3
  export { CmssySiteLocales } from '@cmssy/types';
4
- import { G as GraphqlRequestOptions } from './locale-XintNd0n.js';
5
- export { C as CMSSY_LOCALE_HEADER, b as buildLocaleSwitchHref, a as localeForPath, c as localeForPathname, l as localizeHref, d as localizeHtmlLinks, s as splitCmssyLocale } from './locale-XintNd0n.js';
6
- import { Q as QueryScopedOptions } from './csp-Blh6P15m.js';
7
- export { m as cmssyCspHeaders, o as isDevelopment, q as resolveInitialTarget, t as toCspOrigin } from './csp-Blh6P15m.js';
4
+ import { G as GraphqlRequestOptions } from './locale-Ox_qVlNy.js';
5
+ export { C as CMSSY_LOCALE_HEADER, b as buildLocaleSwitchHref, a as localeForPath, c as localeForPathname, l as localizeHref, d as localizeHtmlLinks, s as splitCmssyLocale } from './locale-Ox_qVlNy.js';
6
+ import { Q as QueryScopedOptions } from './csp-DJ17P3PN.js';
7
+ export { m as cmssyCspHeaders, o as isDevelopment, q as resolveInitialTarget, t as toCspOrigin } from './csp-DJ17P3PN.js';
8
8
  export { localesFromSiteConfig, localizedPath, resolveSiteLocales, splitLocaleFromPath } from './internal/locale.js';
9
9
 
10
- declare const SITE_CONFIG_QUERY = "query PublicSiteConfig($workspaceSlug: String!) {\n public {\n siteConfig(workspaceSlug: $workspaceSlug) {\n id\n workspaceId\n siteName\n defaultLanguage\n enabledLanguages\n enabledFeatures\n notFoundPageId\n previewUrl\n branding {\n brandName\n logoUrl\n faviconUrl\n ogImageUrl\n }\n }\n }\n}";
10
+ declare const SITE_CONFIG_QUERY = "query PublicSiteConfig($workspaceSlug: String!) {\n public {\n siteConfig(workspaceSlug: $workspaceSlug) {\n id\n workspaceId\n siteName\n defaultLanguage\n enabledLanguages\n enabledFeatures\n notFoundPageId\n previewUrl\n branding {\n brandName\n logoUrl\n logoDarkUrl\n faviconUrl\n ogImageUrl\n }\n }\n }\n}";
11
11
  declare const MODEL_DEFINITIONS_QUERY = "query PublicModelDefinitions($workspaceId: String!) {\n public {\n model {\n definitions(workspaceId: $workspaceId) {\n id name slug description icon color displayField recordCount\n }\n }\n }\n}";
12
12
  declare const MODEL_RECORDS_QUERY = "query PublicModelRecords($workspaceId: String!, $modelSlug: String!, $filter: JSON, $sort: String, $locale: String, $limit: Int, $offset: Int, $populate: [String!]) {\n public {\n model {\n records(workspaceId: $workspaceId, modelSlug: $modelSlug, filter: $filter, sort: $sort, locale: $locale, limit: $limit, offset: $offset, populate: $populate) {\n items { id modelId data status createdAt updatedAt }\n total\n hasMore\n }\n }\n }\n}";
13
13
  declare const FORM_QUERY = "query PublicForm($formId: ID!) {\n public {\n form {\n get(formId: $formId) {\n id\n name\n slug\n description\n fields {\n id name fieldType label placeholder helpText\n defaultValue width order showWhen requiredWhen\n options { value label disabled }\n validation { required minLength maxLength minValue maxValue pattern customMessage }\n }\n settings {\n actionType submitButtonLabel successMessage errorMessage\n redirectUrl requireLogin enableCaptcha\n }\n }\n }\n }\n}";
package/dist/internal.js CHANGED
@@ -1,10 +1,17 @@
1
1
  // src/data/http.ts
2
2
  var CmssyRequestError = class extends Error {
3
3
  status;
4
- constructor(message, status) {
4
+ /**
5
+ * How long the server asked us to wait, in ms, when it said so. Present on a
6
+ * 429 that carried `Retry-After`; a caller can serve stale content for that
7
+ * long instead of guessing.
8
+ */
9
+ retryAfterMs;
10
+ constructor(message, status, retryAfterMs2) {
5
11
  super(message);
6
12
  this.name = "CmssyRequestError";
7
13
  this.status = status;
14
+ if (retryAfterMs2 !== void 0) this.retryAfterMs = retryAfterMs2;
8
15
  }
9
16
  };
10
17
  var DEFAULT_RETRY_STATUSES = [429, 503];
@@ -41,14 +48,17 @@ async function fetchWithRetry(doFetch, url, init, retry) {
41
48
  const maxRetries = retry.maxRetries ?? 3;
42
49
  const baseDelayMs = retry.baseDelayMs ?? 300;
43
50
  const maxDelayMs = retry.maxDelayMs ?? 3e3;
51
+ const maxRetryAfterMs = retry.maxRetryAfterMs ?? 1e4;
44
52
  const retryStatuses = retry.retryStatuses ?? DEFAULT_RETRY_STATUSES;
45
53
  let response = await doFetch(url, init);
46
54
  for (let attempt = 0; attempt < maxRetries; attempt++) {
47
55
  if (response.ok || !retryStatuses.includes(response.status)) {
48
56
  return response;
49
57
  }
58
+ const asked = retryAfterMs(response);
59
+ if (asked !== null && asked > maxRetryAfterMs) return response;
50
60
  const backoff = baseDelayMs * 2 ** attempt;
51
- const wait = Math.min(retryAfterMs(response) ?? backoff, maxDelayMs);
61
+ const wait = asked !== null ? asked : Math.min(backoff, maxDelayMs);
52
62
  await sleep(wait, init.signal);
53
63
  response = await doFetch(url, init);
54
64
  }
@@ -82,9 +92,12 @@ async function postGraphql(url, query, variables, options) {
82
92
  } catch {
83
93
  detail = "";
84
94
  }
95
+ const asked = retryAfterMs(response);
96
+ const wait = asked !== null ? ` - retry after ${Math.ceil(asked / 1e3)}s` : "";
85
97
  throw new CmssyRequestError(
86
- `cmssy: ${options.label} failed (${response.status})${detail}`,
87
- response.status
98
+ `cmssy: ${options.label} failed (${response.status})${detail}${wait}`,
99
+ response.status,
100
+ asked ?? void 0
88
101
  );
89
102
  }
90
103
  let json;
@@ -358,6 +371,7 @@ var SITE_CONFIG_QUERY = `query PublicSiteConfig($workspaceSlug: String!) {
358
371
  branding {
359
372
  brandName
360
373
  logoUrl
374
+ logoDarkUrl
361
375
  faviconUrl
362
376
  ogImageUrl
363
377
  }
@@ -1,4 +1,4 @@
1
- import { F as FetchLike, R as RetryPolicy } from './content-client-D0EdiqbQ.cjs';
1
+ import { F as FetchLike, R as RetryPolicy } from './content-client-CJQ-nafm.cjs';
2
2
  import { CmssyClientConfig, CmssyLocaleContext } from '@cmssy/types';
3
3
 
4
4
  interface GraphqlRequestOptions {
@@ -1,4 +1,4 @@
1
- import { F as FetchLike, R as RetryPolicy } from './content-client-D0EdiqbQ.js';
1
+ import { F as FetchLike, R as RetryPolicy } from './content-client-CJQ-nafm.js';
2
2
  import { CmssyClientConfig, CmssyLocaleContext } from '@cmssy/types';
3
3
 
4
4
  interface GraphqlRequestOptions {
@@ -1,4 +1,4 @@
1
- import { F as FetchLike } from './content-client-D0EdiqbQ.cjs';
1
+ import { F as FetchLike } from './content-client-CJQ-nafm.cjs';
2
2
  import { CmssyClientConfig } from '@cmssy/types';
3
3
 
4
4
  interface EditDiagnosticsConfig {
@@ -1,4 +1,4 @@
1
- import { F as FetchLike } from './content-client-D0EdiqbQ.js';
1
+ import { F as FetchLike } from './content-client-CJQ-nafm.js';
2
2
  import { CmssyClientConfig } from '@cmssy/types';
3
3
 
4
4
  interface EditDiagnosticsConfig {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmssy/core",
3
- "version": "10.3.0",
3
+ "version": "10.5.0",
4
4
  "description": "Framework-agnostic cmssy gateway: GraphQL client, block/field system, editor protocol. No React, no Next.",
5
5
  "keywords": [
6
6
  "cmssy",
@@ -62,7 +62,7 @@
62
62
  "vitest": "^2.1.0"
63
63
  },
64
64
  "dependencies": {
65
- "@cmssy/types": "0.31.0",
65
+ "@cmssy/types": "0.32.0",
66
66
  "jose": "^6.2.3"
67
67
  },
68
68
  "scripts": {