@calmlens/sdk 0.13.0 → 0.15.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.
Files changed (30) hide show
  1. package/README.md +44 -40
  2. package/cjs/{CalmLensConnection-DzRDCMOP.js → CalmLensConnection-DoemramF.js} +4 -3
  3. package/cjs/{CalmLensUtils-vX5H_vMn.js → CalmLensUtils-Cv1Ylp9-.js} +10 -10
  4. package/cjs/{CalmLensVersion-DjhsJ1gj.js → CalmLensVersion-CuxKdijk.js} +67 -2
  5. package/cjs/{CalmLensWebhooks-hVquX5L1.js → CalmLensWebhooks-qrL-Zdu3.js} +2 -2
  6. package/cjs/{WebhookPayload-B7CgSmI5.d.ts → WebhookPayload-vy8HNMaK.d.ts} +4355 -449
  7. package/cjs/app.d.ts +3 -3
  8. package/cjs/app.js +3 -3
  9. package/cjs/{index-BywTQbRq.d.ts → index-Dz340UQ9.d.ts} +27 -1
  10. package/cjs/index.d.ts +3 -3
  11. package/cjs/index.js +1 -1
  12. package/cjs/server.d.ts +9 -8
  13. package/cjs/server.js +10 -9
  14. package/cjs/testing.d.ts +19 -45
  15. package/cjs/testing.js +99 -30
  16. package/esm/{CalmLensConnection-D8VsTdsA.js → CalmLensConnection-CQLoUoBd.js} +4 -3
  17. package/esm/{CalmLensUtils-B4i3Z2He.js → CalmLensUtils-B3S--hBG.js} +10 -10
  18. package/esm/{CalmLensVersion-DK4BMEST.js → CalmLensVersion-N71PMJAz.js} +67 -2
  19. package/esm/{CalmLensWebhooks-DyCoEvpf.js → CalmLensWebhooks-BxMSx1Vm.js} +2 -2
  20. package/esm/{WebhookPayload-B7CgSmI5.d.ts → WebhookPayload-vy8HNMaK.d.ts} +4355 -449
  21. package/esm/app.d.ts +3 -3
  22. package/esm/app.js +3 -3
  23. package/esm/{index-BywTQbRq.d.ts → index-Dz340UQ9.d.ts} +27 -1
  24. package/esm/index.d.ts +3 -3
  25. package/esm/index.js +1 -1
  26. package/esm/server.d.ts +9 -8
  27. package/esm/server.js +10 -9
  28. package/esm/testing.d.ts +19 -45
  29. package/esm/testing.js +99 -30
  30. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { c as invalidArgument, l as invalidConfig, n as getUserAgent, o as CalmLensError, r as isBrowserRuntime, s as SDK_ERROR_CODES, u as API_ERROR_CODES } from "./CalmLensVersion-DK4BMEST.js";
1
+ import { c as invalidArgument, l as invalidConfig, n as getUserAgent, o as CalmLensError, r as isBrowserRuntime, s as SDK_ERROR_CODES, u as API_ERROR_CODES } from "./CalmLensVersion-N71PMJAz.js";
2
2
  const MAX_IMAGE_UPLOAD_BYTES = /* @__PURE__ */ (() => 20971520)();
3
3
  const MIN_MULTIPART_IMAGE_UPLOAD_BYTES = /* @__PURE__ */ (() => 10485760)();
