@calmlens/sdk 0.16.3 → 0.17.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/README.md +398 -163
- package/cjs/BrowserUpload-DZ0Vbmxi.js +10 -0
- package/cjs/BrowserUpload-uZjVFGfP.d.ts +11 -0
- package/cjs/CalmLensAppClient-CV_K26Ce.d.ts +40 -0
- package/cjs/CalmLensAppClient-DBGmaDlG.js +89 -0
- package/cjs/CalmLensConnection-K1TAD1Z-.js +659 -0
- package/cjs/CalmLensServerClient-C-pxiz0C.js +645 -0
- package/cjs/CalmLensServerClient-JtP687a3.d.ts +235 -0
- package/cjs/CalmLensTypes-9Vt16pc7.d.ts +40400 -0
- package/cjs/Classification-94kSYWZw-CMnQKW13.d.ts +5873 -0
- package/cjs/CryptoUtils-B_x8lMIx-YBW1-bvL.js +42 -0
- package/cjs/FileIcons-Ob003MdS.js +175 -0
- package/cjs/Jurisdiction-FusEXb4U-zVs21tDv.js +91 -0
- package/cjs/ModerationContext-9lGm-Mna-CcmbRnOy.d.ts +67 -0
- package/cjs/ModerationContextLimits-Dj1YAl3G.js +1311 -0
- package/cjs/ReactUpload-DxtFMr06.js +54 -0
- package/cjs/ReactUpload-nZahpmyg.d.ts +17 -0
- package/cjs/TestTriggers-By07LR31-CmK0yTyR.d.ts +271 -0
- package/cjs/TestTriggers-DcArt0Nu-CvoaONUB.js +1326 -0
- package/cjs/UploadController-BBkN4Ni6.js +618 -0
- package/{esm/index-C9Xw1aid.d.ts → cjs/WebhookPayload-2aL31v0J.d.ts} +131 -155
- package/cjs/app.d.ts +7 -44
- package/cjs/app.js +11 -89
- package/cjs/elements.d.ts +88 -0
- package/cjs/elements.js +555 -0
- package/cjs/file-icons.d.ts +67 -0
- package/cjs/file-icons.js +10 -0
- package/cjs/index-CI4BzN4W.d.ts +252 -0
- package/cjs/index.d.ts +6 -4
- package/cjs/index.js +9 -4
- package/cjs/react-native.d.ts +56 -0
- package/cjs/react-native.js +495 -0
- package/cjs/react.d.ts +30 -0
- package/cjs/react.js +370 -0
- package/cjs/server.d.ts +12 -191
- package/cjs/server.js +18 -378
- package/cjs/test-inputs.d.ts +2 -2
- package/cjs/test-inputs.js +9 -264
- package/cjs/testing.d.ts +285 -190
- package/cjs/testing.js +2393 -1203
- package/cjs/ui-CgZpgpNo.d.ts +526 -0
- package/cjs/ui-KceuoVCM.js +583 -0
- package/cjs/ui.d.ts +2 -0
- package/cjs/ui.js +27 -0
- package/cjs/vue.d.ts +490 -0
- package/cjs/vue.js +419 -0
- package/esm/BrowserUpload-D7-zNmc0.js +5 -0
- package/esm/BrowserUpload-uZjVFGfP.d.ts +11 -0
- package/esm/CalmLensAppClient-CV_K26Ce.d.ts +40 -0
- package/esm/CalmLensAppClient-FVMwrHlH.js +84 -0
- package/esm/CalmLensConnection-iyNQHA8L.js +582 -0
- package/esm/CalmLensServerClient-JtP687a3.d.ts +235 -0
- package/esm/CalmLensServerClient-fQEYKLw4.js +586 -0
- package/esm/CalmLensTypes-9Vt16pc7.d.ts +40400 -0
- package/esm/Classification-94kSYWZw-CMnQKW13.d.ts +5873 -0
- package/esm/CryptoUtils-B_x8lMIx-DhuWGzqn.js +25 -0
- package/esm/FileIcons-M6dzjFxd.js +128 -0
- package/esm/Jurisdiction-FusEXb4U-1ov6m5yE.js +46 -0
- package/esm/ModerationContext-9lGm-Mna-CcmbRnOy.d.ts +67 -0
- package/esm/ModerationContextLimits-D1x_WAtP.js +1114 -0
- package/esm/ReactUpload-D6yBCkcw.js +37 -0
- package/esm/ReactUpload-nZahpmyg.d.ts +17 -0
- package/esm/TestTriggers-By07LR31-CmK0yTyR.d.ts +271 -0
- package/esm/TestTriggers-DcArt0Nu-s0AQZuWE.js +1266 -0
- package/esm/UploadController-txp5NuzH.js +589 -0
- package/{cjs/index-C9Xw1aid.d.ts → esm/WebhookPayload-2aL31v0J.d.ts} +131 -155
- package/esm/app.d.ts +7 -44
- package/esm/app.js +3 -86
- package/esm/elements.d.ts +88 -0
- package/esm/elements.js +528 -0
- package/esm/file-icons.d.ts +67 -0
- package/esm/file-icons.js +1 -0
- package/esm/index-CI4BzN4W.d.ts +252 -0
- package/esm/index.d.ts +6 -4
- package/esm/index.js +1 -1
- package/esm/react-native.d.ts +56 -0
- package/esm/react-native.js +467 -0
- package/esm/react.d.ts +30 -0
- package/esm/react.js +343 -0
- package/esm/server.d.ts +12 -191
- package/esm/server.js +3 -369
- package/esm/styles.css +147 -0
- package/esm/svelte/CalmLensMedia.svelte +134 -0
- package/esm/svelte/CalmLensUploader.svelte +175 -0
- package/esm/svelte/Icon.svelte +7 -0
- package/esm/svelte/index.d.ts +37 -0
- package/esm/svelte/index.js +6 -0
- package/esm/test-inputs.d.ts +2 -2
- package/esm/test-inputs.js +1 -256
- package/esm/testing.d.ts +285 -190
- package/esm/testing.js +2329 -1122
- package/esm/ui-Ca_SpJXf.js +458 -0
- package/esm/ui-CgZpgpNo.d.ts +526 -0
- package/esm/ui.d.ts +2 -0
- package/esm/ui.js +3 -0
- package/esm/vue.d.ts +490 -0
- package/esm/vue.js +392 -0
- package/package.json +110 -11
- package/cjs/CalmLensConnection-BNUHp_AQ.js +0 -234
- package/cjs/CalmLensUtils-o171ownK.js +0 -699
- package/cjs/CalmLensVersion-DwhgxQK5.js +0 -480
- package/cjs/CalmLensWebhooks-BKrq30Yp.js +0 -201
- package/cjs/Classification-BNhgwGEm-DmA9VEuE.d.ts +0 -4806
- package/cjs/TestTriggers-CRKtulyp-vrzEq2wm.d.ts +0 -44
- package/cjs/WebhookPayload-CJoIkGBD.d.ts +0 -11753
- package/esm/CalmLensConnection-XTqmlwzG.js +0 -193
- package/esm/CalmLensUtils-DsF8Aa_x.js +0 -574
- package/esm/CalmLensVersion-DcifRKsx.js +0 -415
- package/esm/CalmLensWebhooks-BvGyk5d3.js +0 -148
- package/esm/Classification-BNhgwGEm-DmA9VEuE.d.ts +0 -4806
- package/esm/TestTriggers-CRKtulyp-vrzEq2wm.d.ts +0 -44
- package/esm/WebhookPayload-CJoIkGBD.d.ts +0 -11753
package/esm/testing.d.ts
CHANGED
|
@@ -1,17 +1,125 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { Ft as TypedEvent, Ht as PermissionGrant, T as CalmLensServerClientOptions, Ut as Folder, Yt as AssetBinaryPayloadInput, _t as SignedUploadToken, f as AssetModeration, gt as SignUploadTokenOptions, n as Asset, w as CalmLensAppClientOptions } from "./CalmLensTypes-9Vt16pc7.js";
|
|
2
|
+
import { t as CalmLensAppClient } from "./CalmLensAppClient-CV_K26Ce.js";
|
|
3
|
+
import { l as ApiErrorCode, n as WebhookEventPayload } from "./WebhookPayload-2aL31v0J.js";
|
|
4
|
+
import { t as CalmLensServerClient } from "./CalmLensServerClient-JtP687a3.js";
|
|
5
|
+
import { t as ClassificationTestSignal } from "./TestTriggers-By07LR31-CmK0yTyR.js";
|
|
6
|
+
import "zod";
|
|
7
|
+
/**
|
|
8
|
+
* Signs a single-use upload token with `apiKey`, locally. `CalmLensServerClient` and
|
|
9
|
+
* `MockCalmLensServerClient` share it so both check options the same way. `@calmlens/sdk/testing`
|
|
10
|
+
* exports it as `signUploadToken`, whose fixed `now` (milliseconds since the epoch) and `nonce`
|
|
11
|
+
* give the same token every time, for comparing with known tokens in tests.
|
|
12
|
+
*/
|
|
13
|
+
declare const signUploadTokenWithApiKey: (apiKey: string, options: SignUploadTokenOptions, { now, nonce }?: {
|
|
14
|
+
now?: number;
|
|
15
|
+
nonce?: string;
|
|
16
|
+
}) => Promise<SignedUploadToken>;
|
|
17
|
+
export declare const MEDIA_TEST_SIGNALS: readonly ["sexual", "violence", "self-harm", "harassment", "hate", "criminal-activity", "personal-information", "profanity", "violence.graphic"];
|
|
6
18
|
/** Read this aloud, or render it as large, high-contrast text in a video frame. */
|
|
7
|
-
export declare function generateMediaTestCode(signal: ClassificationTestSignal, testInputKey: string): string
|
|
8
|
-
//#endregion
|
|
9
|
-
//#endregion
|
|
10
|
-
//#region src/testing/MockApiKey.d.ts
|
|
19
|
+
export declare function generateMediaTestCode(signal: ClassificationTestSignal, testInputKey: string): Promise<string>;
|
|
11
20
|
export declare const MOCK_API_KEY_PREFIX = "sk_test_";
|
|
12
21
|
export declare const createMockApiKey: (grants?: PermissionGrant[]) => string;
|
|
13
|
-
|
|
14
|
-
|
|
22
|
+
/**
|
|
23
|
+
* The prefix of every kind of object customers can see, so an ID says what it identifies:
|
|
24
|
+
* `proj_8fK2mQx7Lp4NvB3tRz9Y` is a project. Rows that never leave the backend (usage meters, upload
|
|
25
|
+
* token uses, retained variants, terms acceptances, notices) keep their own internal IDs.
|
|
26
|
+
*/
|
|
27
|
+
declare const ID_PREFIXES: {
|
|
28
|
+
readonly organisation: "org";
|
|
29
|
+
readonly project: "proj";
|
|
30
|
+
readonly asset: "asset";
|
|
31
|
+
readonly folder: "fldr";
|
|
32
|
+
readonly lens: "lens";
|
|
33
|
+
readonly apiKey: "key";
|
|
34
|
+
readonly uploadPreset: "preset";
|
|
35
|
+
readonly connector: "conn";
|
|
36
|
+
readonly connectorDelivery: "dlv";
|
|
37
|
+
readonly hashList: "hl";
|
|
38
|
+
readonly hashListEntry: "hle";
|
|
39
|
+
readonly policy: "pol";
|
|
40
|
+
readonly event: "evt";
|
|
41
|
+
readonly user: "user";
|
|
42
|
+
readonly member: "mem";
|
|
43
|
+
readonly invitation: "inv";
|
|
44
|
+
readonly supportTicket: "tkt";
|
|
45
|
+
readonly supportTicketMessage: "msg";
|
|
46
|
+
readonly humanReview: "rev";
|
|
47
|
+
readonly appeal: "apl";
|
|
48
|
+
readonly complianceCase: "case";
|
|
49
|
+
readonly safetyHold: "hold";
|
|
50
|
+
readonly creditPurchase: "cp";
|
|
51
|
+
readonly oauthClient: "oac";
|
|
52
|
+
readonly waitlistEntry: "wl";
|
|
53
|
+
};
|
|
54
|
+
type IdKind = keyof typeof ID_PREFIXES;
|
|
55
|
+
type IdPrefix = (typeof ID_PREFIXES)[IdKind];
|
|
56
|
+
/** The parent categories, in the API's order. */
|
|
57
|
+
declare const MOCK_CATEGORIES: readonly ["sexual", "violence", "self-harm", "harassment", "hate", "criminal-activity", "personal-information", "profanity"];
|
|
58
|
+
/**
|
|
59
|
+
* Where the mock's moderation leaves an upload: `pending` (still processing), `failed`
|
|
60
|
+
* (processing failed, retryable), or a decision with that moderation status (`purged` also
|
|
61
|
+
* removes the content).
|
|
62
|
+
*/
|
|
63
|
+
type MockAssetOutcome = "pending" | "failed" | "allowed" | "limited" | "age-restricted" | "blocked" | "purged";
|
|
64
|
+
type Category = (typeof MOCK_CATEGORIES)[number];
|
|
65
|
+
/**
|
|
66
|
+
* A moderation decision for `mockOptions.moderate` or `completeProcessing`, built with
|
|
67
|
+
* `mockDecision(status)`: flag the categories it found, with their scores and qualifiers, and
|
|
68
|
+
* mark the categories it couldn't assess. Each call checks its names and scores and throws
|
|
69
|
+
* `sdk/invalid-argument` for one CalmLens doesn't have.
|
|
70
|
+
*/
|
|
71
|
+
export declare class MockDecision {
|
|
72
|
+
#private;
|
|
73
|
+
readonly status: MockAssetOutcome;
|
|
74
|
+
constructor(status: MockAssetOutcome);
|
|
75
|
+
/**
|
|
76
|
+
* Records findings in `category` with its `score` (0 to 1) and, optionally, scores for its
|
|
77
|
+
* qualifiers, such as `{ "violence-threat": 0.9 }`. The policy acts on a category at 0.5 and
|
|
78
|
+
* above, so `flaggedCategories` lists it there unless the status is `allowed`.
|
|
79
|
+
*/
|
|
80
|
+
flag(category: Category, score: number, qualifiers?: Record<string, number>): this;
|
|
81
|
+
/** Marks `category` as not assessed (`not-evaluated` for reason `not-supported`). */
|
|
82
|
+
notEvaluated(category: Category): this;
|
|
83
|
+
/**
|
|
84
|
+
* The report a decided asset gets, as the API sends it: every category (unflagged ones
|
|
85
|
+
* evaluated with score 0), policy-adjusted results and the automated action and
|
|
86
|
+
* `flaggedCategories`. `undefined` for `pending` and `failed`.
|
|
87
|
+
*/
|
|
88
|
+
report(): Omit<AssetModeration, "status" | "manualReviews"> | undefined;
|
|
89
|
+
}
|
|
90
|
+
/** Starts a moderation decision with this status; see `MockDecision`. */
|
|
91
|
+
export declare const mockDecision: (status: MockAssetOutcome) => MockDecision;
|
|
92
|
+
/** Why the mock is moderating an asset, for `mockOptions.moderate`. */
|
|
93
|
+
type MockModerationTrigger =
|
|
94
|
+
/** An upload completed: `assets.create`, `assets.classify`, `text.classify` or a final part. */
|
|
95
|
+
"upload" |
|
|
96
|
+
/** `assets.retry` queued a failed asset again. */
|
|
97
|
+
"retry" |
|
|
98
|
+
/** `assets.explain` with `rerun: true` queued the asset again. */
|
|
99
|
+
"rerun" |
|
|
100
|
+
/** `completeProcessing(assetId)` finished processing without a decision of its own. */
|
|
101
|
+
"complete";
|
|
102
|
+
/** What `mockOptions.moderate` receives for each asset the mock moderates. */
|
|
103
|
+
interface MockModerationInput {
|
|
104
|
+
/** The asset as stored, still processing. */
|
|
105
|
+
asset: Asset;
|
|
106
|
+
/** The uploaded bytes (`null` without stored content, such as a website), and the text of a plain-text upload. */
|
|
107
|
+
content: {
|
|
108
|
+
bytes: Uint8Array | null;
|
|
109
|
+
text: string | null;
|
|
110
|
+
};
|
|
111
|
+
trigger: MockModerationTrigger;
|
|
112
|
+
/**
|
|
113
|
+
* `true` when the API would queue the work rather than answer with the decision: queued
|
|
114
|
+
* uploads, retries, reruns and `completeProcessing`.
|
|
115
|
+
*/
|
|
116
|
+
queued: boolean;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Decides an asset the mock moderates: a status or a `mockDecision(...)`, or a promise of one.
|
|
120
|
+
* Without it, queued uploads, retries and reruns stay `pending` and everything else is `allowed`.
|
|
121
|
+
*/
|
|
122
|
+
type MockModerate = (input: MockModerationInput) => MockAssetOutcome | MockDecision | Promise<MockAssetOutcome | MockDecision>;
|
|
15
123
|
interface MockStoredContent {
|
|
16
124
|
assetId: string;
|
|
17
125
|
parts: Map<number, Uint8Array>;
|
|
@@ -68,208 +176,196 @@ export declare class InMemoryMockDatabaseStorage implements MockDatabaseStorage
|
|
|
68
176
|
listFolders(projectId: string): Promise<Folder[]>;
|
|
69
177
|
deleteFolder(folderId: string): Promise<void>;
|
|
70
178
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
interface MockCalmLensServerClientOptions extends CalmLensServerClientOptions {
|
|
74
|
-
mockOptions?: {
|
|
75
|
-
databaseStorage?: MockDatabaseStorage;
|
|
76
|
-
imageStorage?: MockImageStorage;
|
|
77
|
-
createId?: () => string;
|
|
78
|
-
now?: () => number;
|
|
79
|
-
/** Outcome of `assets.create` (and queued multipart uploads). Defaults to `pending`. */
|
|
80
|
-
queuedOutcome?: MockAssetOutcome;
|
|
81
|
-
/** Outcome of `assets.moderate` and `text.moderate`. Defaults to `approved`. */
|
|
82
|
-
analyzedOutcome?: MockAssetOutcome;
|
|
83
|
-
signedUrlBaseUrl?: string;
|
|
84
|
-
};
|
|
85
|
-
}
|
|
179
|
+
/** A reviewer's decision for `decide`: the moderation status it gives the asset. */
|
|
180
|
+
type MockReviewDecision = "allowed" | "limited" | "age-restricted" | "blocked" | "purged";
|
|
86
181
|
/**
|
|
87
|
-
*
|
|
88
|
-
*
|
|
182
|
+
* A client method, named like its path on the client. A request is recorded under the first
|
|
183
|
+
* method that sends it; `callsTo` and `failNextRequest` also match the others (see
|
|
184
|
+
* `MockCalmLensCall`).
|
|
89
185
|
*/
|
|
90
|
-
type
|
|
91
|
-
/** The options each `MockCalmLensServerClient` method was given, by operation name. */
|
|
92
|
-
interface MockCalmLensOperationOptions {
|
|
93
|
-
"assets.list": ListAssetsOptions;
|
|
94
|
-
"assets.search": SearchAssetsOptions;
|
|
95
|
-
"assets.retrieve": RetrieveAssetOptions;
|
|
96
|
-
"assets.update": UpdateAssetOptions;
|
|
97
|
-
"assets.listChildren": ListAssetChildrenOptions;
|
|
98
|
-
"assets.create": SubmitAssetOptions;
|
|
99
|
-
"assets.moderate": SubmitAssetOptions;
|
|
100
|
-
"assets.uploadPart": UploadAssetPartOptions;
|
|
101
|
-
"assets.createSignedUrl": CreateAssetSignedUrlOptions;
|
|
102
|
-
"assets.move": MoveAssetOptions;
|
|
103
|
-
"assets.retry": RetryAssetOptions;
|
|
104
|
-
"assets.waitForDecision": WaitForAssetDecisionOptions;
|
|
105
|
-
"assets.deleteContent": DeleteAssetContentOptions;
|
|
106
|
-
"assets.delete": DeleteAssetOptions;
|
|
107
|
-
"text.moderate": ModerateTextOptions;
|
|
108
|
-
"cdn.serve": CdnServeOptions;
|
|
109
|
-
"events.list": ListEventsOptions;
|
|
110
|
-
"folders.list": undefined;
|
|
111
|
-
"folders.retrieve": FolderIdOptions;
|
|
112
|
-
"folders.create": CreateFolderOptions;
|
|
113
|
-
"folders.update": UpdateFolderOptions;
|
|
114
|
-
"folders.delete": FolderIdOptions;
|
|
115
|
-
"folders.move": MoveFolderOptions;
|
|
116
|
-
ensureLens: EnsureLensOptions;
|
|
117
|
-
ensureLenses: EnsureLensesOptions;
|
|
118
|
-
"uploadTokens.sign": SignUploadTokenOptions;
|
|
119
|
-
}
|
|
120
|
-
/** A `MockCalmLensServerClient` method, named like its path on the client. */
|
|
121
|
-
type MockCalmLensOperation = keyof MockCalmLensOperationOptions;
|
|
186
|
+
type MockCalmLensOperation = "assets.list" | "assets.iterate" | "assets.search" | "assets.retrieve" | "assets.waitForDecision" | "assets.update" | "assets.listChildren" | "assets.iterateChildren" | "assets.create" | "assets.classify" | "assets.uploadPart" | "assets.createSignedUrl" | "assets.move" | "assets.retry" | "assets.explain" | "assets.decide" | "assets.deleteContent" | "assets.delete" | "assets.batch" | "text.classify" | "cdn.serve" | "events.list" | "events.pages" | "folders.list" | "folders.retrieve" | "folders.create" | "folders.update" | "folders.delete" | "folders.move" | "hashLists.list" | "hashLists.retrieve" | "hashLists.create" | "hashLists.update" | "hashLists.delete" | "hashLists.listEntries" | "hashLists.addEntry" | "hashLists.removeEntry" | "ensureLens" | "ensureLenses";
|
|
122
187
|
/**
|
|
123
|
-
* One
|
|
124
|
-
*
|
|
188
|
+
* One request a mock client sent, as the in-memory API received it. `operation` is the client
|
|
189
|
+
* method that sends it; requests several methods send are recorded under the first: `text.classify`
|
|
190
|
+
* as `assets.classify`, `ensureLens` as `ensureLenses`, `assets.waitForDecision` polls as
|
|
191
|
+
* `assets.retrieve`, `assets.iterate` pages as `assets.list`, and so on. `callsTo` matches all of
|
|
192
|
+
* them. Methods that send nothing, such as `uploadTokens.sign` or a cached `ensureLens`, are not
|
|
193
|
+
* recorded.
|
|
125
194
|
*/
|
|
126
|
-
|
|
127
|
-
operation:
|
|
128
|
-
|
|
129
|
-
|
|
195
|
+
interface MockCalmLensCall {
|
|
196
|
+
operation: MockCalmLensOperation;
|
|
197
|
+
method: string;
|
|
198
|
+
/** The request URL. */
|
|
199
|
+
url: string;
|
|
200
|
+
/** The path after the API (or CDN) base URL, with each segment decoded, such as `/assets/a1`. */
|
|
201
|
+
path: string;
|
|
202
|
+
/** Query parameters as sent, such as `{ "ordering[0][field]": "createdAt" }`. */
|
|
203
|
+
query: Record<string, string>;
|
|
204
|
+
/** Request headers, with lowercase names. */
|
|
205
|
+
headers: Record<string, string>;
|
|
206
|
+
/** The JSON body, the text of a `text/*` upload, the bytes of another upload, or `undefined`. */
|
|
207
|
+
body: unknown;
|
|
208
|
+
/** The HTTP status the mock answered with, or `undefined` when the request failed without one. */
|
|
209
|
+
status: number | undefined;
|
|
210
|
+
}
|
|
130
211
|
/**
|
|
131
|
-
* What a simulated request failure
|
|
132
|
-
*
|
|
133
|
-
*
|
|
212
|
+
* What a simulated request failure does: `"transport-error"` and `"timeout"` fail the request
|
|
213
|
+
* like a network failure (`sdk/transport-error`) or a deadline (`sdk/timeout`); an API error
|
|
214
|
+
* code, such as `"upload/limit-exceeded"`, answers with that API error and its HTTP status; a
|
|
215
|
+
* `CalmLensError` is thrown as is and any other `Error` as the cause of `sdk/transport-error`,
|
|
216
|
+
* like an exception from `fetch`.
|
|
134
217
|
*/
|
|
135
|
-
type MockRequestFailure = "transport-error" | "timeout" | Error;
|
|
218
|
+
type MockRequestFailure = "transport-error" | "timeout" | ApiErrorCode | Error;
|
|
219
|
+
/** Options for a simulated API error: its `details` and the `Retry-After` it answers with. */
|
|
220
|
+
interface MockFailureOptions {
|
|
221
|
+
operation?: MockCalmLensOperation;
|
|
222
|
+
/** The error's `details`, for an API error code. */
|
|
223
|
+
details?: Record<string, unknown>;
|
|
224
|
+
/** Seconds for the `Retry-After` header, for an API error code. */
|
|
225
|
+
retryAfter?: number;
|
|
226
|
+
}
|
|
136
227
|
/** An event to add to the mock feed; omitted fields get defaults. */
|
|
137
228
|
type MockEventInput = Partial<Omit<TypedEvent, "type">> & {
|
|
138
229
|
type: TypedEvent["type"];
|
|
139
230
|
};
|
|
231
|
+
/** The upload preset settings a `MockCalmLensAppClient` applies, as the API would. */
|
|
232
|
+
interface MockUploadPreset {
|
|
233
|
+
/** Refuse uploads without a token, like **Users your server approves**. Defaults to `false`. */
|
|
234
|
+
requireToken?: boolean;
|
|
235
|
+
/** Accepted content types, such as `["image/*"]`. Defaults to any type. */
|
|
236
|
+
allowedContentTypes?: string[];
|
|
237
|
+
maxFileSizeInBytes?: number;
|
|
238
|
+
/** Return `status` to the uploader. Defaults to `true`. */
|
|
239
|
+
showDecisions?: boolean;
|
|
240
|
+
/** Defaults to `public`. */
|
|
241
|
+
visibility?: "public" | "private";
|
|
242
|
+
/** Defaults to `true`, so the CDN can serve the upload. */
|
|
243
|
+
keepContentAfterProcessing?: boolean;
|
|
244
|
+
folderId?: string | null;
|
|
245
|
+
}
|
|
246
|
+
interface MockCalmLensServerClientOptions extends CalmLensServerClientOptions {
|
|
247
|
+
mockOptions?: {
|
|
248
|
+
databaseStorage?: MockDatabaseStorage;
|
|
249
|
+
imageStorage?: MockImageStorage;
|
|
250
|
+
/**
|
|
251
|
+
* Returns a new ID for an object of the kind `prefix` names (`asset`, `fldr`, `hl`, `hle`,
|
|
252
|
+
* `lens`, `evt` or `rev`). The default is like the API's: the prefix, `_` and 20 random
|
|
253
|
+
* base62 characters, such as `asset_5Gm2Rk8XqT3wLp9VbN4c`.
|
|
254
|
+
*/
|
|
255
|
+
createId?: (prefix: IdPrefix) => string;
|
|
256
|
+
/**
|
|
257
|
+
* The clock, in epoch milliseconds. The default is the system clock, moved on by at least a
|
|
258
|
+
* millisecond per reading, so assets created in a row have increasing `createdAt` values and
|
|
259
|
+
* orderings by `createdAt` don't depend on IDs.
|
|
260
|
+
*/
|
|
261
|
+
now?: () => number;
|
|
262
|
+
/**
|
|
263
|
+
* Decides each asset the mock moderates, from the stored asset, its content (bytes, and the
|
|
264
|
+
* text of a plain-text upload) and why it is moderated (`upload`, `retry`, `rerun` or
|
|
265
|
+
* `complete`). Return a status or a `mockDecision(...)`, whose report fills the asset's
|
|
266
|
+
* categories and policy. Without it, queued uploads, retries and reruns stay `pending` until
|
|
267
|
+
* `completeProcessing`, and everything else is `allowed`.
|
|
268
|
+
*/
|
|
269
|
+
moderate?: MockModerate;
|
|
270
|
+
signedUrlBaseUrl?: string;
|
|
271
|
+
};
|
|
272
|
+
}
|
|
140
273
|
/**
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
274
|
+
* The real `CalmLensServerClient`, answered by an in-memory CalmLens API and CDN instead of the
|
|
275
|
+
* network: every method runs the real client's code, and the in-memory API answers its requests
|
|
276
|
+
* with the API's statuses, bodies, error bodies and headers. Mock helpers decide assets, add
|
|
277
|
+
* events, change the API key's grants, fail requests and list the requests sent.
|
|
144
278
|
*/
|
|
145
|
-
export declare class MockCalmLensServerClient {
|
|
279
|
+
export declare class MockCalmLensServerClient extends CalmLensServerClient {
|
|
280
|
+
#private;
|
|
146
281
|
readonly databaseStorage: MockDatabaseStorage;
|
|
147
282
|
readonly imageStorage: MockImageStorage;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
private readonly signedUrlBaseUrl;
|
|
154
|
-
private readonly cdnBaseUrl;
|
|
155
|
-
private readonly projectId;
|
|
156
|
-
private readonly apiKey;
|
|
157
|
-
private readonly lenses;
|
|
158
|
-
private readonly eventFeed;
|
|
159
|
-
/** The queue mode each open multipart upload was started with, as the API saves it. */
|
|
160
|
-
private readonly uploadQueues;
|
|
161
|
-
private readonly idempotentResults;
|
|
162
|
-
private requestCount;
|
|
163
|
-
private readonly pendingFailures;
|
|
164
|
-
/** Every call made through this client, oldest first. */
|
|
165
|
-
readonly calls: MockCalmLensCall[];
|
|
166
|
-
/** Accepts the same options as `CalmLensServerClient` (validated the same way), plus `mockOptions`. */
|
|
283
|
+
/**
|
|
284
|
+
* Accepts the same options as `CalmLensServerClient` (validated the same way), plus
|
|
285
|
+
* `mockOptions`. `maxRetries` defaults to 0, so a failed request fails once; retry backoff and
|
|
286
|
+
* `assets.waitForDecision` take no real time.
|
|
287
|
+
*/
|
|
167
288
|
constructor(options: MockCalmLensServerClientOptions);
|
|
168
289
|
/**
|
|
169
|
-
*
|
|
170
|
-
*
|
|
290
|
+
* Every request sent to the mock's API and CDN, oldest first, by this client and the
|
|
291
|
+
* `MockCalmLensAppClient`s that use it, each with the client method that sent it.
|
|
171
292
|
*/
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
293
|
+
get calls(): MockCalmLensCall[];
|
|
294
|
+
/**
|
|
295
|
+
* Requests `operation` sends, oldest first. A request several methods send matches each of
|
|
296
|
+
* them: `callsTo("text.classify")` also lists `assets.classify` text uploads, and
|
|
297
|
+
* `callsTo("assets.waitForDecision")` the `assets.retrieve` requests it polls with.
|
|
298
|
+
*/
|
|
299
|
+
callsTo(operation: MockCalmLensOperation): MockCalmLensCall[];
|
|
300
|
+
/** Forgets the requests recorded so far, so `calls` lists only later ones. */
|
|
301
|
+
clearCalls(): void;
|
|
302
|
+
/**
|
|
303
|
+
* Makes the next request (or the next one `operation` sends) fail instead of reaching the
|
|
304
|
+
* in-memory API. Each queued failure fails one request, so a retry takes the next queued
|
|
305
|
+
* failure or reaches the API. An API error code answers with that error and its HTTP status,
|
|
306
|
+
* with `details` and a `Retry-After` of `retryAfter` seconds when given.
|
|
307
|
+
*/
|
|
308
|
+
failNextRequest(failure?: MockRequestFailure, options?: MockFailureOptions): void;
|
|
309
|
+
/**
|
|
310
|
+
* Changes the grants of the mock's API key, as editing the key in the portal would: later
|
|
311
|
+
* requests, such as `cdn.serve`, use them. The key itself stays the same, so idempotency keys
|
|
312
|
+
* it used still replay.
|
|
313
|
+
*/
|
|
314
|
+
setApiKeyGrants(grants: PermissionGrant[]): void;
|
|
177
315
|
/**
|
|
178
316
|
* Adds an event to the feed `events.list` reads, as if CalmLens had recorded it. Returns the
|
|
179
317
|
* stored event; pass it to `toWebhookEventPayload` to build a matching webhook body.
|
|
180
318
|
*/
|
|
181
|
-
enqueueEvent(input: MockEventInput): TypedEvent
|
|
182
|
-
/**
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
* `enqueueEvent`.
|
|
203
|
-
*/
|
|
204
|
-
list: (options?: ListEventsOptions) => Promise<GetEventsResponse>;
|
|
205
|
-
pages: (options?: ListEventsOptions) => AsyncGenerator<GetEventsResponse, void, undefined>;
|
|
206
|
-
};
|
|
207
|
-
private listEvents;
|
|
208
|
-
private iterateEventPages;
|
|
209
|
-
private iteratePages;
|
|
210
|
-
get text(): {
|
|
211
|
-
moderate: (options: ModerateTextOptions) => Promise<Asset>;
|
|
212
|
-
};
|
|
213
|
-
get assets(): {
|
|
319
|
+
enqueueEvent(input: MockEventInput): Promise<TypedEvent>;
|
|
320
|
+
/**
|
|
321
|
+
* Applies a reviewer's decision to a stored asset, as the portal or API would: the moderation
|
|
322
|
+
* status changes (`purged` also removes the content, with reason `requested` and an
|
|
323
|
+
* `asset.content-removed` event), the review joins `manualReviews`, and an `asset.<decision>`
|
|
324
|
+
* event with a `decided-by: reviewer` fact joins the events feed. Rejects with
|
|
325
|
+
* `asset/not-found` for an unknown asset. It sends no request.
|
|
326
|
+
*/
|
|
327
|
+
decide(assetId: string, decision: MockReviewDecision): Promise<Asset>;
|
|
328
|
+
/**
|
|
329
|
+
* Finishes processing a pending asset as the moderation pipeline would: with `decision`, or
|
|
330
|
+
* else what `mockOptions.moderate` returns for the `complete` trigger (`allowed` by default).
|
|
331
|
+
* The asset gets the decision's report, and `asset.classified` and the automated
|
|
332
|
+
* `asset.<status>` (or `asset.failed`) join the events feed. No review is recorded, so the
|
|
333
|
+
* asset can still be moderated again. Rejects with `asset/not-found` for an unknown asset and
|
|
334
|
+
* `sdk/invalid-argument` for one that isn't processing. It sends no request.
|
|
335
|
+
*/
|
|
336
|
+
completeProcessing(assetId: string, decision?: MockAssetOutcome | MockDecision): Promise<Asset>;
|
|
337
|
+
}
|
|
338
|
+
interface MockCalmLensAppClientOptions extends CalmLensAppClientOptions {
|
|
339
|
+
mockOptions?: {
|
|
214
340
|
/**
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
341
|
+
* The mock project the uploads go into. Pass the `MockCalmLensServerClient` your server code
|
|
342
|
+
* uses to see the uploads there and serve them from its CDN. Without one, the client creates
|
|
343
|
+
* its own, available as `server`.
|
|
218
344
|
*/
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
retrieve: (options: RetrieveAssetOptions) => Promise<Asset>;
|
|
224
|
-
listChildren: (childrenOptions?: ListAssetChildrenOptions) => Promise<AssetChildrenPage>;
|
|
225
|
-
iterateChildren: (options: IterateAssetChildrenOptions) => AsyncGenerator<Asset, void, undefined>;
|
|
226
|
-
update: (options: UpdateAssetOptions) => Promise<Asset>;
|
|
227
|
-
create: (options: SubmitAssetOptions) => Promise<Asset>;
|
|
228
|
-
moderate: (options: SubmitAssetOptions) => Promise<Asset>;
|
|
229
|
-
/** Continues a multipart upload: parts must arrive in order while it is `uploading`. */
|
|
230
|
-
uploadPart: (options: UploadAssetPartOptions) => Promise<Asset>;
|
|
231
|
-
createSignedUrl: (signedUrlOptions: CreateAssetSignedUrlOptions) => Promise<PostAssetSignedUrlResponse>;
|
|
232
|
-
move: (options: MoveAssetOptions) => Promise<Asset>;
|
|
233
|
-
retry: (options: RetryAssetOptions) => Promise<Asset>;
|
|
234
|
-
/** Waits like the real client, checking the mock's storage for a decision. */
|
|
235
|
-
waitForDecision: (options: WaitForAssetDecisionOptions) => Promise<Asset>;
|
|
236
|
-
deleteContent: (options: DeleteAssetContentOptions) => Promise<Asset>;
|
|
237
|
-
delete: (options: DeleteAssetOptions) => Promise<void>;
|
|
345
|
+
server?: MockCalmLensServerClient;
|
|
346
|
+
preset?: MockUploadPreset;
|
|
347
|
+
/** The server's `mockOptions.moderate` when the client creates its own server. */
|
|
348
|
+
moderate?: MockModerate;
|
|
238
349
|
};
|
|
239
|
-
/** Signs real upload tokens with the mock's API key, like the real client, without a request. */
|
|
240
|
-
get uploadTokens(): {
|
|
241
|
-
sign: (options: SignUploadTokenOptions) => Promise<SignedUploadToken>;
|
|
242
|
-
};
|
|
243
|
-
get folders(): {
|
|
244
|
-
list: () => Promise<Folder[]>;
|
|
245
|
-
retrieve: (options: FolderIdOptions) => Promise<Folder>;
|
|
246
|
-
create: (options: CreateFolderOptions) => Promise<Folder>;
|
|
247
|
-
update: (options: UpdateFolderOptions) => Promise<Folder>;
|
|
248
|
-
delete: (options: FolderIdOptions) => Promise<void>;
|
|
249
|
-
move: (options: MoveFolderOptions) => Promise<Folder>;
|
|
250
|
-
};
|
|
251
|
-
ensureLens(options: EnsureLensOptions): Promise<Lens>;
|
|
252
|
-
private ensureLensDefinition;
|
|
253
|
-
ensureLenses(options: EnsureLensesOptions): Promise<Lens[]>;
|
|
254
|
-
/** Replays the first result for a reused idempotency key, like the API. */
|
|
255
|
-
private withIdempotency;
|
|
256
|
-
private moderateAsset;
|
|
257
|
-
private createAsset;
|
|
258
|
-
/**
|
|
259
|
-
* Moves an asset to `outcome` like the pipeline would: a decision finishes processing, and
|
|
260
|
-
* finished processing removes content kept only temporarily (`keepContentAfterProcessing` off).
|
|
261
|
-
*/
|
|
262
|
-
private applyOutcome;
|
|
263
|
-
private resolveFolder;
|
|
264
|
-
private findOwnFolder;
|
|
265
|
-
private assertUniqueFolderName;
|
|
266
|
-
private getContentFormat;
|
|
267
|
-
private getSizeInBytes;
|
|
268
350
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
351
|
+
/**
|
|
352
|
+
* The real `CalmLensAppClient`, answered by the in-memory API of a `MockCalmLensServerClient`.
|
|
353
|
+
* The API applies `mockOptions.preset` to this client's uploads like CalmLens applies an upload
|
|
354
|
+
* preset: its token, content type and size rules with the API's error codes, and its visibility,
|
|
355
|
+
* folder, content retention and decision display. The client can check and continue only the
|
|
356
|
+
* uploads it made.
|
|
357
|
+
*/
|
|
358
|
+
export declare class MockCalmLensAppClient extends CalmLensAppClient {
|
|
359
|
+
#private;
|
|
360
|
+
/** The mock project the uploads are stored in. */
|
|
361
|
+
readonly server: MockCalmLensServerClient;
|
|
362
|
+
constructor(options: MockCalmLensAppClientOptions);
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* The JSON body of a webhook delivery for an event, such as one from `events.list`: the event in
|
|
366
|
+
* the same shape `events.list` returns it. Fields that are not part of that shape are left out.
|
|
367
|
+
*/
|
|
368
|
+
export declare const toWebhookEventPayload: (event: TypedEvent) => WebhookEventPayload;
|
|
273
369
|
/** `v1=<hex HMAC-SHA256 of "<timestamp>.<body>">`, the `x-calmlens-signature` header value. */
|
|
274
370
|
export declare const createWebhookSignatureHeader: (secret: string, timestamp: number | string, body: string) => Promise<string>;
|
|
275
371
|
/** Headers for one signed delivery of `body`, as CalmLens sends them. */
|
|
@@ -279,5 +375,4 @@ export declare const createWebhookHeaders: (options: {
|
|
|
279
375
|
deliveryId: string;
|
|
280
376
|
timestampSeconds?: number;
|
|
281
377
|
}) => Promise<Record<string, string>>;
|
|
282
|
-
|
|
283
|
-
export type { MockCalmLensCall, MockCalmLensOperation, MockCalmLensOperationOptions, MockCalmLensServerClientOptions, MockDatabaseStorage, MockEventInput, MockImageStorage, MockRequestFailure, MockStoredContent };
|
|
378
|
+
export { type MockAssetOutcome, type MockCalmLensAppClientOptions, type MockCalmLensCall, type MockCalmLensOperation, type MockCalmLensServerClientOptions, type MockDatabaseStorage, type MockEventInput, type MockFailureOptions, type MockImageStorage, type MockModerate, type MockModerationInput, type MockModerationTrigger, type MockRequestFailure, type MockReviewDecision, type MockStoredContent, type MockUploadPreset, signUploadTokenWithApiKey as signUploadToken };
|