@calmlens/sdk 0.0.0-stage → 0.6.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 +654 -2
- package/cjs/CalmLensTypes-BpmT60j-.d.ts +3522 -0
- package/cjs/CalmLensUtils-DA1_j5-P.js +578 -0
- package/cjs/index.d.ts +2751 -0
- package/cjs/index.js +1252 -0
- package/cjs/package.json +3 -0
- package/cjs/testing.d.ts +190 -0
- package/cjs/testing.js +814 -0
- package/esm/CalmLensTypes-BpmT60j-.d.ts +3522 -0
- package/esm/CalmLensUtils-UthMaLx_.js +431 -0
- package/esm/index.d.ts +2751 -0
- package/esm/index.js +1240 -0
- package/esm/package.json +3 -0
- package/esm/testing.d.ts +190 -0
- package/esm/testing.js +808 -0
- package/package.json +87 -4
package/esm/testing.js
ADDED
|
@@ -0,0 +1,808 @@
|
|
|
1
|
+
import { b as _objectSpread2, d as isRejectedUploadMimeType, f as PUBLIC_ERROR_CODES, g as getAssetPayloadByteLength, h as assetToData, m as assetDataToUint8Array, n as validateClientOptions, o as calmLensError, p as stringifyJsonCanonical, r as _objectWithoutProperties, t as toTextAssetOptions, u as getRejectedUploadMimeTypeError, v as validateAssetPayload, y as _asyncToGenerator } from "./CalmLensUtils-UthMaLx_.js";
|
|
2
|
+
import * as zod from "zod";
|
|
3
|
+
//#region ../shared/src/Permissions.ts
|
|
4
|
+
const ACTION_SCHEMA = zod.enum([
|
|
5
|
+
"assets:read",
|
|
6
|
+
"assets:download",
|
|
7
|
+
"assets:create",
|
|
8
|
+
"assets:update",
|
|
9
|
+
"assets:delete",
|
|
10
|
+
"assets:share",
|
|
11
|
+
"folders:read",
|
|
12
|
+
"folders:create",
|
|
13
|
+
"folders:update",
|
|
14
|
+
"folders:delete",
|
|
15
|
+
"settings:read",
|
|
16
|
+
"settings:write",
|
|
17
|
+
"members:read",
|
|
18
|
+
"members:write",
|
|
19
|
+
"api-keys:read",
|
|
20
|
+
"api-keys:write",
|
|
21
|
+
"connectors:read",
|
|
22
|
+
"connectors:write",
|
|
23
|
+
"metadata:read",
|
|
24
|
+
"metadata:write",
|
|
25
|
+
"lenses:read",
|
|
26
|
+
"lenses:write",
|
|
27
|
+
"project:manage"
|
|
28
|
+
]);
|
|
29
|
+
const PROJECT_ACTIONS = [...[
|
|
30
|
+
"settings",
|
|
31
|
+
"members",
|
|
32
|
+
"api-keys",
|
|
33
|
+
"connectors",
|
|
34
|
+
"metadata",
|
|
35
|
+
"lenses"
|
|
36
|
+
].flatMap((feature) => [`${feature}:read`, `${feature}:write`]), "project:manage"];
|
|
37
|
+
const isProjectAction = (action) => PROJECT_ACTIONS.includes(action);
|
|
38
|
+
/** The actions that include `action`: its feature's write action and project:manage. */
|
|
39
|
+
const actionsImplying = (action) => !isProjectAction(action) || action === "project:manage" ? [] : action.endsWith(":read") ? [action.replace(/:read$/, ":write"), "project:manage"] : ["project:manage"];
|
|
40
|
+
const GRANT_SCHEMA = zod.object({
|
|
41
|
+
actions: zod.array(ACTION_SCHEMA),
|
|
42
|
+
folderId: zod.string().uuid().nullable(),
|
|
43
|
+
includeSubfolders: zod.boolean()
|
|
44
|
+
}).strict().refine((g) => g.folderId === null || !g.actions.some(isProjectAction), "Project configuration permissions require project scope");
|
|
45
|
+
const GRANTS_SCHEMA = zod.array(GRANT_SCHEMA).max(100);
|
|
46
|
+
zod.enum([
|
|
47
|
+
"admin",
|
|
48
|
+
"member",
|
|
49
|
+
"viewer",
|
|
50
|
+
"custom"
|
|
51
|
+
]);
|
|
52
|
+
const permits = (grants, action, folderId, folders) => grants.some((grant) => {
|
|
53
|
+
if (![action, ...actionsImplying(action)].some((held) => grant.actions.includes(held))) return false;
|
|
54
|
+
if (grant.folderId === null) return true;
|
|
55
|
+
let current = folderId;
|
|
56
|
+
const visited = /* @__PURE__ */ new Set();
|
|
57
|
+
while (current && !visited.has(current)) {
|
|
58
|
+
var _folders$find$parentI, _folders$find;
|
|
59
|
+
if (current === grant.folderId) return true;
|
|
60
|
+
if (!grant.includeSubfolders) return false;
|
|
61
|
+
visited.add(current);
|
|
62
|
+
current = (_folders$find$parentI = (_folders$find = folders.find((folder) => folder.id === current)) === null || _folders$find === void 0 ? void 0 : _folders$find.parentId) !== null && _folders$find$parentI !== void 0 ? _folders$find$parentI : null;
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
});
|
|
66
|
+
const SYSTEM_PERMISSION_SCHEMA = zod.enum([
|
|
67
|
+
"system:admin",
|
|
68
|
+
"system:assets:read-all",
|
|
69
|
+
"system:uploads:unlimited"
|
|
70
|
+
]);
|
|
71
|
+
zod.array(SYSTEM_PERMISSION_SCHEMA);
|
|
72
|
+
zod.enum(["active", "banned"]);
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/testing/MockApiKey.ts
|
|
75
|
+
const MOCK_API_KEY_PREFIX = "sk_test_";
|
|
76
|
+
const toBase64Url = (value) => btoa(value).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
|
|
77
|
+
const fromBase64Url = (value) => {
|
|
78
|
+
const padded = value.padEnd(value.length + (4 - value.length % 4) % 4, "=");
|
|
79
|
+
return atob(padded.replaceAll("-", "+").replaceAll("_", "/"));
|
|
80
|
+
};
|
|
81
|
+
const createMockApiKey = (grants = []) => `${MOCK_API_KEY_PREFIX}${toBase64Url(JSON.stringify(GRANTS_SCHEMA.parse(grants)))}`;
|
|
82
|
+
const getMockApiKeyGrants = (apiKey) => {
|
|
83
|
+
if (!apiKey.startsWith("sk_test_")) return [];
|
|
84
|
+
try {
|
|
85
|
+
return GRANTS_SCHEMA.parse(JSON.parse(fromBase64Url(apiKey.slice(8))));
|
|
86
|
+
} catch (_unused) {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/testing/MockStorage.ts
|
|
92
|
+
var InMemoryMockImageStorage = class {
|
|
93
|
+
constructor() {
|
|
94
|
+
this.content = /* @__PURE__ */ new Map();
|
|
95
|
+
}
|
|
96
|
+
putContent(assetId, content) {
|
|
97
|
+
var _this = this;
|
|
98
|
+
return _asyncToGenerator(function* () {
|
|
99
|
+
const validation = validateAssetPayload(content);
|
|
100
|
+
if (!validation.ok) throw new Error(validation.error);
|
|
101
|
+
const bytes = yield assetDataToUint8Array(assetToData(content));
|
|
102
|
+
_this.content.set(assetId, {
|
|
103
|
+
assetId,
|
|
104
|
+
parts: /* @__PURE__ */ new Map([[1, bytes]]),
|
|
105
|
+
type: content.type
|
|
106
|
+
});
|
|
107
|
+
})();
|
|
108
|
+
}
|
|
109
|
+
putPart(assetId, part) {
|
|
110
|
+
var _this2 = this;
|
|
111
|
+
return _asyncToGenerator(function* () {
|
|
112
|
+
var _this$content$get, _part$partNumber, _part$type;
|
|
113
|
+
const validation = validateAssetPayload(part, {
|
|
114
|
+
multipart: true,
|
|
115
|
+
isFinal: part.isFinal
|
|
116
|
+
});
|
|
117
|
+
if (!validation.ok) throw new Error(validation.error);
|
|
118
|
+
const bytes = yield assetDataToUint8Array(assetToData(part));
|
|
119
|
+
const existing = (_this$content$get = _this2.content.get(assetId)) !== null && _this$content$get !== void 0 ? _this$content$get : {
|
|
120
|
+
assetId,
|
|
121
|
+
parts: /* @__PURE__ */ new Map(),
|
|
122
|
+
type: part.type
|
|
123
|
+
};
|
|
124
|
+
existing.parts.set((_part$partNumber = part.partNumber) !== null && _part$partNumber !== void 0 ? _part$partNumber : 1, bytes);
|
|
125
|
+
existing.type = (_part$type = part.type) !== null && _part$type !== void 0 ? _part$type : existing.type;
|
|
126
|
+
_this2.content.set(assetId, existing);
|
|
127
|
+
})();
|
|
128
|
+
}
|
|
129
|
+
getContent(assetId) {
|
|
130
|
+
var _this3 = this;
|
|
131
|
+
return _asyncToGenerator(function* () {
|
|
132
|
+
return _this3.content.get(assetId);
|
|
133
|
+
})();
|
|
134
|
+
}
|
|
135
|
+
deleteContent(assetId) {
|
|
136
|
+
var _this4 = this;
|
|
137
|
+
return _asyncToGenerator(function* () {
|
|
138
|
+
_this4.content.delete(assetId);
|
|
139
|
+
})();
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
var InMemoryMockDatabaseStorage = class {
|
|
143
|
+
constructor() {
|
|
144
|
+
this.assets = /* @__PURE__ */ new Map();
|
|
145
|
+
this.folders = /* @__PURE__ */ new Map();
|
|
146
|
+
}
|
|
147
|
+
createAsset(asset) {
|
|
148
|
+
var _this5 = this;
|
|
149
|
+
return _asyncToGenerator(function* () {
|
|
150
|
+
_this5.assets.set(asset.id, asset);
|
|
151
|
+
return asset;
|
|
152
|
+
})();
|
|
153
|
+
}
|
|
154
|
+
updateAsset(asset) {
|
|
155
|
+
var _this6 = this;
|
|
156
|
+
return _asyncToGenerator(function* () {
|
|
157
|
+
_this6.assets.set(asset.id, asset);
|
|
158
|
+
return asset;
|
|
159
|
+
})();
|
|
160
|
+
}
|
|
161
|
+
getAsset(assetId) {
|
|
162
|
+
var _this7 = this;
|
|
163
|
+
return _asyncToGenerator(function* () {
|
|
164
|
+
return _this7.assets.get(assetId);
|
|
165
|
+
})();
|
|
166
|
+
}
|
|
167
|
+
listAssets(projectId) {
|
|
168
|
+
var _this8 = this;
|
|
169
|
+
return _asyncToGenerator(function* () {
|
|
170
|
+
return [..._this8.assets.values()].filter((asset) => asset.projectId === projectId);
|
|
171
|
+
})();
|
|
172
|
+
}
|
|
173
|
+
deleteAsset(assetId) {
|
|
174
|
+
var _this9 = this;
|
|
175
|
+
return _asyncToGenerator(function* () {
|
|
176
|
+
_this9.assets.delete(assetId);
|
|
177
|
+
})();
|
|
178
|
+
}
|
|
179
|
+
createFolder(folder) {
|
|
180
|
+
var _this10 = this;
|
|
181
|
+
return _asyncToGenerator(function* () {
|
|
182
|
+
_this10.folders.set(folder.id, folder);
|
|
183
|
+
return folder;
|
|
184
|
+
})();
|
|
185
|
+
}
|
|
186
|
+
updateFolder(folder) {
|
|
187
|
+
var _this11 = this;
|
|
188
|
+
return _asyncToGenerator(function* () {
|
|
189
|
+
_this11.folders.set(folder.id, folder);
|
|
190
|
+
return folder;
|
|
191
|
+
})();
|
|
192
|
+
}
|
|
193
|
+
getFolder(folderId) {
|
|
194
|
+
var _this12 = this;
|
|
195
|
+
return _asyncToGenerator(function* () {
|
|
196
|
+
return _this12.folders.get(folderId);
|
|
197
|
+
})();
|
|
198
|
+
}
|
|
199
|
+
listFolders(projectId) {
|
|
200
|
+
var _this13 = this;
|
|
201
|
+
return _asyncToGenerator(function* () {
|
|
202
|
+
return [..._this13.folders.values()].filter((folder) => folder.projectId === projectId).sort((a, b) => a.name.localeCompare(b.name));
|
|
203
|
+
})();
|
|
204
|
+
}
|
|
205
|
+
deleteFolder(folderId) {
|
|
206
|
+
var _this14 = this;
|
|
207
|
+
return _asyncToGenerator(function* () {
|
|
208
|
+
_this14.folders.delete(folderId);
|
|
209
|
+
})();
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
//#endregion
|
|
213
|
+
//#region src/testing/MockUtils.ts
|
|
214
|
+
const appendCdnSelector = (url, options) => {
|
|
215
|
+
if (options.lens && options.transform) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Specify either a lens or a transform, not both" });
|
|
216
|
+
if (options.lens) return `${url}/@${encodeURIComponent(options.lens)}`;
|
|
217
|
+
if (!options.transform) return url;
|
|
218
|
+
return `${url}/${encodeURI(options.transform.replace(/^\/+/, ""))}`;
|
|
219
|
+
};
|
|
220
|
+
const inferAssetType = (options) => {
|
|
221
|
+
if ("url" in options) return "website";
|
|
222
|
+
const type = "content" in options ? options.content.type : options.part.type;
|
|
223
|
+
if (type.startsWith("image/") || [
|
|
224
|
+
"jpg",
|
|
225
|
+
"jpeg",
|
|
226
|
+
"png",
|
|
227
|
+
"gif",
|
|
228
|
+
"webp",
|
|
229
|
+
"avif"
|
|
230
|
+
].includes(type)) return "image";
|
|
231
|
+
if (type.startsWith("video/")) return "video";
|
|
232
|
+
if (type.startsWith("audio/")) return "audio";
|
|
233
|
+
if (type === "text/plain" || type === "txt" || type.startsWith("text/")) return "plaintext-document";
|
|
234
|
+
if (type.includes("pdf") || type.includes("document") || [
|
|
235
|
+
"pdf",
|
|
236
|
+
"doc",
|
|
237
|
+
"docx"
|
|
238
|
+
].includes(type)) return "multimedia-document";
|
|
239
|
+
return "file";
|
|
240
|
+
};
|
|
241
|
+
const createPage = (items, query) => {
|
|
242
|
+
var _query$pageIndex, _query$pageSize;
|
|
243
|
+
const pageIndex = (_query$pageIndex = query.pageIndex) !== null && _query$pageIndex !== void 0 ? _query$pageIndex : 0;
|
|
244
|
+
const pageSize = (_query$pageSize = query.pageSize) !== null && _query$pageSize !== void 0 ? _query$pageSize : 10;
|
|
245
|
+
const start = pageIndex * pageSize;
|
|
246
|
+
return {
|
|
247
|
+
items: items.slice(start, start + pageSize),
|
|
248
|
+
total: items.length,
|
|
249
|
+
pageIndex,
|
|
250
|
+
pageSize,
|
|
251
|
+
ordering: [],
|
|
252
|
+
hasMore: start + pageSize < items.length
|
|
253
|
+
};
|
|
254
|
+
};
|
|
255
|
+
//#endregion
|
|
256
|
+
//#region src/testing/MockCalmLensClient.ts
|
|
257
|
+
const _excluded = ["assetIdentifier"];
|
|
258
|
+
const _excluded2 = ["assetIdentifier"];
|
|
259
|
+
const _excluded3 = ["assetId"];
|
|
260
|
+
const _excluded4 = ["assetId"];
|
|
261
|
+
const _excluded5 = ["assetId"];
|
|
262
|
+
const _excluded6 = ["folderId"];
|
|
263
|
+
const assertValidUploadMimeType = (mimeType) => {
|
|
264
|
+
if (isRejectedUploadMimeType(mimeType)) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_MIME_TYPE, {
|
|
265
|
+
message: getRejectedUploadMimeTypeError(mimeType),
|
|
266
|
+
details: { mimeType }
|
|
267
|
+
});
|
|
268
|
+
};
|
|
269
|
+
const toFailureError = (failure) => {
|
|
270
|
+
if (failure === "transport-error") return calmLensError({ id: "sdk/transport-error" }, {
|
|
271
|
+
message: "Request failed",
|
|
272
|
+
cause: /* @__PURE__ */ new TypeError("Simulated network failure")
|
|
273
|
+
});
|
|
274
|
+
if (failure === "timeout") return calmLensError({ id: "sdk/timeout" }, {
|
|
275
|
+
message: "Request aborted",
|
|
276
|
+
cause: new DOMException("The operation timed out.", "TimeoutError")
|
|
277
|
+
});
|
|
278
|
+
return failure;
|
|
279
|
+
};
|
|
280
|
+
var MockCalmLensClient = class {
|
|
281
|
+
/** Accepts the same options as `CalmLensClient` (validated the same way), plus `mockOptions`. */
|
|
282
|
+
constructor(options) {
|
|
283
|
+
var _options$mockOptions$, _options$mockOptions, _options$mockOptions$2, _options$mockOptions2, _options$mockOptions$3, _options$mockOptions3, _options$mockOptions$4, _options$mockOptions4, _options$mockOptions$5, _options$mockOptions5, _options$mockOptions$6, _options$mockOptions6, _options$mockOptions$7, _options$mockOptions7, _options$cdnBaseUrl;
|
|
284
|
+
this.options = options;
|
|
285
|
+
this.lenses = /* @__PURE__ */ new Map();
|
|
286
|
+
this.pendingFailures = [];
|
|
287
|
+
this.calls = [];
|
|
288
|
+
validateClientOptions(options);
|
|
289
|
+
this.databaseStorage = (_options$mockOptions$ = (_options$mockOptions = options.mockOptions) === null || _options$mockOptions === void 0 ? void 0 : _options$mockOptions.databaseStorage) !== null && _options$mockOptions$ !== void 0 ? _options$mockOptions$ : new InMemoryMockDatabaseStorage();
|
|
290
|
+
this.imageStorage = (_options$mockOptions$2 = (_options$mockOptions2 = options.mockOptions) === null || _options$mockOptions2 === void 0 ? void 0 : _options$mockOptions2.imageStorage) !== null && _options$mockOptions$2 !== void 0 ? _options$mockOptions$2 : new InMemoryMockImageStorage();
|
|
291
|
+
this.createId = (_options$mockOptions$3 = (_options$mockOptions3 = options.mockOptions) === null || _options$mockOptions3 === void 0 ? void 0 : _options$mockOptions3.createId) !== null && _options$mockOptions$3 !== void 0 ? _options$mockOptions$3 : crypto.randomUUID.bind(crypto);
|
|
292
|
+
this.now = (_options$mockOptions$4 = (_options$mockOptions4 = options.mockOptions) === null || _options$mockOptions4 === void 0 ? void 0 : _options$mockOptions4.now) !== null && _options$mockOptions$4 !== void 0 ? _options$mockOptions$4 : Date.now;
|
|
293
|
+
this.queuedStatus = (_options$mockOptions$5 = (_options$mockOptions5 = options.mockOptions) === null || _options$mockOptions5 === void 0 ? void 0 : _options$mockOptions5.queuedStatus) !== null && _options$mockOptions$5 !== void 0 ? _options$mockOptions$5 : "pending";
|
|
294
|
+
this.analyzedStatus = (_options$mockOptions$6 = (_options$mockOptions6 = options.mockOptions) === null || _options$mockOptions6 === void 0 ? void 0 : _options$mockOptions6.analyzedStatus) !== null && _options$mockOptions$6 !== void 0 ? _options$mockOptions$6 : "approved";
|
|
295
|
+
this.apiKeyGrants = getMockApiKeyGrants(options.apiKey);
|
|
296
|
+
this.signedUrlBaseUrl = (_options$mockOptions$7 = (_options$mockOptions7 = options.mockOptions) === null || _options$mockOptions7 === void 0 ? void 0 : _options$mockOptions7.signedUrlBaseUrl) !== null && _options$mockOptions$7 !== void 0 ? _options$mockOptions$7 : "mock://calmlens";
|
|
297
|
+
this.cdnBaseUrl = (_options$cdnBaseUrl = options.cdnBaseUrl) !== null && _options$cdnBaseUrl !== void 0 ? _options$cdnBaseUrl : "mock://calmlens/v1";
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Makes the next call (or the next call to `operation`) throw `failure` instead of running,
|
|
301
|
+
* as if the request never completed. Queue several to fail several calls in a row.
|
|
302
|
+
*/
|
|
303
|
+
failNextRequest(failure = "transport-error", { operation } = {}) {
|
|
304
|
+
this.pendingFailures.push({
|
|
305
|
+
failure,
|
|
306
|
+
operation
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
/** Calls recorded for one operation, oldest first. */
|
|
310
|
+
callsTo(operation) {
|
|
311
|
+
return this.calls.filter((call) => call.operation === operation);
|
|
312
|
+
}
|
|
313
|
+
begin(operation, options) {
|
|
314
|
+
this.calls.push({
|
|
315
|
+
operation,
|
|
316
|
+
options
|
|
317
|
+
});
|
|
318
|
+
const index = this.pendingFailures.findIndex((pending) => pending.operation === void 0 || pending.operation === operation);
|
|
319
|
+
if (index !== -1) {
|
|
320
|
+
const [pending] = this.pendingFailures.splice(index, 1);
|
|
321
|
+
throw toFailureError(pending.failure);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
get cdn() {
|
|
325
|
+
var _this = this;
|
|
326
|
+
return {
|
|
327
|
+
getAssetUrl: (_ref) => {
|
|
328
|
+
var _options$resource;
|
|
329
|
+
let { assetIdentifier } = _ref, options = _objectWithoutProperties(_ref, _excluded);
|
|
330
|
+
if (!assetIdentifier) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Asset identifier is required" });
|
|
331
|
+
const resource = (_options$resource = options.resource) !== null && _options$resource !== void 0 ? _options$resource : "content";
|
|
332
|
+
const url = `${this.cdnBaseUrl.replace(/\/$/, "")}/assets/${encodeURIComponent(this.options.projectId)}/${encodeURIComponent(assetIdentifier)}/${resource}`;
|
|
333
|
+
return appendCdnSelector(url, options);
|
|
334
|
+
},
|
|
335
|
+
serve: function() {
|
|
336
|
+
var _ref2 = _asyncToGenerator(function* (serveOptions) {
|
|
337
|
+
var _asset$folderId, _await$this$databaseS, _this$databaseStorage, _this$databaseStorage2, _storedContent$type;
|
|
338
|
+
_this.begin("cdn.serve", serveOptions);
|
|
339
|
+
const { assetIdentifier } = serveOptions, options = _objectWithoutProperties(serveOptions, _excluded2);
|
|
340
|
+
if (!assetIdentifier) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Asset identifier is required" });
|
|
341
|
+
const asset = (yield _this.databaseStorage.listAssets(_this.options.projectId)).find((asset) => asset.id === assetIdentifier || asset.externalId === assetIdentifier);
|
|
342
|
+
if (!asset) return new Response("Asset not found", { status: 404 });
|
|
343
|
+
if (asset.visibility !== "public" && !permits(_this.apiKeyGrants, "assets:download", (_asset$folderId = asset.folderId) !== null && _asset$folderId !== void 0 ? _asset$folderId : null, (_await$this$databaseS = yield (_this$databaseStorage = (_this$databaseStorage2 = _this.databaseStorage).listFolders) === null || _this$databaseStorage === void 0 ? void 0 : _this$databaseStorage.call(_this$databaseStorage2, _this.options.projectId)) !== null && _await$this$databaseS !== void 0 ? _await$this$databaseS : [])) return new Response(JSON.stringify({
|
|
344
|
+
code: "asset/api-key-missing-permission",
|
|
345
|
+
message: "This API key needs assets:download permission for this asset’s folder."
|
|
346
|
+
}), {
|
|
347
|
+
status: 403,
|
|
348
|
+
headers: { "Content-Type": "application/json" }
|
|
349
|
+
});
|
|
350
|
+
const storedContent = yield _this.imageStorage.getContent(asset.id);
|
|
351
|
+
if (!storedContent) return new Response("Asset content not found", { status: 404 });
|
|
352
|
+
const parts = [...storedContent.parts.entries()].sort(([left], [right]) => left - right).map(([, value]) => value);
|
|
353
|
+
const byteLength = parts.reduce((sum, value) => sum + value.byteLength, 0);
|
|
354
|
+
const bytes = new Uint8Array(byteLength);
|
|
355
|
+
let offset = 0;
|
|
356
|
+
for (const part of parts) {
|
|
357
|
+
bytes.set(part, offset);
|
|
358
|
+
offset += part.byteLength;
|
|
359
|
+
}
|
|
360
|
+
return new Response(bytes, {
|
|
361
|
+
status: 200,
|
|
362
|
+
headers: {
|
|
363
|
+
"Content-Type": (_storedContent$type = storedContent.type) !== null && _storedContent$type !== void 0 ? _storedContent$type : "application/octet-stream",
|
|
364
|
+
"X-Mock-CalmLens-CDN-URL": _this.cdn.getAssetUrl(_objectSpread2({ assetIdentifier }, options))
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
return function serve(_x) {
|
|
369
|
+
return _ref2.apply(this, arguments);
|
|
370
|
+
};
|
|
371
|
+
}()
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
get events() {
|
|
375
|
+
var _this2 = this;
|
|
376
|
+
return {
|
|
377
|
+
/** The mock does not record events; it always returns an empty page at "now". */
|
|
378
|
+
list: function() {
|
|
379
|
+
var _ref3 = _asyncToGenerator(function* (options = {}) {
|
|
380
|
+
var _options$after;
|
|
381
|
+
_this2.begin("events.list", options);
|
|
382
|
+
return {
|
|
383
|
+
events: [],
|
|
384
|
+
cursor: (_options$after = options.after) !== null && _options$after !== void 0 ? _options$after : `${_this2.now()}_`,
|
|
385
|
+
hasMore: false
|
|
386
|
+
};
|
|
387
|
+
});
|
|
388
|
+
return function list() {
|
|
389
|
+
return _ref3.apply(this, arguments);
|
|
390
|
+
};
|
|
391
|
+
}() };
|
|
392
|
+
}
|
|
393
|
+
get text() {
|
|
394
|
+
var _this3 = this;
|
|
395
|
+
return { moderate: function() {
|
|
396
|
+
var _ref4 = _asyncToGenerator(function* (options) {
|
|
397
|
+
_this3.begin("text.moderate", options);
|
|
398
|
+
return _this3.moderateAsset(toTextAssetOptions(options));
|
|
399
|
+
});
|
|
400
|
+
return function moderate(_x2) {
|
|
401
|
+
return _ref4.apply(this, arguments);
|
|
402
|
+
};
|
|
403
|
+
}() };
|
|
404
|
+
}
|
|
405
|
+
get assets() {
|
|
406
|
+
var _this4 = this;
|
|
407
|
+
return {
|
|
408
|
+
list: function() {
|
|
409
|
+
var _ref5 = _asyncToGenerator(function* (options) {
|
|
410
|
+
var _options$pageIndex;
|
|
411
|
+
_this4.begin("assets.list", options);
|
|
412
|
+
const assets = yield _this4.databaseStorage.listAssets(_this4.options.projectId);
|
|
413
|
+
return createPage(assets, _objectSpread2(_objectSpread2({}, options), {}, { pageIndex: (_options$pageIndex = options.pageIndex) !== null && _options$pageIndex !== void 0 ? _options$pageIndex : 0 }));
|
|
414
|
+
});
|
|
415
|
+
return function list(_x3) {
|
|
416
|
+
return _ref5.apply(this, arguments);
|
|
417
|
+
};
|
|
418
|
+
}(),
|
|
419
|
+
retrieve: function() {
|
|
420
|
+
var _ref6 = _asyncToGenerator(function* (options) {
|
|
421
|
+
_this4.begin("assets.retrieve", options);
|
|
422
|
+
const { assetId } = options;
|
|
423
|
+
if (!assetId) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Asset ID is required" });
|
|
424
|
+
const asset = yield _this4.databaseStorage.getAsset(assetId);
|
|
425
|
+
if (!asset) throw calmLensError(PUBLIC_ERROR_CODES.ASSET_NOT_FOUND);
|
|
426
|
+
return asset;
|
|
427
|
+
});
|
|
428
|
+
return function retrieve(_x4) {
|
|
429
|
+
return _ref6.apply(this, arguments);
|
|
430
|
+
};
|
|
431
|
+
}(),
|
|
432
|
+
listChildren: function() {
|
|
433
|
+
var _ref7 = _asyncToGenerator(function* (childrenOptions) {
|
|
434
|
+
var _options$pageIndex2;
|
|
435
|
+
_this4.begin("assets.listChildren", childrenOptions);
|
|
436
|
+
const { assetId } = childrenOptions, options = _objectWithoutProperties(childrenOptions, _excluded3);
|
|
437
|
+
if (!assetId) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Asset ID is required" });
|
|
438
|
+
const assets = yield _this4.databaseStorage.listAssets(_this4.options.projectId);
|
|
439
|
+
return createPage(assets.filter((asset) => asset.parentId === assetId), _objectSpread2(_objectSpread2({}, options), {}, { pageIndex: (_options$pageIndex2 = options.pageIndex) !== null && _options$pageIndex2 !== void 0 ? _options$pageIndex2 : 0 }));
|
|
440
|
+
});
|
|
441
|
+
return function listChildren(_x5) {
|
|
442
|
+
return _ref7.apply(this, arguments);
|
|
443
|
+
};
|
|
444
|
+
}(),
|
|
445
|
+
update: function() {
|
|
446
|
+
var _ref8 = _asyncToGenerator(function* (options) {
|
|
447
|
+
_this4.begin("assets.update", options);
|
|
448
|
+
const { assetId } = options, body = _objectWithoutProperties(options, _excluded4);
|
|
449
|
+
if (!assetId) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Asset ID is required" });
|
|
450
|
+
const asset = yield _this4.databaseStorage.getAsset(assetId);
|
|
451
|
+
if (!asset || asset.projectId !== _this4.options.projectId) throw calmLensError(PUBLIC_ERROR_CODES.ASSET_NOT_FOUND);
|
|
452
|
+
const changes = Object.fromEntries(Object.entries(body).filter(([, value]) => value !== void 0));
|
|
453
|
+
return _this4.databaseStorage.updateAsset(_objectSpread2(_objectSpread2(_objectSpread2({}, asset), changes), {}, { updatedAt: _this4.now() }));
|
|
454
|
+
});
|
|
455
|
+
return function update(_x6) {
|
|
456
|
+
return _ref8.apply(this, arguments);
|
|
457
|
+
};
|
|
458
|
+
}(),
|
|
459
|
+
create: function() {
|
|
460
|
+
var _ref9 = _asyncToGenerator(function* (options) {
|
|
461
|
+
_this4.begin("assets.create", options);
|
|
462
|
+
return _this4.createAsset(options, _this4.queuedStatus);
|
|
463
|
+
});
|
|
464
|
+
return function create(_x7) {
|
|
465
|
+
return _ref9.apply(this, arguments);
|
|
466
|
+
};
|
|
467
|
+
}(),
|
|
468
|
+
moderate: function() {
|
|
469
|
+
var _ref10 = _asyncToGenerator(function* (options) {
|
|
470
|
+
_this4.begin("assets.moderate", options);
|
|
471
|
+
return _this4.moderateAsset(options);
|
|
472
|
+
});
|
|
473
|
+
return function moderate(_x8) {
|
|
474
|
+
return _ref10.apply(this, arguments);
|
|
475
|
+
};
|
|
476
|
+
}(),
|
|
477
|
+
uploadPart: function() {
|
|
478
|
+
var _ref11 = _asyncToGenerator(function* (options) {
|
|
479
|
+
var _asset$uploadPartsRec;
|
|
480
|
+
_this4.begin("assets.uploadPart", options);
|
|
481
|
+
const { assetId, part } = options;
|
|
482
|
+
if (!assetId) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Asset ID is required" });
|
|
483
|
+
if (!part) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Part options are required" });
|
|
484
|
+
const asset = yield _this4.databaseStorage.getAsset(assetId);
|
|
485
|
+
if (!asset) throw calmLensError(PUBLIC_ERROR_CODES.ASSET_NOT_FOUND);
|
|
486
|
+
const validation = validateAssetPayload(part, {
|
|
487
|
+
multipart: true,
|
|
488
|
+
isFinal: part.isFinal
|
|
489
|
+
});
|
|
490
|
+
if (!validation.ok) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: validation.error });
|
|
491
|
+
yield _this4.imageStorage.putPart(assetId, part);
|
|
492
|
+
const updated = _objectSpread2(_objectSpread2({}, asset), {}, {
|
|
493
|
+
status: part.isFinal ? _this4.queuedStatus : "uploading",
|
|
494
|
+
uploadPartsReceived: Math.max((_asset$uploadPartsRec = asset.uploadPartsReceived) !== null && _asset$uploadPartsRec !== void 0 ? _asset$uploadPartsRec : 0, part.partNumber),
|
|
495
|
+
updatedAt: _this4.now()
|
|
496
|
+
});
|
|
497
|
+
return _this4.databaseStorage.updateAsset(updated);
|
|
498
|
+
});
|
|
499
|
+
return function uploadPart(_x9) {
|
|
500
|
+
return _ref11.apply(this, arguments);
|
|
501
|
+
};
|
|
502
|
+
}(),
|
|
503
|
+
createSignedUrl: function() {
|
|
504
|
+
var _ref12 = _asyncToGenerator(function* (signedUrlOptions) {
|
|
505
|
+
var _options$expiresInSec, _options$resource2;
|
|
506
|
+
_this4.begin("assets.createSignedUrl", signedUrlOptions);
|
|
507
|
+
const { assetId } = signedUrlOptions, options = _objectWithoutProperties(signedUrlOptions, _excluded5);
|
|
508
|
+
if (!assetId) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Asset ID is required" });
|
|
509
|
+
if (!(yield _this4.databaseStorage.getAsset(assetId))) throw calmLensError(PUBLIC_ERROR_CODES.ASSET_NOT_FOUND);
|
|
510
|
+
const expiresInSeconds = (_options$expiresInSec = options.expiresInSeconds) !== null && _options$expiresInSec !== void 0 ? _options$expiresInSec : 900;
|
|
511
|
+
const resource = (_options$resource2 = options.resource) !== null && _options$resource2 !== void 0 ? _options$resource2 : "content";
|
|
512
|
+
if (options.lens && options.transform) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Specify either a lens or a transform, not both" });
|
|
513
|
+
const selector = options.lens ? `&lens=${encodeURIComponent(options.lens)}` : options.transform ? `&transform=${encodeURIComponent(options.transform)}` : "";
|
|
514
|
+
return {
|
|
515
|
+
url: `${_this4.signedUrlBaseUrl}/assets/${assetId}/${resource}?expiresInSeconds=${expiresInSeconds}${selector}`,
|
|
516
|
+
expiresAt: _this4.now() + expiresInSeconds * 1e3
|
|
517
|
+
};
|
|
518
|
+
});
|
|
519
|
+
return function createSignedUrl(_x10) {
|
|
520
|
+
return _ref12.apply(this, arguments);
|
|
521
|
+
};
|
|
522
|
+
}(),
|
|
523
|
+
move: function() {
|
|
524
|
+
var _ref13 = _asyncToGenerator(function* (options) {
|
|
525
|
+
_this4.begin("assets.move", options);
|
|
526
|
+
const { assetId, folderId } = options;
|
|
527
|
+
if (!assetId) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Asset ID is required" });
|
|
528
|
+
const asset = yield _this4.databaseStorage.getAsset(assetId);
|
|
529
|
+
if (!asset || asset.projectId !== _this4.options.projectId) throw calmLensError(PUBLIC_ERROR_CODES.ASSET_NOT_FOUND);
|
|
530
|
+
if (folderId !== null && folderId !== void 0) {
|
|
531
|
+
if (!(yield _this4.resolveFolder(folderId))) throw calmLensError(PUBLIC_ERROR_CODES.FOLDER_NOT_FOUND);
|
|
532
|
+
}
|
|
533
|
+
const updated = _objectSpread2(_objectSpread2({}, asset), {}, {
|
|
534
|
+
folderId: folderId !== null && folderId !== void 0 ? folderId : null,
|
|
535
|
+
updatedAt: _this4.now()
|
|
536
|
+
});
|
|
537
|
+
return _this4.databaseStorage.updateAsset(updated);
|
|
538
|
+
});
|
|
539
|
+
return function move(_x11) {
|
|
540
|
+
return _ref13.apply(this, arguments);
|
|
541
|
+
};
|
|
542
|
+
}(),
|
|
543
|
+
retry: function() {
|
|
544
|
+
var _ref14 = _asyncToGenerator(function* (options) {
|
|
545
|
+
_this4.begin("assets.retry", options);
|
|
546
|
+
const { assetId } = options;
|
|
547
|
+
if (!assetId) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Asset ID is required" });
|
|
548
|
+
const asset = yield _this4.databaseStorage.getAsset(assetId);
|
|
549
|
+
if (!asset || asset.projectId !== _this4.options.projectId) throw calmLensError(PUBLIC_ERROR_CODES.ASSET_NOT_FOUND);
|
|
550
|
+
if (asset.status !== "error") throw calmLensError(PUBLIC_ERROR_CODES.ASSET_NOT_RETRYABLE);
|
|
551
|
+
return _this4.databaseStorage.updateAsset(_objectSpread2(_objectSpread2({}, asset), {}, {
|
|
552
|
+
status: "pending",
|
|
553
|
+
updatedAt: _this4.now()
|
|
554
|
+
}));
|
|
555
|
+
});
|
|
556
|
+
return function retry(_x12) {
|
|
557
|
+
return _ref14.apply(this, arguments);
|
|
558
|
+
};
|
|
559
|
+
}()
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
get folders() {
|
|
563
|
+
var _this5 = this;
|
|
564
|
+
return {
|
|
565
|
+
list: function() {
|
|
566
|
+
var _ref15 = _asyncToGenerator(function* () {
|
|
567
|
+
_this5.begin("folders.list", void 0);
|
|
568
|
+
return [..._this5.databaseStorage.listFolders ? yield _this5.databaseStorage.listFolders(_this5.options.projectId) : []].sort((a, b) => a.name.localeCompare(b.name));
|
|
569
|
+
});
|
|
570
|
+
return function list() {
|
|
571
|
+
return _ref15.apply(this, arguments);
|
|
572
|
+
};
|
|
573
|
+
}(),
|
|
574
|
+
retrieve: function() {
|
|
575
|
+
var _ref16 = _asyncToGenerator(function* (options) {
|
|
576
|
+
_this5.begin("folders.retrieve", options);
|
|
577
|
+
const { folderId } = options;
|
|
578
|
+
if (!folderId) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Folder ID is required" });
|
|
579
|
+
const folder = yield _this5.resolveFolder(folderId);
|
|
580
|
+
if (!folder) throw calmLensError(PUBLIC_ERROR_CODES.FOLDER_NOT_FOUND);
|
|
581
|
+
return folder;
|
|
582
|
+
});
|
|
583
|
+
return function retrieve(_x13) {
|
|
584
|
+
return _ref16.apply(this, arguments);
|
|
585
|
+
};
|
|
586
|
+
}(),
|
|
587
|
+
create: function() {
|
|
588
|
+
var _ref17 = _asyncToGenerator(function* (options) {
|
|
589
|
+
var _options$parentId, _options$parentId2;
|
|
590
|
+
_this5.begin("folders.create", options);
|
|
591
|
+
if (!options.name) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Folder name is required" });
|
|
592
|
+
if (options.parentId) {
|
|
593
|
+
if (!(yield _this5.resolveFolder(options.parentId))) throw calmLensError(PUBLIC_ERROR_CODES.FOLDER_NOT_FOUND);
|
|
594
|
+
}
|
|
595
|
+
yield _this5.assertUniqueFolderName(options.name, (_options$parentId = options.parentId) !== null && _options$parentId !== void 0 ? _options$parentId : null);
|
|
596
|
+
const folder = {
|
|
597
|
+
id: _this5.createId(),
|
|
598
|
+
projectId: _this5.options.projectId,
|
|
599
|
+
parentId: (_options$parentId2 = options.parentId) !== null && _options$parentId2 !== void 0 ? _options$parentId2 : null,
|
|
600
|
+
name: options.name,
|
|
601
|
+
createdAt: _this5.now(),
|
|
602
|
+
updatedAt: _this5.now()
|
|
603
|
+
};
|
|
604
|
+
if (_this5.databaseStorage.createFolder) return yield _this5.databaseStorage.createFolder(folder);
|
|
605
|
+
return folder;
|
|
606
|
+
});
|
|
607
|
+
return function create(_x14) {
|
|
608
|
+
return _ref17.apply(this, arguments);
|
|
609
|
+
};
|
|
610
|
+
}(),
|
|
611
|
+
update: function() {
|
|
612
|
+
var _ref18 = _asyncToGenerator(function* (options) {
|
|
613
|
+
_this5.begin("folders.update", options);
|
|
614
|
+
const { folderId } = options, body = _objectWithoutProperties(options, _excluded6);
|
|
615
|
+
if (!folderId) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Folder ID is required" });
|
|
616
|
+
const folder = yield _this5.resolveFolder(folderId);
|
|
617
|
+
if (!folder) throw calmLensError(PUBLIC_ERROR_CODES.FOLDER_NOT_FOUND);
|
|
618
|
+
if (body.name !== void 0 && body.name !== folder.name) {
|
|
619
|
+
var _folder$parentId;
|
|
620
|
+
yield _this5.assertUniqueFolderName(body.name, (_folder$parentId = folder.parentId) !== null && _folder$parentId !== void 0 ? _folder$parentId : null, folderId);
|
|
621
|
+
}
|
|
622
|
+
const updated = _objectSpread2(_objectSpread2(_objectSpread2({}, folder), body.name !== void 0 ? { name: body.name } : {}), {}, { updatedAt: _this5.now() });
|
|
623
|
+
if (_this5.databaseStorage.updateFolder) return yield _this5.databaseStorage.updateFolder(updated);
|
|
624
|
+
return updated;
|
|
625
|
+
});
|
|
626
|
+
return function update(_x15) {
|
|
627
|
+
return _ref18.apply(this, arguments);
|
|
628
|
+
};
|
|
629
|
+
}(),
|
|
630
|
+
delete: function() {
|
|
631
|
+
var _ref19 = _asyncToGenerator(function* (options) {
|
|
632
|
+
_this5.begin("folders.delete", options);
|
|
633
|
+
const { folderId } = options;
|
|
634
|
+
if (!folderId) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Folder ID is required" });
|
|
635
|
+
if (!(yield _this5.resolveFolder(folderId))) throw calmLensError(PUBLIC_ERROR_CODES.FOLDER_NOT_FOUND);
|
|
636
|
+
const hasAssets = (yield _this5.databaseStorage.listAssets(_this5.options.projectId)).some((asset) => asset.folderId === folderId);
|
|
637
|
+
const hasChildren = (_this5.databaseStorage.listFolders ? yield _this5.databaseStorage.listFolders(_this5.options.projectId) : []).some((f) => f.parentId === folderId);
|
|
638
|
+
if (hasAssets || hasChildren) throw calmLensError(PUBLIC_ERROR_CODES.FOLDER_NOT_EMPTY, { details: {
|
|
639
|
+
hasAssets,
|
|
640
|
+
hasChildren
|
|
641
|
+
} });
|
|
642
|
+
if (_this5.databaseStorage.deleteFolder) yield _this5.databaseStorage.deleteFolder(folderId);
|
|
643
|
+
});
|
|
644
|
+
return function _delete(_x16) {
|
|
645
|
+
return _ref19.apply(this, arguments);
|
|
646
|
+
};
|
|
647
|
+
}(),
|
|
648
|
+
move: function() {
|
|
649
|
+
var _ref20 = _asyncToGenerator(function* (options) {
|
|
650
|
+
_this5.begin("folders.move", options);
|
|
651
|
+
const { folderId, parentId } = options;
|
|
652
|
+
if (!folderId) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Folder ID is required" });
|
|
653
|
+
const folder = yield _this5.resolveFolder(folderId);
|
|
654
|
+
if (!folder) throw calmLensError(PUBLIC_ERROR_CODES.FOLDER_NOT_FOUND);
|
|
655
|
+
const targetParentId = parentId !== null && parentId !== void 0 ? parentId : null;
|
|
656
|
+
if (targetParentId) {
|
|
657
|
+
const parent = yield _this5.resolveFolder(targetParentId);
|
|
658
|
+
if (!parent) throw calmLensError(PUBLIC_ERROR_CODES.FOLDER_NOT_FOUND);
|
|
659
|
+
let candidate = parent;
|
|
660
|
+
const visited = /* @__PURE__ */ new Set();
|
|
661
|
+
while (candidate) {
|
|
662
|
+
if (candidate.id === folderId || visited.has(candidate.id)) throw calmLensError(PUBLIC_ERROR_CODES.FOLDER_PARENT_CYCLE);
|
|
663
|
+
visited.add(candidate.id);
|
|
664
|
+
candidate = candidate.parentId ? yield _this5.resolveFolder(candidate.parentId) : void 0;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
if (targetParentId !== folder.parentId) yield _this5.assertUniqueFolderName(folder.name, targetParentId, folderId);
|
|
668
|
+
const updated = _objectSpread2(_objectSpread2({}, folder), {}, {
|
|
669
|
+
parentId: targetParentId,
|
|
670
|
+
updatedAt: _this5.now()
|
|
671
|
+
});
|
|
672
|
+
if (_this5.databaseStorage.updateFolder) return yield _this5.databaseStorage.updateFolder(updated);
|
|
673
|
+
return updated;
|
|
674
|
+
});
|
|
675
|
+
return function move(_x17) {
|
|
676
|
+
return _ref20.apply(this, arguments);
|
|
677
|
+
};
|
|
678
|
+
}()
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
ensureLens(options) {
|
|
682
|
+
var _this6 = this;
|
|
683
|
+
return _asyncToGenerator(function* () {
|
|
684
|
+
_this6.begin("ensureLens", options);
|
|
685
|
+
return _this6.ensureLensDefinition(options);
|
|
686
|
+
})();
|
|
687
|
+
}
|
|
688
|
+
ensureLensDefinition(options) {
|
|
689
|
+
var _existing$description, _options$description, _existing$transforms, _options$transforms;
|
|
690
|
+
const existing = this.lenses.get(options.identifier);
|
|
691
|
+
if (!existing) {
|
|
692
|
+
const lens = _objectSpread2(_objectSpread2({
|
|
693
|
+
id: this.createId(),
|
|
694
|
+
projectId: this.options.projectId,
|
|
695
|
+
userId: null
|
|
696
|
+
}, options), {}, {
|
|
697
|
+
createdAt: this.now(),
|
|
698
|
+
updatedAt: this.now()
|
|
699
|
+
});
|
|
700
|
+
this.lenses.set(lens.identifier, lens);
|
|
701
|
+
return lens;
|
|
702
|
+
}
|
|
703
|
+
if (existing.name === options.name && ((_existing$description = existing.description) !== null && _existing$description !== void 0 ? _existing$description : null) === ((_options$description = options.description) !== null && _options$description !== void 0 ? _options$description : null) && existing.type === options.type && existing.active === options.active && stringifyJsonCanonical((_existing$transforms = existing.transforms) !== null && _existing$transforms !== void 0 ? _existing$transforms : null) === stringifyJsonCanonical((_options$transforms = options.transforms) !== null && _options$transforms !== void 0 ? _options$transforms : null) && existing.version === options.version) return existing;
|
|
704
|
+
if (options.version > existing.version) {
|
|
705
|
+
const lens = _objectSpread2(_objectSpread2(_objectSpread2({}, existing), options), {}, { updatedAt: this.now() });
|
|
706
|
+
this.lenses.set(lens.identifier, lens);
|
|
707
|
+
return lens;
|
|
708
|
+
}
|
|
709
|
+
throw calmLensError(PUBLIC_ERROR_CODES.LENS_VERSION_CONFLICT, { details: {
|
|
710
|
+
currentVersion: existing.version,
|
|
711
|
+
minimumVersion: existing.version + 1,
|
|
712
|
+
requestedVersion: options.version
|
|
713
|
+
} });
|
|
714
|
+
}
|
|
715
|
+
ensureLenses(options) {
|
|
716
|
+
var _this7 = this;
|
|
717
|
+
return _asyncToGenerator(function* () {
|
|
718
|
+
_this7.begin("ensureLenses", options);
|
|
719
|
+
if (options.lenses.length === 0) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "At least one lens is required" });
|
|
720
|
+
return options.lenses.map((option) => _this7.ensureLensDefinition(option));
|
|
721
|
+
})();
|
|
722
|
+
}
|
|
723
|
+
moderateAsset(options) {
|
|
724
|
+
var _this8 = this;
|
|
725
|
+
return _asyncToGenerator(function* () {
|
|
726
|
+
if ("content" in options && "plainText" in options.content && (typeof options.content.plainText !== "string" || !options.content.plainText.trim())) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Text to moderate must be a non-empty string" });
|
|
727
|
+
return _this8.createAsset(options, _this8.analyzedStatus);
|
|
728
|
+
})();
|
|
729
|
+
}
|
|
730
|
+
createAsset(options, status) {
|
|
731
|
+
var _this9 = this;
|
|
732
|
+
return _asyncToGenerator(function* () {
|
|
733
|
+
var _options$folderId, _options$visibility, _options$part$partNum;
|
|
734
|
+
if (!("content" in options) && !("url" in options) && !("part" in options)) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Either file content, URL, or multipart part is required" });
|
|
735
|
+
if (!options.name) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "Asset name is required" });
|
|
736
|
+
if (!("part" in options) && "isFinal" in options) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: "isFinal is only valid for multipart uploads" });
|
|
737
|
+
if ("part" in options && options.part.partNumber && options.part.partNumber > 1) throw calmLensError(PUBLIC_ERROR_CODES.USE_UPLOAD_PART);
|
|
738
|
+
if ("content" in options) {
|
|
739
|
+
assertValidUploadMimeType(options.content.type);
|
|
740
|
+
if (!("plainText" in options.content)) {
|
|
741
|
+
const validation = validateAssetPayload(options.content);
|
|
742
|
+
if (!validation.ok) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: validation.error });
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
if ("part" in options) {
|
|
746
|
+
assertValidUploadMimeType(options.part.type);
|
|
747
|
+
const validation = validateAssetPayload(options.part, {
|
|
748
|
+
multipart: true,
|
|
749
|
+
isFinal: options.part.isFinal
|
|
750
|
+
});
|
|
751
|
+
if (!validation.ok) throw calmLensError(PUBLIC_ERROR_CODES.INVALID_UPLOAD_PAYLOAD, { message: validation.error });
|
|
752
|
+
}
|
|
753
|
+
const id = _this9.createId();
|
|
754
|
+
const now = _this9.now();
|
|
755
|
+
const type = inferAssetType(options);
|
|
756
|
+
const sizeInBytes = _this9.getSizeInBytes(options);
|
|
757
|
+
const asset = {
|
|
758
|
+
id,
|
|
759
|
+
projectId: _this9.options.projectId,
|
|
760
|
+
folderId: (_options$folderId = options.folderId) !== null && _options$folderId !== void 0 ? _options$folderId : null,
|
|
761
|
+
createdAt: now,
|
|
762
|
+
updatedAt: now,
|
|
763
|
+
name: options.name,
|
|
764
|
+
description: options.description,
|
|
765
|
+
externalId: options.externalId,
|
|
766
|
+
externalUrl: "url" in options ? options.url : "content" in options ? options.externalUrl : void 0,
|
|
767
|
+
type,
|
|
768
|
+
metadata: options.metadata,
|
|
769
|
+
status: "part" in options && !options.part.isFinal ? "uploading" : status,
|
|
770
|
+
processingOptions: options.processingOptions,
|
|
771
|
+
visibility: (_options$visibility = options.visibility) !== null && _options$visibility !== void 0 ? _options$visibility : "private",
|
|
772
|
+
sizeInBytes,
|
|
773
|
+
uploadPartsReceived: "part" in options ? (_options$part$partNum = options.part.partNumber) !== null && _options$part$partNum !== void 0 ? _options$part$partNum : 1 : void 0
|
|
774
|
+
};
|
|
775
|
+
if ("content" in options) {
|
|
776
|
+
if (!("plainText" in options.content)) yield _this9.imageStorage.putContent(id, options.content);
|
|
777
|
+
} else if ("part" in options) yield _this9.imageStorage.putPart(id, options.part);
|
|
778
|
+
return _this9.databaseStorage.createAsset(asset);
|
|
779
|
+
})();
|
|
780
|
+
}
|
|
781
|
+
resolveFolder(folderId) {
|
|
782
|
+
var _this10 = this;
|
|
783
|
+
return _asyncToGenerator(function* () {
|
|
784
|
+
if (!_this10.databaseStorage.getFolder) return void 0;
|
|
785
|
+
const folder = yield _this10.databaseStorage.getFolder(folderId);
|
|
786
|
+
if (!folder || folder.projectId !== _this10.options.projectId) return;
|
|
787
|
+
return folder;
|
|
788
|
+
})();
|
|
789
|
+
}
|
|
790
|
+
assertUniqueFolderName(name, parentId, excludeFolderId) {
|
|
791
|
+
var _this11 = this;
|
|
792
|
+
return _asyncToGenerator(function* () {
|
|
793
|
+
if ((_this11.databaseStorage.listFolders ? yield _this11.databaseStorage.listFolders(_this11.options.projectId) : []).find((f) => f.id !== excludeFolderId && f.parentId === (parentId !== null && parentId !== void 0 ? parentId : null) && f.name === name)) throw calmLensError(PUBLIC_ERROR_CODES.DUPLICATE_FOLDER_NAME, { message: `A folder named "${name}" already exists in this location.` });
|
|
794
|
+
})();
|
|
795
|
+
}
|
|
796
|
+
getSizeInBytes(options) {
|
|
797
|
+
if ("content" in options) {
|
|
798
|
+
if ("plainText" in options.content) return new TextEncoder().encode(options.content.plainText).byteLength;
|
|
799
|
+
return getAssetPayloadByteLength(options.content);
|
|
800
|
+
}
|
|
801
|
+
if ("part" in options) {
|
|
802
|
+
var _options$sizeInBytes;
|
|
803
|
+
return (_options$sizeInBytes = options.sizeInBytes) !== null && _options$sizeInBytes !== void 0 ? _options$sizeInBytes : getAssetPayloadByteLength(options.part);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
//#endregion
|
|
808
|
+
export { InMemoryMockDatabaseStorage, InMemoryMockImageStorage, MOCK_API_KEY_PREFIX, MockCalmLensClient, createMockApiKey };
|