@bettercms-ai/sdk 1.7.0 → 1.8.1

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/index.cjs CHANGED
@@ -136,12 +136,20 @@ var BetterCMSError = class _BetterCMSError extends Error {
136
136
  * shares a status with others (e.g. 409 slug-conflict vs 409 project-deleted).
137
137
  */
138
138
  bodyCode;
139
- constructor(message, status, code, bodyCode) {
139
+ /**
140
+ * Per-field validation messages from a 400 `{ errors: { field: message } }` body.
141
+ * The backend returns validation failures in this shape (not `message`/`error`), so
142
+ * without this the SDK collapsed every validation 400 to a bare "Bad Request" with no
143
+ * hint which field or rule failed (FLO-474). Mirrors the forms client's `fieldErrors`.
144
+ */
145
+ fieldErrors;
146
+ constructor(message, status, code, bodyCode, fieldErrors) {
140
147
  super(message);
141
148
  this.name = "BetterCMSError";
142
149
  this.status = status;
143
150
  this.code = code;
144
151
  this.bodyCode = bodyCode;
152
+ this.fieldErrors = fieldErrors;
145
153
  if (Error.captureStackTrace) {
146
154
  Error.captureStackTrace(this, _BetterCMSError);
147
155
  }
@@ -152,25 +160,40 @@ var BetterCMSError = class _BetterCMSError extends Error {
152
160
  message: this.message,
153
161
  status: this.status,
154
162
  code: this.code,
155
- bodyCode: this.bodyCode
163
+ bodyCode: this.bodyCode,
164
+ fieldErrors: this.fieldErrors
156
165
  };
157
166
  }
158
167
  /**
159
- * Factory — creates a BetterCMSError from a failed fetch Response. Reads the
160
- * body's `message` (or `error`) for the human message and `code` for a
161
- * machine-readable condition the SDK surfaces as `bodyCode`.
168
+ * Factory — creates a BetterCMSError from a failed fetch Response. Reads the body's
169
+ * `message` (or `error`) for the human message and `code` for a machine-readable
170
+ * condition surfaced as `bodyCode`. Validation failures arrive as `{ errors: {...} }`
171
+ * (no `message`/`error`), so fall back to the first field error for the message and
172
+ * expose the full map as `fieldErrors` (FLO-474).
162
173
  */
163
174
  static async from(res) {
164
175
  let message = res.statusText || "An error occurred";
165
176
  let bodyCode;
177
+ let fieldErrors;
178
+ let code = statusToCode(res.status);
166
179
  try {
167
180
  const body = await res.json();
181
+ if (body?.errors && typeof body.errors === "object") {
182
+ fieldErrors = body.errors;
183
+ code = ErrorCodes.VALIDATION_ERROR;
184
+ }
168
185
  if (body?.message) message = body.message;
169
186
  else if (body?.error) message = body.error;
187
+ else if (fieldErrors) {
188
+ const [field, detail] = Object.entries(fieldErrors).find(
189
+ ([, v]) => typeof v === "string" && v.length > 0
190
+ ) ?? [];
191
+ if (field) message = `${field}: ${detail}`;
192
+ }
170
193
  if (body?.code) bodyCode = body.code;
171
194
  } catch {
172
195
  }
173
- return new _BetterCMSError(message, res.status, statusToCode(res.status), bodyCode);
196
+ return new _BetterCMSError(message, res.status, code, bodyCode, fieldErrors);
174
197
  }
175
198
  };
176
199
 
@@ -781,15 +804,18 @@ var RETRY_DELAYS2 = [1e3, 2e3, 4e3];
781
804
  var BetterCMSManagementClient = class extends BetterCMSDeliveryClient {
782
805
  timeout;
783
806
  _apiKey;
807
+ _project;
784
808
  constructor(options) {
785
809
  super({ workspace: "", baseUrl: options.baseUrl ?? DEFAULT_BASE_URL2 });
786
810
  this._apiKey = options.apiKey;
811
+ this._project = options.project;
787
812
  this.timeout = options.timeout ?? DEFAULT_TIMEOUT2;
788
813
  }
789
814
  headers() {
790
815
  return {
791
816
  "Content-Type": "application/json",
792
- "X-API-Key": this._apiKey
817
+ "X-API-Key": this._apiKey,
818
+ ...this._project ? { "X-BCMS-Project": this._project } : {}
793
819
  };
794
820
  }
795
821
  /** Management API URL: baseUrl + path (path is workspace-scoped via the key). */