4
4
  const REJECTED_UPLOAD_MIME_TYPE_SET = /* @__PURE__ */ new Set([
@@ -537,12 +537,11 @@ const stringifyQuery = (query) => {
537
537
  for (const [key, value] of Object.entries(query)) appendQueryValue(parts, key, value);
538
538
  return parts.join("&");
539
539
  };
540
- /** Statuses that are a moderation decision; `assets.waitForDecision` returns at the first. */
541
- const DECIDED_ASSET_STATUSES = [
542
- "approved",
543
- "rejected",
544
- "error"
545
- ];
540
+ /**
541
+ * Whether an asset has a moderation decision (`moderation.status` `approved` or `rejected`) or
542
+ * failed processing; `assets.waitForDecision` returns at the first such state.
543
+ */
544
+ const isAssetDecided = (asset) => asset.moderation.status === "approved" || asset.moderation.status === "rejected" || asset.processing.status === "failed";
546
545
  const DECISION_POLL_FIRST_DELAY_MS = 500;
547
546
  const DECISION_POLL_MAX_DELAY_MS = 5e3;
548
547
  const DEFAULT_DECISION_TIMEOUT_MS = 6e4;
@@ -557,13 +556,14 @@ const pollForDecision = async (retrieve, { timeoutMs = DEFAULT_DECISION_TIMEOUT_
557
556
  for (;;) {
558
557
  if (signal?.aborted) throw new CalmLensError(SDK_ERROR_CODES.CANCELLED, { message: "Request cancelled" });
559
558
  const asset = await retrieve();
560
- if (DECIDED_ASSET_STATUSES.includes(asset.status)) return asset;
559
+ if (isAssetDecided(asset)) return asset;
561
560
  const remaining = deadline - now();
562
561
  if (remaining <= 0) throw new CalmLensError(SDK_ERROR_CODES.TIMEOUT, {
563
- message: `Asset ${asset.id} had no moderation decision after ${timeoutMs}ms (status ${asset.status})`,
562
+ message: `Asset ${asset.id} had no moderation decision after ${timeoutMs}ms (processing ${asset.processing.status}, moderation ${asset.moderation.status})`,
564
563
  details: {
565
564
  assetId: asset.id,
566
- status: asset.status
565
+ processingStatus: asset.processing.status,
566
+ moderationStatus: asset.moderation.status
567
567
  }
568
568
  });
569
569
  await sleep(Math.min(delay, remaining), signal);
@@ -39,6 +39,8 @@ const API_ERROR_CODES = {
39
39
  UPLOAD_PRESET_NOT_FOUND: "upload-preset/not-found",
40
40
  UPLOAD_PRESET_DISABLED: "upload-preset/disabled",
41
41
  UPLOAD_PRESET_TOKEN_REQUIRED: "upload-preset/token-required",
42
+ REMOTE_URL_NOT_ALLOWED: "upload/remote-url-not-allowed",
43
+ WEBSITE_RATE_LIMIT_EXCEEDED: "upload/website-rate-limit-exceeded",
42
44
  UPLOAD_PRESET_CONTENT_TYPE_NOT_ALLOWED: "upload-preset/content-type-not-allowed",
43
45
  UPLOAD_PRESET_TOO_LARGE: "upload-preset/too-large",
44
46
  UPLOAD_PRESET_DAILY_LIMIT_REACHED: "upload-preset/daily-limit-reached",
@@ -46,7 +48,18 @@ const API_ERROR_CODES = {
46
48
  UPLOAD_PRESET_FIELD_NOT_ALLOWED: "upload-preset/field-not-allowed",
47
49
  UPLOAD_TOKEN_INVALID: "upload-token/invalid",
48
50
  UPLOAD_TOKEN_EXPIRED: "upload-token/expired",
49
- UPLOAD_TOKEN_USED: "upload-token/used"
51
+ UPLOAD_TOKEN_USED: "upload-token/used",
52
+ INVALID_REMOTE_URL: "asset/invalid-remote-url",
53
+ REMOTE_URL_UNAVAILABLE: "asset/remote-url-unavailable",
54
+ APPEAL_NOT_FOUND: "appeal/not-found",
55
+ APPEAL_JUDGMENT_NOT_FOUND: "appeal/judgment-not-found",
56
+ APPEAL_ASSET_NOT_FOUND: "appeal/asset-not-found",
57
+ APPEAL_PERMISSION_DENIED: "appeal/permission-denied",
58
+ APPEAL_ALREADY_REVIEWED: "appeal/already-reviewed",
59
+ APPEAL_DECISION_CHANGED: "appeal/decision-changed",
60
+ APPEAL_INVALID_ACTION: "appeal/invalid-action",
61
+ APPEAL_SAFETY_HELD: "appeal/safety-held",
62
+ APPEAL_CONTENT_UNAVAILABLE: "appeal/content-unavailable"
50
63
  };
51
64
  /** The HTTP status and default message the API returns with each documented error code. */
52
65
  const API_ERROR_DEFINITIONS = {
@@ -202,6 +215,14 @@ const API_ERROR_DEFINITIONS = {
202
215
  status: 401,
203
216
  message: "This upload preset only accepts uploads with an upload token. Sign one on your server with uploadTokens.sign and pass it to the client."
204
217
  },
218
+ "upload/remote-url-not-allowed": {
219
+ status: 403,
220
+ message: "This project doesn't accept URLs from this domain. Change the allowed or blocked domains under Project settings."
221
+ },
222
+ "upload/website-rate-limit-exceeded": {
223
+ status: 429,
224
+ message: "This project has submitted too many websites in the last minute. Wait for the Retry-After period, or lower the pace of submissions."
225
+ },
205
226
  "upload-preset/content-type-not-allowed": {
206
227
  status: 415,
207
228
  message: "This upload preset doesn't accept this file type."
@@ -233,6 +254,50 @@ const API_ERROR_DEFINITIONS = {
233
254
  "upload-token/used": {
234
255
  status: 409,
235
256
  message: "The upload token has already been used. Each token uploads one asset."
257
+ },
258
+ "asset/invalid-remote-url": {
259
+ status: 400,
260
+ message: "Remote URLs must use HTTP or HTTPS and cannot target private networks, localhost names or URL credentials."
261
+ },
262
+ "asset/remote-url-unavailable": {
263
+ status: 422,
264
+ message: "The URL responded with an error status. Check that it is publicly reachable."
265
+ },
266
+ "appeal/not-found": {
267
+ status: 404,
268
+ message: "The appeal does not exist in this project."
269
+ },
270
+ "appeal/judgment-not-found": {
271
+ status: 404,
272
+ message: "The judgment event is unavailable, belongs to another project or cannot supply an asset decision. Supply explicit context instead."
273
+ },
274
+ "appeal/asset-not-found": {
275
+ status: 404,
276
+ message: "The linked asset does not exist in this project."
277
+ },
278
+ "appeal/permission-denied": {
279
+ status: 403,
280
+ message: "You cannot review this project's appeals."
281
+ },
282
+ "appeal/already-reviewed": {
283
+ status: 409,
284
+ message: "A reviewer already resolved this appeal."
285
+ },
286
+ "appeal/decision-changed": {
287
+ status: 409,
288
+ message: "The linked asset's decision changed after the appealed decision. Submit a new appeal for the current decision."
289
+ },
290
+ "appeal/invalid-action": {
291
+ status: 400,
292
+ message: "The decision's action is not valid for this appeal."
293
+ },
294
+ "appeal/safety-held": {
295
+ status: 409,
296
+ message: "A safety hold prevents this appeal from being submitted or applied."
297
+ },
298
+ "appeal/content-unavailable": {
299
+ status: 409,
300
+ message: "The appeal's content is unavailable, or approval would require restoring removed content."
236
301
  }
237
302
  };
238
303
  //#endregion
@@ -325,7 +390,7 @@ const invalidConfig = (message) => new CalmLensError(SDK_ERROR_CODES.INVALID_CON
325
390
  //#endregion
326
391
  //#region src/client/CalmLensVersion.ts
327
392
  /** This SDK's version, from its package.json. */
328
- const SDK_VERSION = "0.13.0";
393
+ const SDK_VERSION = "0.15.0";
329
394
  const runtimeName = () => {
330
395
  const runtime = globalThis;
331
396
  if (isReactNativeRuntime()) return "react-native";
@@ -1,5 +1,5 @@
1
- import { c as invalidArgument, o as CalmLensError, s as SDK_ERROR_CODES } from "./CalmLensVersion-DK4BMEST.js";
2
- import { n as encodePathSegment } from "./CalmLensUtils-B4i3Z2He.js";
1
+ import { c as invalidArgument, o as CalmLensError, s as SDK_ERROR_CODES } from "./CalmLensVersion-N71PMJAz.js";
2
+ import { n as encodePathSegment } from "./CalmLensUtils-B3S--hBG.js";
3
3
  //#region ../shared/src/JsonUtils.ts
4
4
  const stringifyJsonCanonical = (value) => JSON.stringify(value, (_key, nestedValue) => {
5
5
  if (!nestedValue || typeof nestedValue !== "object" || Array.isArray(nestedValue)) return nestedValue;