@calmlens/sdk 0.15.0 → 0.16.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/README.md +29 -9
- package/cjs/{CalmLensConnection-DoemramF.js → CalmLensConnection-CPdx_acA.js} +2 -2
- package/cjs/{CalmLensUtils-Cv1Ylp9-.js → CalmLensUtils-DvhY8-cU.js} +1 -1
- package/cjs/{CalmLensVersion-CuxKdijk.js → CalmLensVersion-CrlGk2gX.js} +6 -1
- package/cjs/{CalmLensWebhooks-qrL-Zdu3.js → CalmLensWebhooks-C2VrleZm.js} +4 -4
- package/cjs/Classification-DJU_DfOO.d.ts +4565 -0
- package/cjs/TestTriggers-CxFZ-3uz.d.ts +43 -0
- package/cjs/{WebhookPayload-vy8HNMaK.d.ts → WebhookPayload-BfUmVu2y.d.ts} +77 -4622
- package/cjs/app.d.ts +4 -3
- package/cjs/app.js +3 -3
- package/cjs/{index-Dz340UQ9.d.ts → index-VxklV9OQ.d.ts} +4 -1
- package/cjs/index.d.ts +4 -3
- package/cjs/index.js +1 -1
- package/cjs/server.d.ts +8 -7
- package/cjs/server.js +17 -21
- package/cjs/test-inputs.d.ts +2 -0
- package/cjs/test-inputs.js +265 -0
- package/cjs/testing.d.ts +2 -4
- package/cjs/testing.js +48 -27
- package/esm/{CalmLensConnection-CQLoUoBd.js → CalmLensConnection-DYo5U2L0.js} +2 -2
- package/esm/{CalmLensUtils-B3S--hBG.js → CalmLensUtils-BDtpOfho.js} +1 -1
- package/esm/{CalmLensVersion-N71PMJAz.js → CalmLensVersion-CchG7NWy.js} +6 -1
- package/esm/{CalmLensWebhooks-BxMSx1Vm.js → CalmLensWebhooks-B7nQMCHx.js} +4 -4
- package/esm/Classification-DJU_DfOO.d.ts +4565 -0
- package/esm/TestTriggers-CxFZ-3uz.d.ts +43 -0
- package/esm/{WebhookPayload-vy8HNMaK.d.ts → WebhookPayload-BfUmVu2y.d.ts} +77 -4622
- package/esm/app.d.ts +4 -3
- package/esm/app.js +3 -3
- package/esm/{index-Dz340UQ9.d.ts → index-VxklV9OQ.d.ts} +4 -1
- package/esm/index.d.ts +4 -3
- package/esm/index.js +1 -1
- package/esm/server.d.ts +8 -7
- package/esm/server.js +17 -21
- package/esm/test-inputs.d.ts +2 -0
- package/esm/test-inputs.js +256 -0
- package/esm/testing.d.ts +2 -4
- package/esm/testing.js +48 -27
- package/package.json +13 -2
package/README.md
CHANGED
|
@@ -216,15 +216,14 @@ List assets in your project with pagination.
|
|
|
216
216
|
|
|
217
217
|
```typescript
|
|
218
218
|
async assets.list(options: {
|
|
219
|
-
|
|
219
|
+
cursor?: string;
|
|
220
220
|
pageSize?: number;
|
|
221
|
-
ordering?: Array<{ field:
|
|
221
|
+
ordering?: Array<{ field: "createdAt" | "id"; direction: "ASC" | "DESC" }>;
|
|
222
222
|
filter?: string | null;
|
|
223
223
|
}): Promise<{
|
|
224
224
|
items: Asset[];
|
|
225
|
-
total: number;
|
|
226
225
|
hasMore: boolean;
|
|
227
|
-
|
|
226
|
+
nextCursor: string | null;
|
|
228
227
|
pageSize: number;
|
|
229
228
|
}>
|
|
230
229
|
```
|
|
@@ -232,17 +231,16 @@ async assets.list(options: {
|
|
|
232
231
|
**Example:**
|
|
233
232
|
```typescript
|
|
234
233
|
const result = await client.assets.list({
|
|
235
|
-
pageIndex: 0,
|
|
236
234
|
pageSize: 20
|
|
237
235
|
});
|
|
238
236
|
|
|
239
|
-
console.log(`
|
|
237
|
+
console.log(`Received ${result.items.length} assets`);
|
|
240
238
|
result.items.forEach(asset => {
|
|
241
239
|
console.log(`${asset.name}: ${asset.moderation.status}`);
|
|
242
240
|
});
|
|
243
241
|
```
|
|
244
242
|
|
|
245
|
-
To read every matching asset, iterate instead of paging by hand. Pages are fetched as you go
|
|
243
|
+
To read every matching asset, iterate instead of paging by hand. Pages are fetched as you go using continuation cursors. Inserting or deleting other assets does not shift the cursor position. To page manually, pass `nextCursor` as `cursor` with the same filters and ordering until it is null. Lists are not snapshots; assets may still be deleted or change filter membership during traversal.
|
|
246
244
|
|
|
247
245
|
```typescript
|
|
248
246
|
for await (const asset of client.assets.iterate({ filter: "moderation.status==rejected", pageSize: 100 })) {
|
|
@@ -257,7 +255,6 @@ List assets extracted from a website or multimedia document.
|
|
|
257
255
|
```typescript
|
|
258
256
|
const children = await client.assets.listChildren({
|
|
259
257
|
assetId: parentAssetId,
|
|
260
|
-
pageIndex: 0,
|
|
261
258
|
pageSize: 20,
|
|
262
259
|
});
|
|
263
260
|
|
|
@@ -704,7 +701,7 @@ Each delivery has these headers (the names are exported as constants):
|
|
|
704
701
|
|
|
705
702
|
Verify the exact raw request body before parsing it; re-serializing parsed JSON can change the signed bytes. `parseWebhookEvent` verifies the delivery and returns the parsed event, or throws `sdk/invalid-webhook-signature` (bad signature or a timestamp more than `WEBHOOK_SIGNATURE_TOLERANCE_SECONDS`, 5 minutes, from your clock, which stops replays) or `sdk/invalid-webhook-payload`. `verifyWebhookSignature` takes the same options and returns a boolean. Both accept the body as a string, `Uint8Array`/`Buffer` or `ArrayBuffer`, and read the two headers from `headers` (a `Headers` object or Node's `req.headers`) when you don't pass `signature` and `timestamp`.
|
|
706
703
|
|
|
707
|
-
The result is typed as `WebhookEventPayload
|
|
704
|
+
The result is typed as an extensible `WebhookEventPayload`. Event types and fact keys may be unfamiliar, and fact values are `unknown`; validate the facts your handler uses. Extra fields remain available. The [webhooks guide](https://calmlens.com/docs/guides/webhooks#event-types) lists current event types. Deliveries are retried, so make your handler idempotent by `event.id`.
|
|
708
705
|
|
|
709
706
|
**Fetch API** (Next.js route handlers, Remix, Cloudflare Workers, Bun, Deno):
|
|
710
707
|
|
|
@@ -810,3 +807,26 @@ Requests send `User-Agent: calmlens-js/<version> (<runtime>/<version>)` from ser
|
|
|
810
807
|
## Releasing
|
|
811
808
|
|
|
812
809
|
Stable releases are published automatically from `main` when packed SDK contents differ from npm `latest` and an SDK Changeset is present. Contributors must run `bun run changeset` to choose the release type and write release notes. CI updates and commits this package's `CHANGELOG.md` automatically. See the repository's [.changeset release guide](../../.changeset/README.md).
|
|
810
|
+
|
|
811
|
+
### Test-input images
|
|
812
|
+
|
|
813
|
+
The optional `@calmlens/sdk/test-inputs` entry generates and recognises the same
|
|
814
|
+
project-specific colour grids used by the CalmLens portal:
|
|
815
|
+
|
|
816
|
+
```ts
|
|
817
|
+
import { paintTestImage, detectTestImage } from "@calmlens/sdk/test-inputs";
|
|
818
|
+
|
|
819
|
+
const width = 512;
|
|
820
|
+
const height = 512;
|
|
821
|
+
const rgba = paintTestImage("violence", projectTestInputKey, width, height);
|
|
822
|
+
const signal = detectTestImage({ width, height, rgba }, projectTestInputKey);
|
|
823
|
+
// signal === "violence"
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
Encode the returned RGBA bytes with your image library to download a PNG. To
|
|
827
|
+
recognise a downloaded image, decode it into RGBA first. These helpers have no
|
|
828
|
+
DOM, image-codec, or Cloudflare dependencies. The grid tolerates resizing and
|
|
829
|
+
lossy compression; cropping, rotation, and severe colour changes are unsupported.
|
|
830
|
+
The entry also exports `generateTestTextCode` and `detectTestTrigger` for text
|
|
831
|
+
test inputs. Use your project's test input key; another project's key does not
|
|
832
|
+
activate its test signals.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const require_CalmLensVersion = require("./CalmLensVersion-
|
|
2
|
-
const require_CalmLensUtils = require("./CalmLensUtils-
|
|
1
|
+
const require_CalmLensVersion = require("./CalmLensVersion-CrlGk2gX.js");
|
|
2
|
+
const require_CalmLensUtils = require("./CalmLensUtils-DvhY8-cU.js");
|
|
3
3
|
//#region src/client/CalmLensConnection.ts
|
|
4
4
|
const DEFAULT_TIMEOUT_MS = 12e4;
|
|
5
5
|
const DEFAULT_MAX_RETRIES = 2;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_CalmLensVersion = require("./CalmLensVersion-
|
|
1
|
+
const require_CalmLensVersion = require("./CalmLensVersion-CrlGk2gX.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([
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
//#region src/client/CalmLensErrorCodes.ts
|
|
2
2
|
/** Error codes the CalmLens API documents, by name. */
|
|
3
3
|
const API_ERROR_CODES = {
|
|
4
|
+
INVALID_CURSOR: "validation/invalid-cursor",
|
|
4
5
|
MISSING_TOKEN: "auth/missing-token",
|
|
5
6
|
INVALID_API_KEY: "auth/invalid-api-key",
|
|
6
7
|
API_KEY_PROJECT_MISMATCH: "auth/project-mismatch",
|
|
@@ -63,6 +64,10 @@ const API_ERROR_CODES = {
|
|
|
63
64
|
};
|
|
64
65
|
/** The HTTP status and default message the API returns with each documented error code. */
|
|
65
66
|
const API_ERROR_DEFINITIONS = {
|
|
67
|
+
"validation/invalid-cursor": {
|
|
68
|
+
status: 400,
|
|
69
|
+
message: "The cursor is invalid or belongs to a different query."
|
|
70
|
+
},
|
|
66
71
|
"auth/missing-token": {
|
|
67
72
|
status: 401,
|
|
68
73
|
message: "Authentication required. Send your project API key in the X-Api-Key header."
|
|
@@ -390,7 +395,7 @@ const invalidConfig = (message) => new CalmLensError(SDK_ERROR_CODES.INVALID_CON
|
|
|
390
395
|
//#endregion
|
|
391
396
|
//#region src/client/CalmLensVersion.ts
|
|
392
397
|
/** This SDK's version, from its package.json. */
|
|
393
|
-
const SDK_VERSION = "0.
|
|
398
|
+
const SDK_VERSION = "0.16.0";
|
|
394
399
|
const runtimeName = () => {
|
|
395
400
|
const runtime = globalThis;
|
|
396
401
|
if (isReactNativeRuntime()) return "react-native";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const require_CalmLensVersion = require("./CalmLensVersion-
|
|
2
|
-
const require_CalmLensUtils = require("./CalmLensUtils-
|
|
1
|
+
const require_CalmLensVersion = require("./CalmLensVersion-CrlGk2gX.js");
|
|
2
|
+
const require_CalmLensUtils = require("./CalmLensUtils-DvhY8-cU.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;
|
|
@@ -124,7 +124,7 @@ async function verifyWebhookSignature(options) {
|
|
|
124
124
|
/**
|
|
125
125
|
* Verifies a webhook delivery and parses its body. Throws `sdk/invalid-webhook-signature`
|
|
126
126
|
* when the signature or timestamp does not verify, and `sdk/invalid-webhook-payload` when a
|
|
127
|
-
* verified body is not a webhook event.
|
|
127
|
+
* verified body is not a webhook event. Unknown event types, fact values and fields remain available.
|
|
128
128
|
*
|
|
129
129
|
* Event types and fact keys added to CalmLens after this SDK version are returned as they are,
|
|
130
130
|
* so keep a default branch when you switch on `type`.
|
|
@@ -141,7 +141,7 @@ async function parseWebhookEvent(options) {
|
|
|
141
141
|
});
|
|
142
142
|
}
|
|
143
143
|
const candidate = event;
|
|
144
|
-
if (!candidate || typeof candidate !== "object" || typeof candidate.id !== "string" || typeof candidate.type !== "string" || typeof candidate.projectId !== "string" || !candidate.data || typeof candidate.data !== "object") throw new require_CalmLensVersion.CalmLensError(require_CalmLensVersion.SDK_ERROR_CODES.INVALID_WEBHOOK_PAYLOAD, { message: "Webhook body is not a CalmLens event" });
|
|
144
|
+
if (!candidate || typeof candidate !== "object" || typeof candidate.id !== "string" || typeof candidate.type !== "string" || typeof candidate.projectId !== "string" || !candidate.data || typeof candidate.data !== "object" || Array.isArray(candidate.data)) throw new require_CalmLensVersion.CalmLensError(require_CalmLensVersion.SDK_ERROR_CODES.INVALID_WEBHOOK_PAYLOAD, { message: "Webhook body is not a CalmLens event" });
|
|
145
145
|
return event;
|
|
146
146
|
}
|
|
147
147
|
//#endregion
|