@calmlens/sdk 0.0.0-stage → 0.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.
- package/README.md +554 -2
- package/bin/calmlens.js +1323 -0
- package/cjs/CalmLensTypes-DG_kHVqY.d.ts +3521 -0
- package/cjs/CalmLensUtils-0QaxbI3A.js +551 -0
- package/cjs/index.d.ts +2741 -0
- package/cjs/index.js +1206 -0
- package/cjs/package.json +3 -0
- package/cjs/testing.d.ts +149 -0
- package/cjs/testing.js +702 -0
- package/esm/CalmLensTypes-DG_kHVqY.d.ts +3521 -0
- package/esm/CalmLensUtils-BQEgxGWk.js +410 -0
- package/esm/index.d.ts +2741 -0
- package/esm/index.js +1196 -0
- package/esm/package.json +3 -0
- package/esm/testing.d.ts +149 -0
- package/esm/testing.js +696 -0
- package/package.json +88 -4
package/cjs/index.js
ADDED
|
@@ -0,0 +1,1206 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_CalmLensUtils = require("./CalmLensUtils-0QaxbI3A.js");
|
|
3
|
+
let zod = require("zod");
|
|
4
|
+
zod = require_CalmLensUtils.__toESM(zod);
|
|
5
|
+
require("zod/v4");
|
|
6
|
+
let api_def = require("api-def");
|
|
7
|
+
//#region ../shared/src/ModerationCategoryDefinitions.ts
|
|
8
|
+
const MODERATION_CATEGORY_DEFINITIONS = {
|
|
9
|
+
sexual: {
|
|
10
|
+
summary: "Sexual acts, explicit sexual anatomy, sexual services, sexual assault depictions and clearly erotic material.",
|
|
11
|
+
definition: "covers sexual acts, explicit sexual anatomy, sexual services and clearly erotic material. Descriptions of sexual assault can qualify without erotic intent. Fictional, illustrated and generated depictions can also qualify.",
|
|
12
|
+
exclusions: "Ordinary affection, swimwear, fitness, fashion, non-erotic medical diagrams and general sexual-health education do not qualify on their own. A person accepting money or wearing revealing clothing does not establish sexual content without a qualifying act, display or offer.",
|
|
13
|
+
docsHref: "/docs/guides/moderation-categories#sexual-content"
|
|
14
|
+
},
|
|
15
|
+
violence: {
|
|
16
|
+
summary: "Physical attacks, injury, death, threats against others, and planning or encouraging physical violence.",
|
|
17
|
+
definition: "covers physical attacks, bodily injury, death and threats against others. Accidental or medical injuries and natural death also count; an attacker or intent to harm is not required. It also includes planning, requesting, encouraging or praising physical violence. A depicted or described act can qualify in fiction or news reporting even when the author condemns it.",
|
|
18
|
+
exclusions: "Solely intentional self-injury or suicide belongs under self-harm. Property damage alone, figurative language, abstract discussion of violence, injury or death and merely possessing a weapon do not establish violence. Consensual sport or training without injury or abuse is excluded.",
|
|
19
|
+
docsHref: "/docs/guides/moderation-categories#violence"
|
|
20
|
+
},
|
|
21
|
+
"self-harm": {
|
|
22
|
+
summary: "Intentional self-injury, suicide, preparation, methods or encouragement; text also includes current or recurring self-harm thoughts.",
|
|
23
|
+
definition: "covers intentional self-injury, suicide, current self-harm risk, preparation, methods and encouragement. For text, it also includes current or recurring self-harm thoughts and an explicitly expressed desire to die. Asking for support does not cancel a separate disclosure of current risk or behavior.",
|
|
24
|
+
exclusions: "For images, require evidence of a self-directed act, preparation, harmful methods or encouragement. An injury or covered body does not establish that harm was self-inflicted. General sadness, neutral statistics, prevention, recovery and healed scars alone are excluded.",
|
|
25
|
+
docsHref: "/docs/guides/moderation-categories#self-harm"
|
|
26
|
+
},
|
|
27
|
+
harassment: {
|
|
28
|
+
summary: "Targeted personal abuse, humiliation, bullying or serious intimidation; ordinary criticism and neutral reporting are excluded.",
|
|
29
|
+
definition: "covers personal abuse, humiliation, bullying and serious intimidation directed at a person or identifiable group. The target can be named, implied or defined by an activity or affiliation. A protected identity is not required.",
|
|
30
|
+
exclusions: "Disagreement, ordinary criticism of conduct or competence, untargeted profanity and neutral reporting of abuse do not qualify without a separate personal attack. Criticism can still qualify when it also contains personal degradation.",
|
|
31
|
+
docsHref: "/docs/guides/moderation-categories#harassment-and-bullying"
|
|
32
|
+
},
|
|
33
|
+
hate: {
|
|
34
|
+
summary: "Identity-based abuse, dehumanization, discriminatory exclusion or threats against people because of protected characteristics.",
|
|
35
|
+
definition: "covers attacks on people because of race, ethnicity, nationality, religion, caste, sex, gender identity, sexual orientation or disability. It includes dehumanization, asserted inferiority, discriminatory exclusion, identity-based abuse and threats.",
|
|
36
|
+
exclusions: "Both the protected target and the identity-based attack must be supported. Identity mentions, cultural clothing, religious imagery, criticism of beliefs or an unrelated threat do not establish hate. Neutral reporting, condemnation and opposition to hate are excluded unless a separate attack is expressed or endorsed.",
|
|
37
|
+
docsHref: "/docs/guides/moderation-categories#hate-and-identity-abuse"
|
|
38
|
+
},
|
|
39
|
+
"criminal-activity": {
|
|
40
|
+
summary: "Planning, assistance, instructions, encouragement or facilitation of a concrete criminal or seriously dangerous act.",
|
|
41
|
+
definition: "covers planning, requests for assistance, instructions, encouragement or facilitation of a concrete criminal or seriously dangerous act. A request can qualify even when no act occurs and a later reply refuses it. Dangerous activity requires a concrete serious risk of physical harm.",
|
|
42
|
+
exclusions: "Neutral reporting, prevention, lawful safety advice, fiction without criminal assistance, and vague dangerous references do not qualify. Masks, computers, payment cards, detention or ordinary tools do not establish criminal facilitation by themselves. A clear visual demonstration of how to carry out a crime can qualify.",
|
|
43
|
+
docsHref: "/docs/guides/moderation-categories#criminal-and-dangerous-activity"
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region ../shared/src/ModerationPolicyDimensions.ts
|
|
48
|
+
const MODERATION_QUALIFIERS = [
|
|
49
|
+
"nudity",
|
|
50
|
+
"sexual-activity",
|
|
51
|
+
"explicit-sexual-language",
|
|
52
|
+
"sexual-solicitation",
|
|
53
|
+
"physical-attack",
|
|
54
|
+
"violent-threat",
|
|
55
|
+
"violent-preparation",
|
|
56
|
+
"violent-encouragement",
|
|
57
|
+
"injury",
|
|
58
|
+
"death",
|
|
59
|
+
"graphic",
|
|
60
|
+
"self-harm-thoughts",
|
|
61
|
+
"self-harm-preparation",
|
|
62
|
+
"self-harm-act",
|
|
63
|
+
"self-harm-methods",
|
|
64
|
+
"self-harm-encouragement",
|
|
65
|
+
"personal-abuse",
|
|
66
|
+
"targeted-intimidation",
|
|
67
|
+
"harassment-threat",
|
|
68
|
+
"sexual-harassment",
|
|
69
|
+
"harassment-encouragement",
|
|
70
|
+
"identity-abuse",
|
|
71
|
+
"dehumanization",
|
|
72
|
+
"identity-inferiority",
|
|
73
|
+
"discriminatory-exclusion",
|
|
74
|
+
"hate-threat",
|
|
75
|
+
"criminal-demonstration",
|
|
76
|
+
"criminal-preparation",
|
|
77
|
+
"criminal-request",
|
|
78
|
+
"criminal-instructions",
|
|
79
|
+
"criminal-promotion",
|
|
80
|
+
"historical",
|
|
81
|
+
"documentary",
|
|
82
|
+
"fictional",
|
|
83
|
+
"support-prevention"
|
|
84
|
+
];
|
|
85
|
+
const SHARED_QUALIFIERS = [
|
|
86
|
+
"historical",
|
|
87
|
+
"documentary",
|
|
88
|
+
"fictional",
|
|
89
|
+
"support-prevention"
|
|
90
|
+
];
|
|
91
|
+
[...SHARED_QUALIFIERS], [...SHARED_QUALIFIERS], [...SHARED_QUALIFIERS], [...SHARED_QUALIFIERS], [...SHARED_QUALIFIERS], [...SHARED_QUALIFIERS];
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region ../../node_modules/zod-meta/esm/index.js
|
|
94
|
+
const createMetaType = (type) => {
|
|
95
|
+
return Object.assign((value) => {
|
|
96
|
+
return {
|
|
97
|
+
type,
|
|
98
|
+
data: value !== null && value !== void 0 ? value : {}
|
|
99
|
+
};
|
|
100
|
+
}, type);
|
|
101
|
+
};
|
|
102
|
+
createMetaType({ id: "docPropertyInfo" });
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region ../shared/src/ZodUtils.ts
|
|
105
|
+
const SIZE_LIMITS = {
|
|
106
|
+
small: 64,
|
|
107
|
+
medium: 200,
|
|
108
|
+
large: 1500
|
|
109
|
+
};
|
|
110
|
+
const saneStringField = (options) => {
|
|
111
|
+
return zod.string().transform((value) => value.trim()).refine((value) => {
|
|
112
|
+
if ((options === null || options === void 0 ? void 0 : options.minWidth) && value.length < options.minWidth) return false;
|
|
113
|
+
return true;
|
|
114
|
+
}, "Not long enough").refine((value) => {
|
|
115
|
+
var _options$type;
|
|
116
|
+
const sizeLimit = SIZE_LIMITS[(_options$type = options === null || options === void 0 ? void 0 : options.type) !== null && _options$type !== void 0 ? _options$type : "medium"];
|
|
117
|
+
return typeof value === "string" && value.length < sizeLimit;
|
|
118
|
+
}, "Too long");
|
|
119
|
+
};
|
|
120
|
+
const CLASSIFICATION_INPUT_TYPE_SCHEMA = zod.enum(["text", "image"]);
|
|
121
|
+
const CLASSIFICATION_CATEGORIES = [
|
|
122
|
+
"sexual",
|
|
123
|
+
"violence",
|
|
124
|
+
"self-harm",
|
|
125
|
+
"harassment",
|
|
126
|
+
"hate",
|
|
127
|
+
"criminal-activity"
|
|
128
|
+
];
|
|
129
|
+
const CLASSIFICATION_CATEGORY_SCHEMA = zod.enum(CLASSIFICATION_CATEGORIES);
|
|
130
|
+
zod.object({
|
|
131
|
+
category: CLASSIFICATION_CATEGORY_SCHEMA,
|
|
132
|
+
displayName: saneStringField(),
|
|
133
|
+
description: saneStringField(),
|
|
134
|
+
supportedInputTypes: zod.array(CLASSIFICATION_INPUT_TYPE_SCHEMA).min(1)
|
|
135
|
+
});
|
|
136
|
+
MODERATION_CATEGORY_DEFINITIONS.sexual.summary, MODERATION_CATEGORY_DEFINITIONS.violence.summary, MODERATION_CATEGORY_DEFINITIONS["self-harm"].summary, MODERATION_CATEGORY_DEFINITIONS.harassment.summary, MODERATION_CATEGORY_DEFINITIONS.hate.summary, MODERATION_CATEGORY_DEFINITIONS["criminal-activity"].summary;
|
|
137
|
+
const LIKELIHOOD_SCHEMA = zod.enum([
|
|
138
|
+
"very-unlikely",
|
|
139
|
+
"unlikely",
|
|
140
|
+
"possible",
|
|
141
|
+
"likely",
|
|
142
|
+
"very-likely"
|
|
143
|
+
]);
|
|
144
|
+
const CLASSIFICATION_NOT_EVALUATED_REASON_SCHEMA = zod.enum(["not-supported", "unavailable"]);
|
|
145
|
+
const CLASSIFICATION_QUALIFIER_RESULTS_SCHEMA = zod.partialRecord(zod.enum(MODERATION_QUALIFIERS), zod.discriminatedUnion("status", [zod.object({
|
|
146
|
+
status: zod.literal("evaluated"),
|
|
147
|
+
score: zod.number().min(0).max(1),
|
|
148
|
+
scopeScore: zod.number().min(0).max(1).optional(),
|
|
149
|
+
likelihood: LIKELIHOOD_SCHEMA
|
|
150
|
+
}).strict().refine(({ score, scopeScore }) => scopeScore === void 0 || scopeScore <= score, {
|
|
151
|
+
message: "Only confidence cannot exceed Any confidence",
|
|
152
|
+
path: ["scopeScore"]
|
|
153
|
+
}), zod.object({
|
|
154
|
+
status: zod.literal("not-evaluated"),
|
|
155
|
+
reason: CLASSIFICATION_NOT_EVALUATED_REASON_SCHEMA
|
|
156
|
+
}).strict()]));
|
|
157
|
+
const CLASSIFICATION_CATEGORY_REPORT_SCHEMA = zod.discriminatedUnion("status", [
|
|
158
|
+
zod.object({
|
|
159
|
+
status: zod.literal("evaluated"),
|
|
160
|
+
likelihood: LIKELIHOOD_SCHEMA,
|
|
161
|
+
score: zod.number().min(0).max(1),
|
|
162
|
+
qualifiers: CLASSIFICATION_QUALIFIER_RESULTS_SCHEMA.optional()
|
|
163
|
+
}).strict(),
|
|
164
|
+
zod.object({
|
|
165
|
+
status: zod.literal("partial"),
|
|
166
|
+
likelihood: LIKELIHOOD_SCHEMA,
|
|
167
|
+
score: zod.number().min(0).max(1),
|
|
168
|
+
qualifiers: CLASSIFICATION_QUALIFIER_RESULTS_SCHEMA.optional()
|
|
169
|
+
}).strict(),
|
|
170
|
+
zod.object({
|
|
171
|
+
status: zod.literal("not-evaluated"),
|
|
172
|
+
reason: CLASSIFICATION_NOT_EVALUATED_REASON_SCHEMA,
|
|
173
|
+
qualifiers: CLASSIFICATION_QUALIFIER_RESULTS_SCHEMA.optional()
|
|
174
|
+
}).strict()
|
|
175
|
+
]);
|
|
176
|
+
const CATEGORIES_SCHEMA = zod.object({
|
|
177
|
+
sexual: CLASSIFICATION_CATEGORY_REPORT_SCHEMA,
|
|
178
|
+
violence: CLASSIFICATION_CATEGORY_REPORT_SCHEMA,
|
|
179
|
+
"self-harm": CLASSIFICATION_CATEGORY_REPORT_SCHEMA,
|
|
180
|
+
harassment: CLASSIFICATION_CATEGORY_REPORT_SCHEMA,
|
|
181
|
+
hate: CLASSIFICATION_CATEGORY_REPORT_SCHEMA,
|
|
182
|
+
"criminal-activity": CLASSIFICATION_CATEGORY_REPORT_SCHEMA
|
|
183
|
+
}).strict();
|
|
184
|
+
const CLASSIFICATION_LABEL_SCHEMA = zod.object({
|
|
185
|
+
description: saneStringField(),
|
|
186
|
+
score: zod.number(),
|
|
187
|
+
topicalityScore: zod.number().nullish(),
|
|
188
|
+
likelihood: LIKELIHOOD_SCHEMA,
|
|
189
|
+
knowledgeBaseId: saneStringField().nullish()
|
|
190
|
+
});
|
|
191
|
+
zod.object({
|
|
192
|
+
processedAt: zod.number(),
|
|
193
|
+
categories: CATEGORIES_SCHEMA,
|
|
194
|
+
flagged: zod.boolean(),
|
|
195
|
+
score: zod.number(),
|
|
196
|
+
notes: saneStringField().nullish(),
|
|
197
|
+
media: zod.object({
|
|
198
|
+
durationSeconds: zod.number().positive(),
|
|
199
|
+
frameIntervalSeconds: zod.number().positive().optional(),
|
|
200
|
+
sampledFrames: zod.number().int().nonnegative(),
|
|
201
|
+
audioTranscribed: zod.boolean(),
|
|
202
|
+
segments: zod.array(zod.object({
|
|
203
|
+
source: zod.enum([
|
|
204
|
+
"frame",
|
|
205
|
+
"speech",
|
|
206
|
+
"frame-text"
|
|
207
|
+
]),
|
|
208
|
+
startSeconds: zod.number().nonnegative(),
|
|
209
|
+
endSeconds: zod.number().nonnegative(),
|
|
210
|
+
categories: CATEGORIES_SCHEMA
|
|
211
|
+
}).strict())
|
|
212
|
+
}).strict().optional(),
|
|
213
|
+
labels: zod.array(CLASSIFICATION_LABEL_SCHEMA).nullish()
|
|
214
|
+
}).strict();
|
|
215
|
+
//#endregion
|
|
216
|
+
//#region ../shared/src/MediaTestTriggers.ts
|
|
217
|
+
const MEDIA_TEST_SIGNALS = [...CLASSIFICATION_CATEGORIES, "violence.graphic"];
|
|
218
|
+
const HEX_WORDS = [
|
|
219
|
+
"zero",
|
|
220
|
+
"one",
|
|
221
|
+
"two",
|
|
222
|
+
"three",
|
|
223
|
+
"four",
|
|
224
|
+
"five",
|
|
225
|
+
"six",
|
|
226
|
+
"seven",
|
|
227
|
+
"eight",
|
|
228
|
+
"nine",
|
|
229
|
+
"alpha",
|
|
230
|
+
"bravo",
|
|
231
|
+
"charlie",
|
|
232
|
+
"delta",
|
|
233
|
+
"echo",
|
|
234
|
+
"foxtrot"
|
|
235
|
+
];
|
|
236
|
+
/** Read this aloud, or render it as large, high-contrast text in a video frame. */
|
|
237
|
+
function generateMediaTestCode(signal, projectId) {
|
|
238
|
+
if (!MEDIA_TEST_SIGNALS.includes(signal)) throw new Error("Unsupported media test signal");
|
|
239
|
+
const suffix = projectId.slice(-8).toLowerCase();
|
|
240
|
+
if (!/^[a-f0-9]{8}$/.test(suffix)) throw new Error("Expected a project ID with an eight-character hexadecimal suffix");
|
|
241
|
+
return `Calm Lens test ${[...suffix].map((character) => HEX_WORDS[Number.parseInt(character, 16)]).join(" ")} ${signal.replace(/[.-]/g, " ")} end test`;
|
|
242
|
+
}
|
|
243
|
+
//#endregion
|
|
244
|
+
//#region src/client/CalmLensWebhooks.ts
|
|
245
|
+
const WEBHOOK_DELIVERY_HEADER = "x-calmlens-delivery";
|
|
246
|
+
const WEBHOOK_TIMESTAMP_HEADER = "x-calmlens-timestamp";
|
|
247
|
+
const WEBHOOK_SIGNATURE_HEADER = "x-calmlens-signature";
|
|
248
|
+
/** Deliveries whose timestamp is further than this from the receiver's clock are rejected. */
|
|
249
|
+
const WEBHOOK_SIGNATURE_TOLERANCE_SECONDS = 300;
|
|
250
|
+
const encoder = new TextEncoder();
|
|
251
|
+
const hmacSha256Hex = function() {
|
|
252
|
+
var _ref = require_CalmLensUtils._asyncToGenerator(function* (secret, message) {
|
|
253
|
+
const key = yield crypto.subtle.importKey("raw", encoder.encode(secret), {
|
|
254
|
+
name: "HMAC",
|
|
255
|
+
hash: "SHA-256"
|
|
256
|
+
}, false, ["sign"]);
|
|
257
|
+
const signature = yield crypto.subtle.sign("HMAC", key, encoder.encode(message));
|
|
258
|
+
return Array.from(new Uint8Array(signature), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
259
|
+
});
|
|
260
|
+
return function hmacSha256Hex(_x, _x2) {
|
|
261
|
+
return _ref.apply(this, arguments);
|
|
262
|
+
};
|
|
263
|
+
}();
|
|
264
|
+
/** Constant-time comparison of two strings of the same length. */
|
|
265
|
+
const timingSafeEqual = (a, b) => {
|
|
266
|
+
if (a.length !== b.length) return false;
|
|
267
|
+
let diff = 0;
|
|
268
|
+
for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
269
|
+
return diff === 0;
|
|
270
|
+
};
|
|
271
|
+
/** `v1=<hex HMAC-SHA256 of "<timestamp>.<body>">`, the `x-calmlens-signature` header value. */
|
|
272
|
+
const createWebhookSignatureHeader = function() {
|
|
273
|
+
var _ref2 = require_CalmLensUtils._asyncToGenerator(function* (secret, timestamp, body) {
|
|
274
|
+
return `v1=${yield hmacSha256Hex(secret, `${timestamp}.${body}`)}`;
|
|
275
|
+
});
|
|
276
|
+
return function createWebhookSignatureHeader(_x3, _x4, _x5) {
|
|
277
|
+
return _ref2.apply(this, arguments);
|
|
278
|
+
};
|
|
279
|
+
}();
|
|
280
|
+
(function() {
|
|
281
|
+
var _ref3 = require_CalmLensUtils._asyncToGenerator(function* (options) {
|
|
282
|
+
var _options$timestampSec;
|
|
283
|
+
const timestamp = (_options$timestampSec = options.timestampSeconds) !== null && _options$timestampSec !== void 0 ? _options$timestampSec : Math.floor(Date.now() / 1e3);
|
|
284
|
+
return {
|
|
285
|
+
"content-type": "application/json",
|
|
286
|
+
[WEBHOOK_DELIVERY_HEADER]: options.deliveryId,
|
|
287
|
+
[WEBHOOK_TIMESTAMP_HEADER]: String(timestamp),
|
|
288
|
+
[WEBHOOK_SIGNATURE_HEADER]: yield createWebhookSignatureHeader(options.secret, timestamp, options.body)
|
|
289
|
+
};
|
|
290
|
+
});
|
|
291
|
+
return function createWebhookHeaders(_x6) {
|
|
292
|
+
return _ref3.apply(this, arguments);
|
|
293
|
+
};
|
|
294
|
+
})();
|
|
295
|
+
/**
|
|
296
|
+
* Verifies a webhook delivery: `x-calmlens-signature` must contain a `v1=` HMAC-SHA256 of
|
|
297
|
+
* `"<x-calmlens-timestamp>.<raw body>"`, and the timestamp must be within `toleranceSeconds`
|
|
298
|
+
* (default 300) of now. Returns `false` for anything missing or malformed.
|
|
299
|
+
*/
|
|
300
|
+
function verifyWebhookSignature(_x7) {
|
|
301
|
+
return _verifyWebhookSignature.apply(this, arguments);
|
|
302
|
+
}
|
|
303
|
+
function _verifyWebhookSignature() {
|
|
304
|
+
_verifyWebhookSignature = require_CalmLensUtils._asyncToGenerator(function* ({ payload, signature, timestamp, secret, toleranceSeconds = 300, now }) {
|
|
305
|
+
if (!secret || !signature || timestamp === null || timestamp === void 0) return false;
|
|
306
|
+
const timestampText = String(timestamp).trim();
|
|
307
|
+
if (!/^\d+$/.test(timestampText)) return false;
|
|
308
|
+
const nowMs = now === void 0 ? Date.now() : now instanceof Date ? now.getTime() : now;
|
|
309
|
+
if (Math.abs(Math.floor(nowMs / 1e3) - Number(timestampText)) > toleranceSeconds) return false;
|
|
310
|
+
const candidates = signature.split(",").map((part) => part.trim()).filter((part) => part.startsWith("v1=")).map((part) => part.slice(3).toLowerCase());
|
|
311
|
+
if (candidates.length === 0) return false;
|
|
312
|
+
const body = typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
313
|
+
const expected = yield hmacSha256Hex(secret, `${timestampText}.${body}`);
|
|
314
|
+
let matched = false;
|
|
315
|
+
for (const candidate of candidates) if (timingSafeEqual(expected, candidate)) matched = true;
|
|
316
|
+
return matched;
|
|
317
|
+
});
|
|
318
|
+
return _verifyWebhookSignature.apply(this, arguments);
|
|
319
|
+
}
|
|
320
|
+
//#endregion
|
|
321
|
+
//#region src/client/CalmLensClient.ts
|
|
322
|
+
const _excluded = ["uint8Array"];
|
|
323
|
+
const _excluded2 = ["buffer"];
|
|
324
|
+
const _excluded3 = ["assetIdentifier"];
|
|
325
|
+
const _excluded4 = ["assetIdentifier", "init"];
|
|
326
|
+
const _excluded5 = ["assetId"];
|
|
327
|
+
const _excluded6 = ["assetId"];
|
|
328
|
+
const _excluded7 = ["assetId"];
|
|
329
|
+
const _excluded8 = ["folderId"];
|
|
330
|
+
const toBlobPartBytes = (value) => {
|
|
331
|
+
if (value instanceof ArrayBuffer) return new Uint8Array(value);
|
|
332
|
+
return Uint8Array.from(value);
|
|
333
|
+
};
|
|
334
|
+
const normalizePayloadForRequest = (payload) => {
|
|
335
|
+
if ("base64" in payload && payload.base64) return require_CalmLensUtils._objectSpread2(require_CalmLensUtils._objectSpread2({}, payload), {}, { base64: require_CalmLensUtils.getRawBase64(payload.base64) });
|
|
336
|
+
if ("uint8Array" in payload && payload.uint8Array) {
|
|
337
|
+
const { uint8Array } = payload, rest = require_CalmLensUtils._objectWithoutProperties(payload, _excluded);
|
|
338
|
+
return require_CalmLensUtils._objectSpread2(require_CalmLensUtils._objectSpread2({}, rest), {}, { data: new Blob([toBlobPartBytes(uint8Array)]) });
|
|
339
|
+
}
|
|
340
|
+
if ("buffer" in payload && payload.buffer) {
|
|
341
|
+
const { buffer } = payload, rest = require_CalmLensUtils._objectWithoutProperties(payload, _excluded2);
|
|
342
|
+
return require_CalmLensUtils._objectSpread2(require_CalmLensUtils._objectSpread2({}, rest), {}, { data: new Blob([toBlobPartBytes(buffer)]) });
|
|
343
|
+
}
|
|
344
|
+
return payload;
|
|
345
|
+
};
|
|
346
|
+
const normalizeMetadataForMultipart = (metadata) => {
|
|
347
|
+
if (!Array.isArray(metadata)) return metadata;
|
|
348
|
+
return Object.fromEntries(metadata.map((item, index) => [index, item]));
|
|
349
|
+
};
|
|
350
|
+
const normalizeMetadataOptionsForRequest = (options) => {
|
|
351
|
+
if (!("metadata" in options) || !Array.isArray(options.metadata)) return options;
|
|
352
|
+
return require_CalmLensUtils._objectSpread2(require_CalmLensUtils._objectSpread2({}, options), {}, { metadata: normalizeMetadataForMultipart(options.metadata) });
|
|
353
|
+
};
|
|
354
|
+
const normalizeAssetOptionsForRequest = (options) => {
|
|
355
|
+
const normalizedOptions = normalizeMetadataOptionsForRequest(options);
|
|
356
|
+
if ("part" in normalizedOptions) return require_CalmLensUtils._objectSpread2(require_CalmLensUtils._objectSpread2({}, normalizedOptions), {}, { part: normalizePayloadForRequest(normalizedOptions.part) });
|
|
357
|
+
if ("content" in normalizedOptions && !("plainText" in normalizedOptions.content)) return require_CalmLensUtils._objectSpread2(require_CalmLensUtils._objectSpread2({}, normalizedOptions), {}, { content: normalizePayloadForRequest(normalizedOptions.content) });
|
|
358
|
+
return normalizedOptions;
|
|
359
|
+
};
|
|
360
|
+
const toRawUploadBody = (payload) => {
|
|
361
|
+
const data = require_CalmLensUtils.assetToData(normalizePayloadForRequest(payload));
|
|
362
|
+
if (data instanceof Response) {
|
|
363
|
+
if (!data.body) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Response upload data must have a body" });
|
|
364
|
+
return data.body;
|
|
365
|
+
}
|
|
366
|
+
if (data instanceof ArrayBuffer || data instanceof Blob) return data;
|
|
367
|
+
if ("getReader" in data) return data;
|
|
368
|
+
return new Blob([toBlobPartBytes(data)]);
|
|
369
|
+
};
|
|
370
|
+
const setOptionalQueryValue = (params, key, value) => {
|
|
371
|
+
if (value !== void 0 && value !== null) params.set(key, typeof value === "string" ? value : JSON.stringify(value));
|
|
372
|
+
};
|
|
373
|
+
const assertValidUploadMimeType = (mimeType) => {
|
|
374
|
+
if (require_CalmLensUtils.isRejectedUploadMimeType(mimeType)) throw require_CalmLensUtils.calmLensError(require_CalmLensUtils.PUBLIC_ERROR_CODES.INVALID_UPLOAD_MIME_TYPE, {
|
|
375
|
+
message: require_CalmLensUtils.getRejectedUploadMimeTypeError(mimeType),
|
|
376
|
+
details: { mimeType }
|
|
377
|
+
});
|
|
378
|
+
};
|
|
379
|
+
const isImageMimeType = (mimeType) => mimeType.toLowerCase().startsWith("image/");
|
|
380
|
+
const prepareSubmitAssetOptions = (options) => {
|
|
381
|
+
if (!("content" in options) && !("url" in options) && !("part" in options)) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Either file content, URL, or multipart part is required" });
|
|
382
|
+
if (!options.name) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Asset name is required" });
|
|
383
|
+
if (!("part" in options) && "isFinal" in options) throw require_CalmLensUtils.calmLensError(require_CalmLensUtils.PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "isFinal is only valid for multipart uploads" });
|
|
384
|
+
if ("part" in options && options.part.partNumber && options.part.partNumber > 1) throw require_CalmLensUtils.calmLensError(require_CalmLensUtils.PUBLIC_ERROR_CODES.USE_UPLOAD_PART);
|
|
385
|
+
if ("content" in options) {
|
|
386
|
+
assertValidUploadMimeType(options.content.type);
|
|
387
|
+
if (!("plainText" in options.content)) {
|
|
388
|
+
const validation = require_CalmLensUtils.validateAssetPayload(options.content);
|
|
389
|
+
if (!validation.ok) throw require_CalmLensUtils.calmLensError(require_CalmLensUtils.PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: validation.error });
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if ("part" in options) {
|
|
393
|
+
var _options$part$sizeInB;
|
|
394
|
+
assertValidUploadMimeType(options.part.type);
|
|
395
|
+
const partSizeInBytes = (_options$part$sizeInB = options.part.sizeInBytes) !== null && _options$part$sizeInB !== void 0 ? _options$part$sizeInB : require_CalmLensUtils.getAssetPayloadByteLength(options.part);
|
|
396
|
+
if (isImageMimeType(options.part.type) && partSizeInBytes !== void 0) {
|
|
397
|
+
if (partSizeInBytes > require_CalmLensUtils.MAX_IMAGE_UPLOAD_BYTES) throw require_CalmLensUtils.calmLensError(require_CalmLensUtils.PUBLIC_ERROR_CODES.MULTIPART_IMAGE_TOO_LARGE);
|
|
398
|
+
if (options.part.isFinal && partSizeInBytes < require_CalmLensUtils.MIN_MULTIPART_IMAGE_UPLOAD_BYTES) throw require_CalmLensUtils.calmLensError(require_CalmLensUtils.PUBLIC_ERROR_CODES.MULTIPART_IMAGE_TOO_SMALL);
|
|
399
|
+
}
|
|
400
|
+
const validation = require_CalmLensUtils.validateAssetPayload(options.part, {
|
|
401
|
+
multipart: true,
|
|
402
|
+
isFinal: options.part.isFinal
|
|
403
|
+
});
|
|
404
|
+
if (!validation.ok) throw require_CalmLensUtils.calmLensError(require_CalmLensUtils.PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: validation.error });
|
|
405
|
+
}
|
|
406
|
+
return options;
|
|
407
|
+
};
|
|
408
|
+
const appendCdnSelector = (url, options) => {
|
|
409
|
+
if (options.lens && options.transform) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Specify either a lens or a transform, not both" });
|
|
410
|
+
if (options.lens) return `${url}/@${encodeURIComponent(options.lens)}`;
|
|
411
|
+
if (!options.transform) return url;
|
|
412
|
+
return `${url}/${encodeURI(options.transform.replace(/^\/+/, ""))}`;
|
|
413
|
+
};
|
|
414
|
+
const getEnsureLensCacheKey = (options) => {
|
|
415
|
+
var _options$description, _options$transforms;
|
|
416
|
+
return require_CalmLensUtils.stringifyJsonCanonical({
|
|
417
|
+
identifier: options.identifier,
|
|
418
|
+
name: options.name,
|
|
419
|
+
description: (_options$description = options.description) !== null && _options$description !== void 0 ? _options$description : null,
|
|
420
|
+
type: options.type,
|
|
421
|
+
active: options.active,
|
|
422
|
+
transforms: (_options$transforms = options.transforms) !== null && _options$transforms !== void 0 ? _options$transforms : null,
|
|
423
|
+
version: options.version
|
|
424
|
+
});
|
|
425
|
+
};
|
|
426
|
+
const withApiKeyHeader = (init, apiKey) => {
|
|
427
|
+
const headers = new Headers(init === null || init === void 0 ? void 0 : init.headers);
|
|
428
|
+
headers.set("X-Api-Key", apiKey);
|
|
429
|
+
return require_CalmLensUtils._objectSpread2(require_CalmLensUtils._objectSpread2({}, init), {}, {
|
|
430
|
+
redirect: "error",
|
|
431
|
+
headers: Object.fromEntries(headers.entries())
|
|
432
|
+
});
|
|
433
|
+
};
|
|
434
|
+
const requestSignal = (options, signal) => {
|
|
435
|
+
var _options$timeoutMs;
|
|
436
|
+
const signals = [
|
|
437
|
+
options.signal,
|
|
438
|
+
signal,
|
|
439
|
+
AbortSignal.timeout((_options$timeoutMs = options.timeoutMs) !== null && _options$timeoutMs !== void 0 ? _options$timeoutMs : 12e4)
|
|
440
|
+
].filter((value) => value != null);
|
|
441
|
+
return AbortSignal.any(signals);
|
|
442
|
+
};
|
|
443
|
+
const safeFetch = (fetchImpl, options) => function() {
|
|
444
|
+
var _ref = require_CalmLensUtils._asyncToGenerator(function* (input, init) {
|
|
445
|
+
var _init$signal;
|
|
446
|
+
const signal = requestSignal(options, (_init$signal = init === null || init === void 0 ? void 0 : init.signal) !== null && _init$signal !== void 0 ? _init$signal : input instanceof Request ? input.signal : void 0);
|
|
447
|
+
try {
|
|
448
|
+
signal.throwIfAborted();
|
|
449
|
+
return yield fetchImpl(input, require_CalmLensUtils._objectSpread2(require_CalmLensUtils._objectSpread2({}, init), {}, {
|
|
450
|
+
redirect: "error",
|
|
451
|
+
signal
|
|
452
|
+
}));
|
|
453
|
+
} catch (cause) {
|
|
454
|
+
var _signal$reason;
|
|
455
|
+
throw require_CalmLensUtils.calmLensError({ id: signal.aborted ? ((_signal$reason = signal.reason) === null || _signal$reason === void 0 ? void 0 : _signal$reason.name) === "TimeoutError" ? "sdk/timeout" : "sdk/cancelled" : "sdk/transport-error" }, {
|
|
456
|
+
message: signal.aborted ? "Request aborted" : "Request failed",
|
|
457
|
+
cause
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
return function(_x, _x2) {
|
|
462
|
+
return _ref.apply(this, arguments);
|
|
463
|
+
};
|
|
464
|
+
}();
|
|
465
|
+
const createApi = (options) => {
|
|
466
|
+
return new api_def.Api({
|
|
467
|
+
name: "Calm Lens",
|
|
468
|
+
baseUrl: options.baseUrl,
|
|
469
|
+
middleware: [
|
|
470
|
+
(0, api_def.RequestCoalescingMiddleware)(),
|
|
471
|
+
{ beforeSend: (context) => {
|
|
472
|
+
context.updateHeaders({ "X-Api-Key": options.apiKey });
|
|
473
|
+
} },
|
|
474
|
+
{ [api_def.RequestEvent.ERROR]: (context) => {
|
|
475
|
+
if (context.error) throw normalizeApiError(context.error);
|
|
476
|
+
} }
|
|
477
|
+
],
|
|
478
|
+
requestBackend: options.requestBackend ? Object.assign(Object.create(options.requestBackend), "fetch" in options.requestBackend && typeof options.requestBackend.fetch === "function" ? { fetch: safeFetch(options.requestBackend.fetch, options) } : {}) : new api_def.FetchRequestBackend(safeFetch(globalThis.fetch, options))
|
|
479
|
+
});
|
|
480
|
+
};
|
|
481
|
+
const isApiErrorPayload = (value) => {
|
|
482
|
+
return !!value && typeof value === "object" && typeof value.code === "string";
|
|
483
|
+
};
|
|
484
|
+
const normalizeApiError = (error) => {
|
|
485
|
+
let cause = error;
|
|
486
|
+
const seen = /* @__PURE__ */ new Set();
|
|
487
|
+
while (cause instanceof Error && !seen.has(cause)) {
|
|
488
|
+
seen.add(cause);
|
|
489
|
+
if (cause instanceof require_CalmLensUtils.CalmLensError) return cause;
|
|
490
|
+
if (cause.name === "AbortError" || cause.name === "TimeoutError") return require_CalmLensUtils.calmLensError({ id: cause.name === "TimeoutError" ? "sdk/timeout" : "sdk/cancelled" }, {
|
|
491
|
+
message: "Request aborted",
|
|
492
|
+
cause
|
|
493
|
+
});
|
|
494
|
+
cause = cause.cause;
|
|
495
|
+
}
|
|
496
|
+
const response = error instanceof Error ? (0, api_def.getErrorResponse)(error) : void 0;
|
|
497
|
+
if (error instanceof Error && (0, api_def.isRequestError)(error) && isApiErrorPayload(response === null || response === void 0 ? void 0 : response.data)) {
|
|
498
|
+
const { code, message, details, traceId } = response.data;
|
|
499
|
+
return require_CalmLensUtils.calmLensError({
|
|
500
|
+
id: code,
|
|
501
|
+
defaultMessage: message
|
|
502
|
+
}, {
|
|
503
|
+
message,
|
|
504
|
+
status: response === null || response === void 0 ? void 0 : response.status,
|
|
505
|
+
cause: error,
|
|
506
|
+
details: require_CalmLensUtils._objectSpread2(require_CalmLensUtils._objectSpread2({}, details), {}, {
|
|
507
|
+
traceId,
|
|
508
|
+
network: true
|
|
509
|
+
})
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
if (error instanceof require_CalmLensUtils.CalmLensError) return error;
|
|
513
|
+
return require_CalmLensUtils.calmLensError({ id: response ? response.ok ? "sdk/invalid-response" : "sdk/http-error" : "sdk/transport-error" }, {
|
|
514
|
+
message: response ? `HTTP ${response.status}` : error.message,
|
|
515
|
+
status: response === null || response === void 0 ? void 0 : response.status,
|
|
516
|
+
cause: error
|
|
517
|
+
});
|
|
518
|
+
};
|
|
519
|
+
const createEndpoints = (api) => {
|
|
520
|
+
const getFolders = api.endpoint().paramsOf().responseOf().build({
|
|
521
|
+
id: "getFolders",
|
|
522
|
+
method: "get",
|
|
523
|
+
path: "/projects/:projectId/folders"
|
|
524
|
+
});
|
|
525
|
+
const getFolder = api.endpoint().paramsOf().responseOf().build({
|
|
526
|
+
id: "getFolder",
|
|
527
|
+
method: "get",
|
|
528
|
+
path: "/folders/:folderId"
|
|
529
|
+
});
|
|
530
|
+
const postFolder = api.endpoint().paramsOf().bodyOf().responseOf().build({
|
|
531
|
+
id: "postFolder",
|
|
532
|
+
method: "post",
|
|
533
|
+
path: "/projects/:projectId/folders"
|
|
534
|
+
});
|
|
535
|
+
const patchFolder = api.endpoint().paramsOf().bodyOf().responseOf().build({
|
|
536
|
+
id: "patchFolder",
|
|
537
|
+
method: "patch",
|
|
538
|
+
path: "/folders/:folderId"
|
|
539
|
+
});
|
|
540
|
+
const deleteFolder = api.endpoint().paramsOf().responseOf().build({
|
|
541
|
+
id: "deleteFolder",
|
|
542
|
+
method: "delete",
|
|
543
|
+
path: "/folders/:folderId"
|
|
544
|
+
});
|
|
545
|
+
const moveFolder = api.endpoint().paramsOf().bodyOf().responseOf().build({
|
|
546
|
+
id: "moveFolder",
|
|
547
|
+
method: "post",
|
|
548
|
+
path: "/folders/:folderId/move"
|
|
549
|
+
});
|
|
550
|
+
const getAssetsPage = api.endpoint().queryOf().paramsOf().responseOf().build({
|
|
551
|
+
id: "getAssetsPage",
|
|
552
|
+
method: "get",
|
|
553
|
+
path: "/projects/:projectId/assets/page"
|
|
554
|
+
});
|
|
555
|
+
const getAsset = api.endpoint().paramsOf().responseOf().build({
|
|
556
|
+
id: "getAsset",
|
|
557
|
+
method: "get",
|
|
558
|
+
path: "/assets/:assetId"
|
|
559
|
+
});
|
|
560
|
+
const getAssetChildren = api.endpoint().paramsOf().queryOf().responseOf().build({
|
|
561
|
+
id: "getAssetChildren",
|
|
562
|
+
method: "get",
|
|
563
|
+
path: "/assets/:assetId/children"
|
|
564
|
+
});
|
|
565
|
+
const patchAsset = api.endpoint().paramsOf().bodyOf().responseOf().build({
|
|
566
|
+
id: "patchAsset",
|
|
567
|
+
method: "patch",
|
|
568
|
+
path: "/assets/:assetId"
|
|
569
|
+
});
|
|
570
|
+
const postUploadAsset = api.endpoint().bodyOf({ encoding: "multipart/form-data" }).paramsOf().queryOf().responseOf().build({
|
|
571
|
+
id: "postUploadAsset",
|
|
572
|
+
method: "post",
|
|
573
|
+
path: "/projects/:projectId/assets"
|
|
574
|
+
});
|
|
575
|
+
const postAssetSignedUrl = api.endpoint().bodyOf().paramsOf().responseOf().build({
|
|
576
|
+
id: "postAssetSignedUrl",
|
|
577
|
+
method: "post",
|
|
578
|
+
path: "/assets/:assetId/signed-url"
|
|
579
|
+
});
|
|
580
|
+
const postAssetPart = api.endpoint().bodyOf({ encoding: "multipart/form-data" }).paramsOf().queryOf().responseOf().build({
|
|
581
|
+
id: "postAssetPart",
|
|
582
|
+
method: "post",
|
|
583
|
+
path: "/assets/:assetId/part"
|
|
584
|
+
});
|
|
585
|
+
const moveAsset = api.endpoint().paramsOf().bodyOf().responseOf().build({
|
|
586
|
+
id: "moveAsset",
|
|
587
|
+
method: "post",
|
|
588
|
+
path: "/assets/:assetId/move"
|
|
589
|
+
});
|
|
590
|
+
const retryAsset = api.endpoint().paramsOf().responseOf().build({
|
|
591
|
+
id: "retryAsset",
|
|
592
|
+
method: "post",
|
|
593
|
+
path: "/assets/:assetId/retry"
|
|
594
|
+
});
|
|
595
|
+
const getEvents = api.endpoint().paramsOf().queryOf().responseOf().build({
|
|
596
|
+
id: "getEvents",
|
|
597
|
+
method: "get",
|
|
598
|
+
path: "/projects/:projectId/events"
|
|
599
|
+
});
|
|
600
|
+
return {
|
|
601
|
+
getFolders,
|
|
602
|
+
getFolder,
|
|
603
|
+
postFolder,
|
|
604
|
+
patchFolder,
|
|
605
|
+
deleteFolder,
|
|
606
|
+
moveFolder,
|
|
607
|
+
getAssetsPage,
|
|
608
|
+
getAsset,
|
|
609
|
+
getAssetChildren,
|
|
610
|
+
patchAsset,
|
|
611
|
+
postUploadAsset,
|
|
612
|
+
postAssetSignedUrl,
|
|
613
|
+
postAssetPart,
|
|
614
|
+
moveAsset,
|
|
615
|
+
retryAsset,
|
|
616
|
+
ensureLens: api.endpoint().bodyOf().paramsOf().responseOf().build({
|
|
617
|
+
id: "ensureLens",
|
|
618
|
+
method: "put",
|
|
619
|
+
path: "/lenses/:lensIdentifier"
|
|
620
|
+
}),
|
|
621
|
+
ensureLenses: api.endpoint().bodyOf().paramsOf().responseOf().build({
|
|
622
|
+
id: "ensureLenses",
|
|
623
|
+
method: "put",
|
|
624
|
+
path: "/projects/:projectId/lenses"
|
|
625
|
+
}),
|
|
626
|
+
getEvents
|
|
627
|
+
};
|
|
628
|
+
};
|
|
629
|
+
var CalmLensClient = class CalmLensClient {
|
|
630
|
+
/**
|
|
631
|
+
* Verifies that a webhook delivery came from CalmLens: checks the `v1=` HMAC-SHA256 in
|
|
632
|
+
* `x-calmlens-signature` over `"<x-calmlens-timestamp>.<raw body>"` and rejects timestamps
|
|
633
|
+
* more than `toleranceSeconds` (default 300) from now, which stops replayed deliveries.
|
|
634
|
+
*
|
|
635
|
+
* @param options.payload - The raw request body, exactly as received (verify before parsing)
|
|
636
|
+
* @param options.signature - The 'x-calmlens-signature' header value
|
|
637
|
+
* @param options.timestamp - The 'x-calmlens-timestamp' header value
|
|
638
|
+
* @param options.secret - The connector's signing secret
|
|
639
|
+
* @param options.toleranceSeconds - Allowed clock distance in seconds (default 300)
|
|
640
|
+
* @param options.now - Override the current time (Date or epoch milliseconds), for tests
|
|
641
|
+
* @returns Promise<boolean> - True if the signature is valid and fresh, false otherwise
|
|
642
|
+
*
|
|
643
|
+
* @example
|
|
644
|
+
* ```javascript
|
|
645
|
+
* // In your webhook handler (e.g. a Fetch API Request)
|
|
646
|
+
* const payload = await request.text();
|
|
647
|
+
* const isValid = await CalmLensClient.verifyWebhookSignature({
|
|
648
|
+
* payload,
|
|
649
|
+
* signature: request.headers.get('x-calmlens-signature'),
|
|
650
|
+
* timestamp: request.headers.get('x-calmlens-timestamp'),
|
|
651
|
+
* secret: WEBHOOK_SECRET,
|
|
652
|
+
* });
|
|
653
|
+
*
|
|
654
|
+
* if (!isValid) {
|
|
655
|
+
* return new Response('Unauthorized', { status: 401 });
|
|
656
|
+
* }
|
|
657
|
+
* const event = JSON.parse(payload); // { id, type, createdAt, projectId, data }
|
|
658
|
+
* ```
|
|
659
|
+
*/
|
|
660
|
+
static verifyWebhookSignature(options) {
|
|
661
|
+
return require_CalmLensUtils._asyncToGenerator(function* () {
|
|
662
|
+
return verifyWebhookSignature(options);
|
|
663
|
+
})();
|
|
664
|
+
}
|
|
665
|
+
constructor(options) {
|
|
666
|
+
var _this$options$baseUrl, _this$options$cdnBase;
|
|
667
|
+
this.options = options;
|
|
668
|
+
this.ensuredLenses = /* @__PURE__ */ new Map();
|
|
669
|
+
this.pendingEnsureLenses = /* @__PURE__ */ new Map();
|
|
670
|
+
this.multipartImageUploadSizes = /* @__PURE__ */ new Map();
|
|
671
|
+
this.multipartUploadQueues = /* @__PURE__ */ new Map();
|
|
672
|
+
if (!options.apiKey) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "API key is required" });
|
|
673
|
+
if (!options.projectId) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Project ID is required" });
|
|
674
|
+
if (options.timeoutMs !== void 0 && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs <= 0)) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "timeoutMs must be a positive integer" });
|
|
675
|
+
this.options = require_CalmLensUtils._objectSpread2({}, options);
|
|
676
|
+
this.options.baseUrl = (_this$options$baseUrl = this.options.baseUrl) !== null && _this$options$baseUrl !== void 0 ? _this$options$baseUrl : `https://api.${require_CalmLensUtils.DOMAIN}/v1`;
|
|
677
|
+
this.options.cdnBaseUrl = (_this$options$cdnBase = this.options.cdnBaseUrl) !== null && _this$options$cdnBase !== void 0 ? _this$options$cdnBase : `https://cdn.${require_CalmLensUtils.DOMAIN}/v1`;
|
|
678
|
+
this.api = createApi(this.options);
|
|
679
|
+
this.endpoints = createEndpoints(this.api);
|
|
680
|
+
}
|
|
681
|
+
/** Scope cancellation/timeout to an operation without changing this client's defaults. */
|
|
682
|
+
withRequestOptions(options) {
|
|
683
|
+
const client = new CalmLensClient(require_CalmLensUtils._objectSpread2(require_CalmLensUtils._objectSpread2({}, this.options), options));
|
|
684
|
+
client.multipartUploadQueues = this.multipartUploadQueues;
|
|
685
|
+
client.multipartImageUploadSizes = this.multipartImageUploadSizes;
|
|
686
|
+
return client;
|
|
687
|
+
}
|
|
688
|
+
getUploadFetch() {
|
|
689
|
+
var _this$options$request, _ref2, _this$options$uploadF;
|
|
690
|
+
const requestBackendFetch = (_this$options$request = this.options.requestBackend) === null || _this$options$request === void 0 ? void 0 : _this$options$request.fetch;
|
|
691
|
+
const fetchImpl = (_ref2 = (_this$options$uploadF = this.options.uploadFetch) !== null && _this$options$uploadF !== void 0 ? _this$options$uploadF : requestBackendFetch) !== null && _ref2 !== void 0 ? _ref2 : globalThis.fetch;
|
|
692
|
+
if (!fetchImpl) throw require_CalmLensUtils.calmLensError(require_CalmLensUtils.SDK_ERRORS.NO_CDN_FETCH);
|
|
693
|
+
return safeFetch(fetchImpl, this.options);
|
|
694
|
+
}
|
|
695
|
+
submitRawAssetUpload(options, queue) {
|
|
696
|
+
var _this = this;
|
|
697
|
+
return require_CalmLensUtils._asyncToGenerator(function* () {
|
|
698
|
+
var _payload$sizeInBytes;
|
|
699
|
+
const query = new URLSearchParams();
|
|
700
|
+
query.set("name", options.name);
|
|
701
|
+
query.set("queue", String(queue));
|
|
702
|
+
setOptionalQueryValue(query, "description", options.description);
|
|
703
|
+
setOptionalQueryValue(query, "processingOptions", options.processingOptions);
|
|
704
|
+
setOptionalQueryValue(query, "visibility", options.visibility);
|
|
705
|
+
setOptionalQueryValue(query, "metadata", options.metadata);
|
|
706
|
+
setOptionalQueryValue(query, "externalId", options.externalId);
|
|
707
|
+
setOptionalQueryValue(query, "externalUrl", options.externalUrl);
|
|
708
|
+
setOptionalQueryValue(query, "folderId", options.folderId);
|
|
709
|
+
const isMultipart = "part" in options;
|
|
710
|
+
const payload = isMultipart ? options.part : options.content;
|
|
711
|
+
query.set("contentType", payload.type);
|
|
712
|
+
setOptionalQueryValue(query, "sizeInBytes", (_payload$sizeInBytes = payload.sizeInBytes) !== null && _payload$sizeInBytes !== void 0 ? _payload$sizeInBytes : require_CalmLensUtils.getAssetPayloadByteLength(payload));
|
|
713
|
+
if (isMultipart) {
|
|
714
|
+
var _part$partNumber, _part$isFinal, _part$sizeInBytes;
|
|
715
|
+
const part = payload;
|
|
716
|
+
const multipartOptions = options;
|
|
717
|
+
query.set("partNumber", String((_part$partNumber = part.partNumber) !== null && _part$partNumber !== void 0 ? _part$partNumber : 1));
|
|
718
|
+
query.set("isFinal", String((_part$isFinal = part.isFinal) !== null && _part$isFinal !== void 0 ? _part$isFinal : false));
|
|
719
|
+
setOptionalQueryValue(query, "sizeInBytes", (_part$sizeInBytes = part.sizeInBytes) !== null && _part$sizeInBytes !== void 0 ? _part$sizeInBytes : multipartOptions.sizeInBytes);
|
|
720
|
+
}
|
|
721
|
+
const baseUrl = _this.options.baseUrl.replace(/\/$/, "");
|
|
722
|
+
const path = isMultipart ? "assets/multipart-upload" : "assets/upload";
|
|
723
|
+
const url = `${baseUrl}/projects/${encodeURIComponent(_this.options.projectId)}/${path}?${query}`;
|
|
724
|
+
const response = yield _this.getUploadFetch()(url, {
|
|
725
|
+
method: "POST",
|
|
726
|
+
headers: {
|
|
727
|
+
"Content-Type": payload.type,
|
|
728
|
+
"X-Api-Key": _this.options.apiKey,
|
|
729
|
+
"X-CalmLens-Upload": isMultipart ? "part" : "content"
|
|
730
|
+
},
|
|
731
|
+
body: toRawUploadBody(payload),
|
|
732
|
+
duplex: "half"
|
|
733
|
+
});
|
|
734
|
+
const asset = yield _this.parseRawUploadResponse(response);
|
|
735
|
+
if (isMultipart && asset.status === "uploading") {
|
|
736
|
+
_this.multipartUploadQueues.set(asset.id, queue);
|
|
737
|
+
if (isImageMimeType(payload.type)) {
|
|
738
|
+
var _asset$sizeInBytes;
|
|
739
|
+
_this.multipartImageUploadSizes.set(asset.id, (_asset$sizeInBytes = asset.sizeInBytes) !== null && _asset$sizeInBytes !== void 0 ? _asset$sizeInBytes : 0);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
return asset;
|
|
743
|
+
})();
|
|
744
|
+
}
|
|
745
|
+
submitRawAssetPart(assetId, part, queue) {
|
|
746
|
+
var _this2 = this;
|
|
747
|
+
return require_CalmLensUtils._asyncToGenerator(function* () {
|
|
748
|
+
var _part$isFinal2, _part$sizeInBytes2;
|
|
749
|
+
const query = new URLSearchParams({
|
|
750
|
+
queue: String(queue),
|
|
751
|
+
partNumber: String(part.partNumber),
|
|
752
|
+
isFinal: String((_part$isFinal2 = part.isFinal) !== null && _part$isFinal2 !== void 0 ? _part$isFinal2 : false)
|
|
753
|
+
});
|
|
754
|
+
setOptionalQueryValue(query, "sizeInBytes", (_part$sizeInBytes2 = part.sizeInBytes) !== null && _part$sizeInBytes2 !== void 0 ? _part$sizeInBytes2 : require_CalmLensUtils.getAssetPayloadByteLength(part));
|
|
755
|
+
const url = `${_this2.options.baseUrl.replace(/\/$/, "")}/assets/${encodeURIComponent(assetId)}/part?${query}`;
|
|
756
|
+
const response = yield _this2.getUploadFetch()(url, {
|
|
757
|
+
method: "POST",
|
|
758
|
+
headers: {
|
|
759
|
+
"X-Api-Key": _this2.options.apiKey,
|
|
760
|
+
"X-CalmLens-Upload": "part"
|
|
761
|
+
},
|
|
762
|
+
body: toRawUploadBody(part),
|
|
763
|
+
duplex: "half"
|
|
764
|
+
});
|
|
765
|
+
const asset = yield _this2.parseRawUploadResponse(response);
|
|
766
|
+
if (asset.status === "uploading") {
|
|
767
|
+
var _asset$sizeInBytes2;
|
|
768
|
+
_this2.multipartImageUploadSizes.set(asset.id, (_asset$sizeInBytes2 = asset.sizeInBytes) !== null && _asset$sizeInBytes2 !== void 0 ? _asset$sizeInBytes2 : 0);
|
|
769
|
+
} else {
|
|
770
|
+
_this2.multipartImageUploadSizes.delete(assetId);
|
|
771
|
+
_this2.multipartUploadQueues.delete(assetId);
|
|
772
|
+
}
|
|
773
|
+
return asset;
|
|
774
|
+
})();
|
|
775
|
+
}
|
|
776
|
+
parseRawUploadResponse(response) {
|
|
777
|
+
return require_CalmLensUtils._asyncToGenerator(function* () {
|
|
778
|
+
let data;
|
|
779
|
+
try {
|
|
780
|
+
data = yield response.json();
|
|
781
|
+
} catch (cause) {
|
|
782
|
+
throw require_CalmLensUtils.calmLensError({ id: cause instanceof Error && ["TimeoutError", "AbortError"].includes(cause.name) ? cause.name === "TimeoutError" ? "sdk/timeout" : "sdk/cancelled" : response.ok ? "sdk/invalid-response" : "sdk/http-error" }, {
|
|
783
|
+
message: `Invalid JSON response (HTTP ${response.status})`,
|
|
784
|
+
status: response.status,
|
|
785
|
+
cause
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
if (!response.ok) {
|
|
789
|
+
if (isApiErrorPayload(data)) throw require_CalmLensUtils.calmLensError({
|
|
790
|
+
id: data.code,
|
|
791
|
+
defaultMessage: data.message
|
|
792
|
+
}, {
|
|
793
|
+
message: data.message,
|
|
794
|
+
status: response.status,
|
|
795
|
+
details: require_CalmLensUtils._objectSpread2(require_CalmLensUtils._objectSpread2({}, data.details), {}, {
|
|
796
|
+
traceId: data.traceId,
|
|
797
|
+
network: true
|
|
798
|
+
})
|
|
799
|
+
});
|
|
800
|
+
throw require_CalmLensUtils.calmLensError({ id: "sdk/http-error" }, {
|
|
801
|
+
message: `HTTP ${response.status}`,
|
|
802
|
+
status: response.status
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
if (!data || typeof data !== "object" || !("id" in data) || typeof data.id !== "string" || !data.id || !("status" in data) || ![
|
|
806
|
+
"uploading",
|
|
807
|
+
"pending",
|
|
808
|
+
"approved",
|
|
809
|
+
"rejected",
|
|
810
|
+
"error"
|
|
811
|
+
].includes(String(data.status))) throw require_CalmLensUtils.calmLensError({ id: "sdk/invalid-response" }, {
|
|
812
|
+
message: "Expected an asset response",
|
|
813
|
+
status: response.status
|
|
814
|
+
});
|
|
815
|
+
return data;
|
|
816
|
+
})();
|
|
817
|
+
}
|
|
818
|
+
get cdn() {
|
|
819
|
+
var _this3 = this;
|
|
820
|
+
return {
|
|
821
|
+
/**
|
|
822
|
+
* Create a CDN URL for asset content or previews.
|
|
823
|
+
* Private assets require an authenticated request or signed URL.
|
|
824
|
+
*/
|
|
825
|
+
getAssetUrl: (_ref3) => {
|
|
826
|
+
var _options$resource;
|
|
827
|
+
let { assetIdentifier } = _ref3, options = require_CalmLensUtils._objectWithoutProperties(_ref3, _excluded3);
|
|
828
|
+
if (!assetIdentifier) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Asset identifier is required" });
|
|
829
|
+
const resource = (_options$resource = options.resource) !== null && _options$resource !== void 0 ? _options$resource : "content";
|
|
830
|
+
const url = `${this.options.cdnBaseUrl.replace(/\/$/, "")}/assets/${encodeURIComponent(this.options.projectId)}/${encodeURIComponent(assetIdentifier)}/${resource}`;
|
|
831
|
+
return appendCdnSelector(url, options);
|
|
832
|
+
},
|
|
833
|
+
/**
|
|
834
|
+
* Fetch asset content or previews from the CDN.
|
|
835
|
+
* Private assets are authenticated with the client's API key.
|
|
836
|
+
*/
|
|
837
|
+
serve: function() {
|
|
838
|
+
var _ref5 = require_CalmLensUtils._asyncToGenerator(function* (_ref4) {
|
|
839
|
+
var _this$options$cdnFetc;
|
|
840
|
+
let { assetIdentifier, init } = _ref4, urlOptions = require_CalmLensUtils._objectWithoutProperties(_ref4, _excluded4);
|
|
841
|
+
const fetchImpl = (_this$options$cdnFetc = _this3.options.cdnFetch) !== null && _this$options$cdnFetc !== void 0 ? _this$options$cdnFetc : globalThis.fetch;
|
|
842
|
+
if (!fetchImpl) throw require_CalmLensUtils.calmLensError(require_CalmLensUtils.SDK_ERRORS.NO_CDN_FETCH);
|
|
843
|
+
return safeFetch(fetchImpl, _this3.options)(_this3.cdn.getAssetUrl(require_CalmLensUtils._objectSpread2({ assetIdentifier }, urlOptions)), withApiKeyHeader(init, _this3.options.apiKey));
|
|
844
|
+
});
|
|
845
|
+
return function serve(_x3) {
|
|
846
|
+
return _ref5.apply(this, arguments);
|
|
847
|
+
};
|
|
848
|
+
}()
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
get text() {
|
|
852
|
+
var _this4 = this;
|
|
853
|
+
return { moderate: function() {
|
|
854
|
+
var _ref6 = require_CalmLensUtils._asyncToGenerator(function* (options) {
|
|
855
|
+
return _this4.assets.moderate(require_CalmLensUtils.toTextAssetOptions(options));
|
|
856
|
+
});
|
|
857
|
+
return function moderate(_x4) {
|
|
858
|
+
return _ref6.apply(this, arguments);
|
|
859
|
+
};
|
|
860
|
+
}() };
|
|
861
|
+
}
|
|
862
|
+
get assets() {
|
|
863
|
+
var _this5 = this;
|
|
864
|
+
return {
|
|
865
|
+
/**
|
|
866
|
+
* List all assets for a project
|
|
867
|
+
* @param options - Pagination and filtering options
|
|
868
|
+
* @returns Promise with paginated assets
|
|
869
|
+
*/
|
|
870
|
+
list: function() {
|
|
871
|
+
var _ref7 = require_CalmLensUtils._asyncToGenerator(function* (options) {
|
|
872
|
+
var _options$pageIndex;
|
|
873
|
+
return (yield _this5.endpoints.getAssetsPage.submit({
|
|
874
|
+
params: { projectId: _this5.options.projectId },
|
|
875
|
+
query: require_CalmLensUtils._objectSpread2(require_CalmLensUtils._objectSpread2({}, options), {}, { pageIndex: (_options$pageIndex = options.pageIndex) !== null && _options$pageIndex !== void 0 ? _options$pageIndex : 0 })
|
|
876
|
+
})).data;
|
|
877
|
+
});
|
|
878
|
+
return function list(_x5) {
|
|
879
|
+
return _ref7.apply(this, arguments);
|
|
880
|
+
};
|
|
881
|
+
}(),
|
|
882
|
+
/**
|
|
883
|
+
* Retrieve a specific asset by ID
|
|
884
|
+
* @param assetId - The asset ID
|
|
885
|
+
* @returns Promise with asset data
|
|
886
|
+
*/
|
|
887
|
+
retrieve: function() {
|
|
888
|
+
var _ref8 = require_CalmLensUtils._asyncToGenerator(function* ({ assetId }) {
|
|
889
|
+
if (!assetId) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Asset ID is required" });
|
|
890
|
+
return (yield _this5.endpoints.getAsset.submit({ params: { assetId } })).data;
|
|
891
|
+
});
|
|
892
|
+
return function retrieve(_x6) {
|
|
893
|
+
return _ref8.apply(this, arguments);
|
|
894
|
+
};
|
|
895
|
+
}(),
|
|
896
|
+
update: function() {
|
|
897
|
+
var _ref10 = require_CalmLensUtils._asyncToGenerator(function* (_ref9) {
|
|
898
|
+
let { assetId } = _ref9, body = require_CalmLensUtils._objectWithoutProperties(_ref9, _excluded5);
|
|
899
|
+
if (!assetId) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Asset ID is required" });
|
|
900
|
+
return (yield _this5.endpoints.patchAsset.submit({
|
|
901
|
+
params: { assetId },
|
|
902
|
+
body
|
|
903
|
+
})).data;
|
|
904
|
+
});
|
|
905
|
+
return function update(_x7) {
|
|
906
|
+
return _ref10.apply(this, arguments);
|
|
907
|
+
};
|
|
908
|
+
}(),
|
|
909
|
+
/**
|
|
910
|
+
* Get child assets of a parent asset
|
|
911
|
+
* @param assetId - The parent asset ID
|
|
912
|
+
* @param options - Pagination options
|
|
913
|
+
* @returns Promise with paginated child assets
|
|
914
|
+
*/
|
|
915
|
+
listChildren: function() {
|
|
916
|
+
var _ref12 = require_CalmLensUtils._asyncToGenerator(function* (_ref11) {
|
|
917
|
+
var _options$pageIndex2;
|
|
918
|
+
let { assetId } = _ref11, options = require_CalmLensUtils._objectWithoutProperties(_ref11, _excluded6);
|
|
919
|
+
if (!assetId) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Asset ID is required" });
|
|
920
|
+
return (yield _this5.endpoints.getAssetChildren.submit({
|
|
921
|
+
params: { assetId },
|
|
922
|
+
query: require_CalmLensUtils._objectSpread2(require_CalmLensUtils._objectSpread2({}, options), {}, { pageIndex: (_options$pageIndex2 = options.pageIndex) !== null && _options$pageIndex2 !== void 0 ? _options$pageIndex2 : 0 })
|
|
923
|
+
})).data;
|
|
924
|
+
});
|
|
925
|
+
return function listChildren(_x8) {
|
|
926
|
+
return _ref12.apply(this, arguments);
|
|
927
|
+
};
|
|
928
|
+
}(),
|
|
929
|
+
/**
|
|
930
|
+
* Submit a new asset for processing (queued asynchronously)
|
|
931
|
+
* The asset will be queued for classification and returned immediately.
|
|
932
|
+
* @param options - Asset submission options
|
|
933
|
+
* @returns Promise with created asset
|
|
934
|
+
*/
|
|
935
|
+
create: function() {
|
|
936
|
+
var _ref13 = require_CalmLensUtils._asyncToGenerator(function* (options) {
|
|
937
|
+
const body = prepareSubmitAssetOptions(options);
|
|
938
|
+
if ("content" in body || "part" in body) return yield _this5.submitRawAssetUpload(body, true);
|
|
939
|
+
return (yield _this5.endpoints.postUploadAsset.submit({
|
|
940
|
+
body: normalizeAssetOptionsForRequest(body),
|
|
941
|
+
params: { projectId: _this5.options.projectId },
|
|
942
|
+
query: { queue: true }
|
|
943
|
+
})).data;
|
|
944
|
+
});
|
|
945
|
+
return function create(_x9) {
|
|
946
|
+
return _ref13.apply(this, arguments);
|
|
947
|
+
};
|
|
948
|
+
}(),
|
|
949
|
+
/**
|
|
950
|
+
* Submit a new asset and moderate it synchronously
|
|
951
|
+
* The asset will be classified immediately before the response is returned.
|
|
952
|
+
* This may take longer but ensures the asset is fully processed.
|
|
953
|
+
* @param options - Asset submission options
|
|
954
|
+
* @returns Promise with created and analyzed asset
|
|
955
|
+
*/
|
|
956
|
+
moderate: function() {
|
|
957
|
+
var _ref14 = require_CalmLensUtils._asyncToGenerator(function* (options) {
|
|
958
|
+
if ("content" in options && "plainText" in options.content && (typeof options.content.plainText !== "string" || !options.content.plainText.trim())) throw require_CalmLensUtils.calmLensError(require_CalmLensUtils.PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Text to moderate must be a non-empty string" });
|
|
959
|
+
const body = prepareSubmitAssetOptions(options);
|
|
960
|
+
if ("content" in body || "part" in body) return yield _this5.submitRawAssetUpload(body, false);
|
|
961
|
+
return (yield _this5.endpoints.postUploadAsset.submit({
|
|
962
|
+
body: normalizeAssetOptionsForRequest(body),
|
|
963
|
+
params: { projectId: _this5.options.projectId },
|
|
964
|
+
query: { queue: false }
|
|
965
|
+
})).data;
|
|
966
|
+
});
|
|
967
|
+
return function moderate(_x10) {
|
|
968
|
+
return _ref14.apply(this, arguments);
|
|
969
|
+
};
|
|
970
|
+
}(),
|
|
971
|
+
/**
|
|
972
|
+
* Upload a part for a multipart upload
|
|
973
|
+
* @param assetId - The asset ID
|
|
974
|
+
* @param part - The part to upload
|
|
975
|
+
* @returns Promise with asset data
|
|
976
|
+
*/
|
|
977
|
+
uploadPart: function() {
|
|
978
|
+
var _ref15 = require_CalmLensUtils._asyncToGenerator(function* ({ assetId, part }) {
|
|
979
|
+
var _part$sizeInBytes3, _this$multipartUpload;
|
|
980
|
+
if (!assetId) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Asset ID is required" });
|
|
981
|
+
if (!part) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Part options are required" });
|
|
982
|
+
const validation = require_CalmLensUtils.validateAssetPayload(part, {
|
|
983
|
+
multipart: true,
|
|
984
|
+
isFinal: part.isFinal
|
|
985
|
+
});
|
|
986
|
+
if (!validation.ok) throw require_CalmLensUtils.calmLensError(require_CalmLensUtils.PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: validation.error });
|
|
987
|
+
const existingImageSizeInBytes = _this5.multipartImageUploadSizes.get(assetId);
|
|
988
|
+
const partSizeInBytes = (_part$sizeInBytes3 = part.sizeInBytes) !== null && _part$sizeInBytes3 !== void 0 ? _part$sizeInBytes3 : require_CalmLensUtils.getAssetPayloadByteLength(part);
|
|
989
|
+
if (existingImageSizeInBytes !== void 0 && partSizeInBytes !== void 0) {
|
|
990
|
+
const totalSizeInBytes = existingImageSizeInBytes + partSizeInBytes;
|
|
991
|
+
if (totalSizeInBytes > require_CalmLensUtils.MAX_IMAGE_UPLOAD_BYTES) throw require_CalmLensUtils.calmLensError(require_CalmLensUtils.PUBLIC_ERROR_CODES.MULTIPART_IMAGE_TOO_LARGE);
|
|
992
|
+
if (part.isFinal && totalSizeInBytes < require_CalmLensUtils.MIN_MULTIPART_IMAGE_UPLOAD_BYTES) throw require_CalmLensUtils.calmLensError(require_CalmLensUtils.PUBLIC_ERROR_CODES.MULTIPART_IMAGE_TOO_SMALL);
|
|
993
|
+
}
|
|
994
|
+
return yield _this5.submitRawAssetPart(assetId, part, (_this$multipartUpload = _this5.multipartUploadQueues.get(assetId)) !== null && _this$multipartUpload !== void 0 ? _this$multipartUpload : false);
|
|
995
|
+
});
|
|
996
|
+
return function uploadPart(_x11) {
|
|
997
|
+
return _ref15.apply(this, arguments);
|
|
998
|
+
};
|
|
999
|
+
}(),
|
|
1000
|
+
/**
|
|
1001
|
+
* Create a short-lived signed CDN URL for an asset.
|
|
1002
|
+
* This is useful for private assets where clients should not send app
|
|
1003
|
+
* auth cookies or API keys to the CDN on every media request.
|
|
1004
|
+
*/
|
|
1005
|
+
createSignedUrl: function() {
|
|
1006
|
+
var _ref17 = require_CalmLensUtils._asyncToGenerator(function* (_ref16) {
|
|
1007
|
+
var _options$resource2, _options$expiresInSec;
|
|
1008
|
+
let { assetId } = _ref16, options = require_CalmLensUtils._objectWithoutProperties(_ref16, _excluded7);
|
|
1009
|
+
if (!assetId) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Asset ID is required" });
|
|
1010
|
+
if (options.lens && options.transform) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Specify either a lens or a transform, not both" });
|
|
1011
|
+
return (yield _this5.endpoints.postAssetSignedUrl.submit({
|
|
1012
|
+
body: {
|
|
1013
|
+
resource: (_options$resource2 = options.resource) !== null && _options$resource2 !== void 0 ? _options$resource2 : "content",
|
|
1014
|
+
expiresInSeconds: (_options$expiresInSec = options.expiresInSeconds) !== null && _options$expiresInSec !== void 0 ? _options$expiresInSec : 900,
|
|
1015
|
+
lens: options.lens,
|
|
1016
|
+
transform: options.transform
|
|
1017
|
+
},
|
|
1018
|
+
params: { assetId }
|
|
1019
|
+
})).data;
|
|
1020
|
+
});
|
|
1021
|
+
return function createSignedUrl(_x12) {
|
|
1022
|
+
return _ref17.apply(this, arguments);
|
|
1023
|
+
};
|
|
1024
|
+
}(),
|
|
1025
|
+
move: function() {
|
|
1026
|
+
var _ref18 = require_CalmLensUtils._asyncToGenerator(function* ({ assetId, folderId }) {
|
|
1027
|
+
if (!assetId) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Asset ID is required" });
|
|
1028
|
+
return (yield _this5.endpoints.moveAsset.submit({
|
|
1029
|
+
params: { assetId },
|
|
1030
|
+
body: { folderId }
|
|
1031
|
+
})).data;
|
|
1032
|
+
});
|
|
1033
|
+
return function move(_x13) {
|
|
1034
|
+
return _ref18.apply(this, arguments);
|
|
1035
|
+
};
|
|
1036
|
+
}(),
|
|
1037
|
+
/**
|
|
1038
|
+
* Processes an asset that failed (status `error`) again. It returns to `pending` and is
|
|
1039
|
+
* moderated like a new upload; its content must still be stored.
|
|
1040
|
+
*/
|
|
1041
|
+
retry: function() {
|
|
1042
|
+
var _ref19 = require_CalmLensUtils._asyncToGenerator(function* ({ assetId }) {
|
|
1043
|
+
if (!assetId) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Asset ID is required" });
|
|
1044
|
+
return (yield _this5.endpoints.retryAsset.submit({ params: { assetId } })).data;
|
|
1045
|
+
});
|
|
1046
|
+
return function retry(_x14) {
|
|
1047
|
+
return _ref19.apply(this, arguments);
|
|
1048
|
+
};
|
|
1049
|
+
}()
|
|
1050
|
+
};
|
|
1051
|
+
}
|
|
1052
|
+
get events() {
|
|
1053
|
+
var _this6 = this;
|
|
1054
|
+
return {
|
|
1055
|
+
/**
|
|
1056
|
+
* List project events after a cursor, oldest first. Call without `after` to get a cursor
|
|
1057
|
+
* for "now", then poll with the returned `cursor`. Webhook deliveries carry the same events
|
|
1058
|
+
* reshaped as `{ id, type, createdAt, projectId, data }`.
|
|
1059
|
+
*/
|
|
1060
|
+
list: function() {
|
|
1061
|
+
var _ref20 = require_CalmLensUtils._asyncToGenerator(function* (options = {}) {
|
|
1062
|
+
return (yield _this6.endpoints.getEvents.submit({
|
|
1063
|
+
params: { projectId: _this6.options.projectId },
|
|
1064
|
+
query: options
|
|
1065
|
+
})).data;
|
|
1066
|
+
});
|
|
1067
|
+
return function list() {
|
|
1068
|
+
return _ref20.apply(this, arguments);
|
|
1069
|
+
};
|
|
1070
|
+
}() };
|
|
1071
|
+
}
|
|
1072
|
+
get folders() {
|
|
1073
|
+
var _this7 = this;
|
|
1074
|
+
return {
|
|
1075
|
+
list: function() {
|
|
1076
|
+
var _ref21 = require_CalmLensUtils._asyncToGenerator(function* () {
|
|
1077
|
+
return (yield _this7.endpoints.getFolders.submit({ params: { projectId: _this7.options.projectId } })).data.folders;
|
|
1078
|
+
});
|
|
1079
|
+
return function list() {
|
|
1080
|
+
return _ref21.apply(this, arguments);
|
|
1081
|
+
};
|
|
1082
|
+
}(),
|
|
1083
|
+
retrieve: function() {
|
|
1084
|
+
var _ref22 = require_CalmLensUtils._asyncToGenerator(function* ({ folderId }) {
|
|
1085
|
+
if (!folderId) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Folder ID is required" });
|
|
1086
|
+
return (yield _this7.endpoints.getFolder.submit({ params: { folderId } })).data;
|
|
1087
|
+
});
|
|
1088
|
+
return function retrieve(_x15) {
|
|
1089
|
+
return _ref22.apply(this, arguments);
|
|
1090
|
+
};
|
|
1091
|
+
}(),
|
|
1092
|
+
create: function() {
|
|
1093
|
+
var _ref23 = require_CalmLensUtils._asyncToGenerator(function* (options) {
|
|
1094
|
+
return (yield _this7.endpoints.postFolder.submit({
|
|
1095
|
+
params: { projectId: _this7.options.projectId },
|
|
1096
|
+
body: options
|
|
1097
|
+
})).data;
|
|
1098
|
+
});
|
|
1099
|
+
return function create(_x16) {
|
|
1100
|
+
return _ref23.apply(this, arguments);
|
|
1101
|
+
};
|
|
1102
|
+
}(),
|
|
1103
|
+
update: function() {
|
|
1104
|
+
var _ref25 = require_CalmLensUtils._asyncToGenerator(function* (_ref24) {
|
|
1105
|
+
let { folderId } = _ref24, body = require_CalmLensUtils._objectWithoutProperties(_ref24, _excluded8);
|
|
1106
|
+
if (!folderId) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Folder ID is required" });
|
|
1107
|
+
return (yield _this7.endpoints.patchFolder.submit({
|
|
1108
|
+
params: { folderId },
|
|
1109
|
+
body
|
|
1110
|
+
})).data;
|
|
1111
|
+
});
|
|
1112
|
+
return function update(_x17) {
|
|
1113
|
+
return _ref25.apply(this, arguments);
|
|
1114
|
+
};
|
|
1115
|
+
}(),
|
|
1116
|
+
delete: function() {
|
|
1117
|
+
var _ref26 = require_CalmLensUtils._asyncToGenerator(function* ({ folderId }) {
|
|
1118
|
+
if (!folderId) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Folder ID is required" });
|
|
1119
|
+
yield _this7.endpoints.deleteFolder.submit({ params: { folderId } });
|
|
1120
|
+
});
|
|
1121
|
+
return function _delete(_x18) {
|
|
1122
|
+
return _ref26.apply(this, arguments);
|
|
1123
|
+
};
|
|
1124
|
+
}(),
|
|
1125
|
+
move: function() {
|
|
1126
|
+
var _ref27 = require_CalmLensUtils._asyncToGenerator(function* ({ folderId, parentId }) {
|
|
1127
|
+
if (!folderId) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Folder ID is required" });
|
|
1128
|
+
return (yield _this7.endpoints.moveFolder.submit({
|
|
1129
|
+
params: { folderId },
|
|
1130
|
+
body: { parentId }
|
|
1131
|
+
})).data;
|
|
1132
|
+
});
|
|
1133
|
+
return function move(_x19) {
|
|
1134
|
+
return _ref27.apply(this, arguments);
|
|
1135
|
+
};
|
|
1136
|
+
}()
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Create a named lens at any positive version, or update it with a greater version.
|
|
1141
|
+
* Supplying the same definition and version is idempotent.
|
|
1142
|
+
*/
|
|
1143
|
+
ensureLens(options) {
|
|
1144
|
+
var _this8 = this;
|
|
1145
|
+
return require_CalmLensUtils._asyncToGenerator(function* () {
|
|
1146
|
+
if (!options.identifier) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Lens identifier is required" });
|
|
1147
|
+
const [lens] = yield _this8.ensureLenses({ lenses: [options] });
|
|
1148
|
+
return lens;
|
|
1149
|
+
})();
|
|
1150
|
+
}
|
|
1151
|
+
/**
|
|
1152
|
+
* Create or update several named lenses in one API request.
|
|
1153
|
+
* Each lens follows the same versioning and idempotency rules as ensureLens().
|
|
1154
|
+
*/
|
|
1155
|
+
ensureLenses({ lenses }) {
|
|
1156
|
+
var _this9 = this;
|
|
1157
|
+
return require_CalmLensUtils._asyncToGenerator(function* () {
|
|
1158
|
+
if (lenses.length === 0) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "At least one lens is required" });
|
|
1159
|
+
if (lenses.some((option) => !option.identifier)) throw require_CalmLensUtils.calmLensError({ id: "upload/invalid-payload" }, { message: "Lens identifier is required" });
|
|
1160
|
+
const missingOptions = [];
|
|
1161
|
+
const missingKeys = /* @__PURE__ */ new Set();
|
|
1162
|
+
for (const option of lenses) {
|
|
1163
|
+
const cacheKey = getEnsureLensCacheKey(option);
|
|
1164
|
+
if (!_this9.ensuredLenses.has(cacheKey) && !missingKeys.has(cacheKey)) {
|
|
1165
|
+
missingKeys.add(cacheKey);
|
|
1166
|
+
missingOptions.push(option);
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
if (missingOptions.length === 0) return lenses.map((option) => _this9.ensuredLenses.get(getEnsureLensCacheKey(option)));
|
|
1170
|
+
const batchCacheKey = JSON.stringify([...missingKeys].sort());
|
|
1171
|
+
let pending = _this9.pendingEnsureLenses.get(batchCacheKey);
|
|
1172
|
+
if (!pending) {
|
|
1173
|
+
pending = _this9.submitEnsureLenses(missingOptions);
|
|
1174
|
+
_this9.pendingEnsureLenses.set(batchCacheKey, pending);
|
|
1175
|
+
pending.then(() => _this9.pendingEnsureLenses.delete(batchCacheKey), () => _this9.pendingEnsureLenses.delete(batchCacheKey));
|
|
1176
|
+
}
|
|
1177
|
+
yield pending;
|
|
1178
|
+
return lenses.map((option) => _this9.ensuredLenses.get(getEnsureLensCacheKey(option)));
|
|
1179
|
+
})();
|
|
1180
|
+
}
|
|
1181
|
+
submitEnsureLenses(options) {
|
|
1182
|
+
var _this10 = this;
|
|
1183
|
+
return require_CalmLensUtils._asyncToGenerator(function* () {
|
|
1184
|
+
const result = yield _this10.endpoints.ensureLenses.submit({
|
|
1185
|
+
body: { lenses: options },
|
|
1186
|
+
params: { projectId: _this10.options.projectId }
|
|
1187
|
+
});
|
|
1188
|
+
for (const [index, lens] of result.data.lenses.entries()) {
|
|
1189
|
+
const optionsForLens = options[index];
|
|
1190
|
+
if (!optionsForLens) throw require_CalmLensUtils.calmLensError({ id: "sdk/invalid-response" }, { message: "CalmLens returned an unexpected lens response" });
|
|
1191
|
+
for (const [cacheKey, cachedLens] of _this10.ensuredLenses) if (cachedLens.identifier === optionsForLens.identifier) _this10.ensuredLenses.delete(cacheKey);
|
|
1192
|
+
_this10.ensuredLenses.set(getEnsureLensCacheKey(optionsForLens), lens);
|
|
1193
|
+
}
|
|
1194
|
+
})();
|
|
1195
|
+
}
|
|
1196
|
+
};
|
|
1197
|
+
//#endregion
|
|
1198
|
+
exports.CalmLensClient = CalmLensClient;
|
|
1199
|
+
exports.CalmLensError = require_CalmLensUtils.CalmLensError;
|
|
1200
|
+
exports.MEDIA_TEST_SIGNALS = MEDIA_TEST_SIGNALS;
|
|
1201
|
+
exports.WEBHOOK_DELIVERY_HEADER = WEBHOOK_DELIVERY_HEADER;
|
|
1202
|
+
exports.WEBHOOK_SIGNATURE_HEADER = WEBHOOK_SIGNATURE_HEADER;
|
|
1203
|
+
exports.WEBHOOK_SIGNATURE_TOLERANCE_SECONDS = WEBHOOK_SIGNATURE_TOLERANCE_SECONDS;
|
|
1204
|
+
exports.WEBHOOK_TIMESTAMP_HEADER = WEBHOOK_TIMESTAMP_HEADER;
|
|
1205
|
+
exports.generateMediaTestCode = generateMediaTestCode;
|
|
1206
|
+
exports.verifyWebhookSignature = verifyWebhookSignature;
|