@mediaviz/sdk 1.8.0 → 1.9.0-dev.107

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/dist/sdk.esm.js CHANGED
@@ -2,36 +2,181 @@ function getDefaultExportFromCjs (x) {
2
2
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
3
3
  }
4
4
 
5
- var pkce;
6
- var hasRequiredPkce;
5
+ var base64;
6
+ var hasRequiredBase64;
7
7
 
8
- function requirePkce () {
9
- if (hasRequiredPkce) return pkce;
10
- hasRequiredPkce = 1;
8
+ function requireBase64 () {
9
+ if (hasRequiredBase64) return base64;
10
+ hasRequiredBase64 = 1;
11
+
12
+ // Base64URL codec, used by PKCE (encode) and JWT payload decoding (decode).
13
+ // Hand-rolled rather than delegating to atob/btoa, Buffer, or TextDecoder:
14
+ // none of those is present on every target runtime — React Native's Hermes has
15
+ // no Buffer and does not guarantee atob — and the alphabet here is URL-safe and
16
+ // unpadded, which the standard helpers do not produce.
11
17
 
12
- // base64url-encode a Uint8Array without padding
18
+ const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
19
+
20
+ /**
21
+ * @param {Uint8Array} bytes
22
+ * @returns {string} unpadded base64url
23
+ */
13
24
  function base64urlEncode(bytes) {
14
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
15
25
  let result = '';
16
26
  for (let i = 0; i < bytes.length; i += 3) {
17
27
  const b0 = bytes[i];
18
28
  const b1 = i + 1 < bytes.length ? bytes[i + 1] : 0;
19
29
  const b2 = i + 2 < bytes.length ? bytes[i + 2] : 0;
20
- result += chars[b0 >> 2];
21
- result += chars[((b0 & 3) << 4) | (b1 >> 4)];
22
- if (i + 1 < bytes.length) result += chars[((b1 & 0xf) << 2) | (b2 >> 6)];
23
- if (i + 2 < bytes.length) result += chars[b2 & 0x3f];
30
+ result += ALPHABET[b0 >> 2];
31
+ result += ALPHABET[((b0 & 3) << 4) | (b1 >> 4)];
32
+ if (i + 1 < bytes.length) result += ALPHABET[((b1 & 0xf) << 2) | (b2 >> 6)];
33
+ if (i + 2 < bytes.length) result += ALPHABET[b2 & 0x3f];
24
34
  }
25
35
  return result;
26
36
  }
27
37
 
38
+ /**
39
+ * Decodes base64url or standard base64, padded or not.
40
+ * @param {string} str
41
+ * @returns {Uint8Array}
42
+ */
43
+ function base64urlDecode(str) {
44
+ const clean = String(str).replace(/=+$/, '');
45
+ const out = new Uint8Array((clean.length * 3) >> 2);
46
+ let acc = 0;
47
+ let bits = 0;
48
+ let i = 0;
49
+ for (const ch of clean) {
50
+ const value = decodeChar(ch);
51
+ if (value < 0) throw new TypeError(`Invalid base64url character: ${JSON.stringify(ch)}`);
52
+ acc = (acc << 6) | value;
53
+ bits += 6;
54
+ if (bits >= 8) {
55
+ bits -= 8;
56
+ out[i++] = (acc >> bits) & 0xff;
57
+ }
58
+ }
59
+ return out.subarray(0, i);
60
+ }
61
+
62
+ /**
63
+ * @param {Uint8Array} bytes
64
+ * @returns {string}
65
+ */
66
+ function utf8Decode(bytes) {
67
+ let out = '';
68
+ let i = 0;
69
+ while (i < bytes.length) {
70
+ const b0 = bytes[i++];
71
+ let codePoint;
72
+ if (b0 < 0x80) codePoint = b0;
73
+ else if ((b0 & 0xe0) === 0xc0) codePoint = ((b0 & 0x1f) << 6) | (bytes[i++] & 0x3f);
74
+ else if ((b0 & 0xf0) === 0xe0)
75
+ codePoint = ((b0 & 0x0f) << 12) | ((bytes[i++] & 0x3f) << 6) | (bytes[i++] & 0x3f);
76
+ else
77
+ codePoint =
78
+ ((b0 & 0x07) << 18) | ((bytes[i++] & 0x3f) << 12) | ((bytes[i++] & 0x3f) << 6) | (bytes[i++] & 0x3f);
79
+ out += String.fromCodePoint(codePoint);
80
+ }
81
+ return out;
82
+ }
83
+
84
+ // helpers
85
+ function decodeChar(ch) {
86
+ // '+' and '/' map onto the URL-safe alphabet's '-' and '_' slots, so standard
87
+ // base64 decodes through the same table.
88
+ if (ch === '+') return 62;
89
+ if (ch === '/') return 63;
90
+ return ALPHABET.indexOf(ch);
91
+ }
92
+
93
+ base64 = { base64urlEncode, base64urlDecode, utf8Decode };
94
+ return base64;
95
+ }
96
+
97
+ var crypto;
98
+ var hasRequiredCrypto;
99
+
100
+ function requireCrypto () {
101
+ if (hasRequiredCrypto) return crypto;
102
+ hasRequiredCrypto = 1;
103
+
104
+ // Crypto seam for PKCE.
105
+ //
106
+ // Defaults to WebCrypto, which covers browsers and Node >= 18. React Native's
107
+ // Hermes runtime provides neither half of what PKCE needs: there is no
108
+ // SubtleCrypto at all (so no SHA-256), and no crypto.getRandomValues without a
109
+ // polyfill. Hosts on such runtimes call configureCrypto() once at startup with
110
+ // native-backed equivalents (expo-crypto, react-native-quick-crypto).
111
+
112
+ /** @typedef {{getRandomValues: (bytes: Uint8Array) => Uint8Array, sha256: (bytes: Uint8Array) => Promise<Uint8Array>}} CryptoProvider */
113
+
114
+ let _provider = null;
115
+
116
+ /**
117
+ * Installs a crypto provider, replacing the WebCrypto default.
118
+ * @param {CryptoProvider} provider
119
+ */
120
+ function configureCrypto(provider) {
121
+ if (!provider || typeof provider.getRandomValues !== 'function' || typeof provider.sha256 !== 'function') {
122
+ throw new TypeError(
123
+ 'configureCrypto requires { getRandomValues(bytes) => bytes, sha256(bytes) => Promise<Uint8Array> }'
124
+ );
125
+ }
126
+ _provider = provider;
127
+ }
128
+
129
+ /** Restores the WebCrypto default. Primarily for tests. */
130
+ function resetCrypto() {
131
+ _provider = null;
132
+ }
133
+
134
+ /**
135
+ * @returns {CryptoProvider}
136
+ */
137
+ function getCrypto() {
138
+ return _provider ?? webCryptoProvider();
139
+ }
140
+
141
+ // helpers
142
+ function webCryptoProvider() {
143
+ const wc = globalThis.crypto;
144
+ // Named explicitly rather than letting a property access blow up deep inside
145
+ // PKCE: on React Native the failure is a missing polyfill, and the message
146
+ // has to say so.
147
+ if (!wc || typeof wc.getRandomValues !== 'function' || !wc.subtle) {
148
+ throw new Error(
149
+ 'No WebCrypto available in this runtime. On React Native (or any host without ' +
150
+ 'SubtleCrypto), call configureCrypto({ getRandomValues, sha256 }) before using PKCE.'
151
+ );
152
+ }
153
+ return {
154
+ getRandomValues: (bytes) => wc.getRandomValues(bytes),
155
+ sha256: async (bytes) => new Uint8Array(await wc.subtle.digest('SHA-256', bytes)),
156
+ };
157
+ }
158
+
159
+ crypto = { configureCrypto, resetCrypto, getCrypto };
160
+ return crypto;
161
+ }
162
+
163
+ var pkce;
164
+ var hasRequiredPkce;
165
+
166
+ function requirePkce () {
167
+ if (hasRequiredPkce) return pkce;
168
+ hasRequiredPkce = 1;
169
+
170
+ const { base64urlEncode } = requireBase64();
171
+ const { getCrypto } = requireCrypto();
172
+
28
173
  /**
29
174
  * Generates a 64-character PKCE code verifier from [A-Za-z0-9-._~].
30
175
  * @returns {string}
31
176
  */
32
177
  function generateCodeVerifier() {
33
178
  const bytes = new Uint8Array(48);
34
- globalThis.crypto.getRandomValues(bytes);
179
+ getCrypto().getRandomValues(bytes);
35
180
  return base64urlEncode(bytes).slice(0, 64);
36
181
  }
37
182
 
@@ -41,9 +186,8 @@ function requirePkce () {
41
186
  * @returns {Promise<string>}
42
187
  */
43
188
  async function generateCodeChallenge(verifier) {
44
- const encoded = new TextEncoder().encode(verifier);
45
- const hashBuf = await globalThis.crypto.subtle.digest('SHA-256', encoded);
46
- return base64urlEncode(new Uint8Array(hashBuf));
189
+ const hash = await getCrypto().sha256(asciiEncode(verifier));
190
+ return base64urlEncode(hash);
47
191
  }
48
192
 
49
193
  /**
@@ -52,8 +196,24 @@ function requirePkce () {
52
196
  */
53
197
  function generateState() {
54
198
  const bytes = new Uint8Array(16);
55
- globalThis.crypto.getRandomValues(bytes);
56
- return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
199
+ getCrypto().getRandomValues(bytes);
200
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, '0')).join('');
201
+ }
202
+
203
+ // helpers
204
+
205
+ // The RFC 7636 §4.1 verifier alphabet is ASCII-only, so a byte-per-char encode
206
+ // is exact and keeps TextEncoder — absent on some React Native versions — off
207
+ // the PKCE path entirely. A non-ASCII verifier is invalid input, not something
208
+ // to silently re-encode.
209
+ function asciiEncode(str) {
210
+ const out = new Uint8Array(str.length);
211
+ for (let i = 0; i < str.length; i++) {
212
+ const code = str.charCodeAt(i);
213
+ if (code > 0x7f) throw new TypeError('PKCE code_verifier must be ASCII (RFC 7636 §4.1)');
214
+ out[i] = code;
215
+ }
216
+ return out;
57
217
  }
58
218
 
59
219
  pkce = { generateCodeVerifier, generateCodeChallenge, generateState };
@@ -176,6 +336,7 @@ function requireClient () {
176
336
 
177
337
  const { generateCodeVerifier, generateCodeChallenge, generateState } = requirePkce();
178
338
  const { postForm, postJson } = requireHttp();
339
+ const { base64urlDecode, utf8Decode } = requireBase64();
179
340
  const { OAuthError } = requireErrors();
180
341
 
181
342
  // In-flight dedup key for client_credentials re-mints (no refresh_token to key on).
@@ -251,8 +412,7 @@ function requireClient () {
251
412
  code,
252
413
  code_verifier: codeVerifier,
253
414
  redirect_uri: redirectUri ?? this._config.redirectUri,
254
- client_id: this._config.clientId,
255
- client_secret: this._config.clientSecret,
415
+ ...this._clientAuth(),
256
416
  });
257
417
  }
258
418
 
@@ -264,8 +424,7 @@ function requireClient () {
264
424
  async getClientCredentialsToken() {
265
425
  return postForm(`${this._config.baseUrl}/oauth/token`, {
266
426
  grant_type: 'client_credentials',
267
- client_id: this._config.clientId,
268
- client_secret: this._config.clientSecret,
427
+ ...this._clientAuth(),
269
428
  });
270
429
  }
271
430
 
@@ -277,8 +436,7 @@ function requireClient () {
277
436
  return postForm(`${this._config.baseUrl}/oauth/token`, {
278
437
  grant_type: 'refresh_token',
279
438
  refresh_token: refreshToken,
280
- client_id: this._config.clientId,
281
- client_secret: this._config.clientSecret,
439
+ ...this._clientAuth(),
282
440
  });
283
441
  }
284
442
 
@@ -288,7 +446,7 @@ function requireClient () {
288
446
  * @returns {Promise<void>}
289
447
  */
290
448
  async revokeToken(token, tokenTypeHint) {
291
- const params = { token, client_id: this._config.clientId, client_secret: this._config.clientSecret };
449
+ const params = { token, ...this._clientAuth() };
292
450
  if (tokenTypeHint) params.token_type_hint = tokenTypeHint;
293
451
  await postForm(`${this._config.baseUrl}/oauth/revoke`, params);
294
452
  }
@@ -369,10 +527,22 @@ function requireClient () {
369
527
  decodeAccessToken(accessToken) {
370
528
  const segment = accessToken.split('.')[1];
371
529
  if (!segment) throw new OAuthError('invalid_token', 'Malformed JWT', 400);
372
- const b64 = segment.replace(/-/g, '+').replace(/_/g, '/').padEnd(Math.ceil(segment.length / 4) * 4, '=');
373
- const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
374
- const payload = JSON.parse(new TextDecoder().decode(bytes));
375
- return payload;
530
+ return JSON.parse(utf8Decode(base64urlDecode(segment)));
531
+ }
532
+
533
+ /**
534
+ * Client-authentication params for a token-endpoint request.
535
+ *
536
+ * A public client (mobile, SPA) holds no secret, and the authorization server
537
+ * rejects the request outright if one is present, so the key is omitted
538
+ * entirely rather than sent empty. Passing it through unconditionally
539
+ * serializes `undefined` into the form body as that literal string.
540
+ * @returns {Record<string, string>}
541
+ */
542
+ _clientAuth() {
543
+ const params = { client_id: this._config.clientId };
544
+ if (this._config.clientSecret) params.client_secret = this._config.clientSecret;
545
+ return params;
376
546
  }
377
547
  }
378
548
 
@@ -469,8 +639,9 @@ function requireSrc$1 () {
469
639
  const { OAuthClient } = requireClient();
470
640
  const { OAuthError } = requireErrors();
471
641
  const { OAuthErrorCode } = requireTypes();
642
+ const { configureCrypto } = requireCrypto();
472
643
 
473
- src$1 = { OAuthClient, OAuthError, OAuthErrorCode };
644
+ src$1 = { OAuthClient, OAuthError, OAuthErrorCode, configureCrypto };
474
645
  return src$1;
475
646
  }
476
647
 
@@ -478,7 +649,7 @@ var srcExports$1 = requireSrc$1();
478
649
  var _oauth = /*@__PURE__*/getDefaultExportFromCjs(srcExports$1);
479
650
 
480
651
  // Auto-generated — do not edit
481
- const { OAuthClient, OAuthError, OAuthErrorCode } = _oauth;
652
+ const { OAuthClient, OAuthError, OAuthErrorCode, configureCrypto } = _oauth;
482
653
 
483
654
  var signing;
484
655
  var hasRequiredSigning;
@@ -495,12 +666,21 @@ function requireSigning () {
495
666
  // constant time. Web Crypto only, so the same code runs in Node >= 18 and
496
667
  // browsers.
497
668
 
498
- const _encoder = new TextEncoder();
669
+ // Built on first use, not at import. These functions are a server-side concern
670
+ // (only the endpoint receiving a push verifies a signature), but the module is
671
+ // bundled into every SDK including React Native — and constructing this at
672
+ // module scope made merely importing the SDK crash on any runtime without a
673
+ // TextEncoder global.
674
+ let _encoderInstance = null;
675
+ function _encode(text) {
676
+ if (!_encoderInstance) _encoderInstance = new TextEncoder();
677
+ return _encoderInstance.encode(text);
678
+ }
499
679
 
500
680
  async function signWebhookPayload(secret, timestamp, rawBody) {
501
681
  const key = await globalThis.crypto.subtle.importKey(
502
- 'raw', _encoder.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
503
- const payload = _concat(_encoder.encode(`${timestamp}.`), toBytes(rawBody));
682
+ 'raw', _encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
683
+ const payload = _concat(_encode(`${timestamp}.`), toBytes(rawBody));
504
684
  const digest = await globalThis.crypto.subtle.sign('HMAC', key, payload);
505
685
  return 'sha256=' + _hex(new Uint8Array(digest));
506
686
  }
@@ -524,7 +704,7 @@ function requireSigning () {
524
704
 
525
705
  // helpers
526
706
  function toBytes(rawBody) {
527
- if (typeof rawBody === 'string') return _encoder.encode(rawBody);
707
+ if (typeof rawBody === 'string') return _encode(rawBody);
528
708
  if (rawBody instanceof Uint8Array) return rawBody;
529
709
  if (rawBody instanceof ArrayBuffer) return new Uint8Array(rawBody);
530
710
  throw new TypeError('rawBody must be a string, Uint8Array, or ArrayBuffer');
@@ -967,7 +1147,7 @@ class Company {
967
1147
  }
968
1148
  }
969
1149
 
970
- function stripUndef$7(o) { const r = {}; for (const k in o) if (o[k] !== undefined) r[k] = o[k]; return r; }
1150
+ function stripUndef$8(o) { const r = {}; for (const k in o) if (o[k] !== undefined) r[k] = o[k]; return r; }
971
1151
 
972
1152
  class CuratedAlbums {
973
1153
  constructor(ctx) { this._ctx = ctx; }
@@ -975,7 +1155,7 @@ class CuratedAlbums {
975
1155
  async createCuratedAlbum(projectTableName, name, description = undefined, confidenceValue = undefined) {
976
1156
  this._ctx.requireTokens();
977
1157
  const path = `/api/v1/curated_album/project/${encodeURIComponent(projectTableName)}`;
978
- const body = stripUndef$7({
1158
+ const body = stripUndef$8({
979
1159
  name: name,
980
1160
  description: description,
981
1161
  confidence_value: confidenceValue,
@@ -1029,7 +1209,7 @@ class CuratedAlbums {
1029
1209
  async updateCuratedAlbum(albumId, { name, description, confidenceValue } = {}) {
1030
1210
  this._ctx.requireTokens();
1031
1211
  const path = `/api/v1/curated_album/${encodeURIComponent(albumId)}`;
1032
- const body = stripUndef$7({
1212
+ const body = stripUndef$8({
1033
1213
  name: name,
1034
1214
  description: description,
1035
1215
  confidence_value: confidenceValue,
@@ -1053,7 +1233,7 @@ class CuratedAlbums {
1053
1233
  }
1054
1234
  }
1055
1235
 
1056
- function stripUndef$6(o) { const r = {}; for (const k in o) if (o[k] !== undefined) r[k] = o[k]; return r; }
1236
+ function stripUndef$7(o) { const r = {}; for (const k in o) if (o[k] !== undefined) r[k] = o[k]; return r; }
1057
1237
 
1058
1238
  class CustomAlbums {
1059
1239
  constructor(ctx) { this._ctx = ctx; }
@@ -1101,7 +1281,7 @@ class CustomAlbums {
1101
1281
  async createProjectCustomAlbum(projectTableName, { name, description, photoIdInclusionList, photoIdRemovalList } = {}) {
1102
1282
  this._ctx.requireTokens();
1103
1283
  const path = `/api/v1/custom_album/project/${encodeURIComponent(projectTableName)}`;
1104
- const body = stripUndef$6({
1284
+ const body = stripUndef$7({
1105
1285
  name: name,
1106
1286
  description: description,
1107
1287
  photo_id_inclusion_list: photoIdInclusionList,
@@ -1114,7 +1294,7 @@ class CustomAlbums {
1114
1294
  async updateCustomAlbum(albumId, { name, description, photoIdInclusionList, photoIdRemovalList } = {}) {
1115
1295
  this._ctx.requireTokens();
1116
1296
  const path = `/api/v1/custom_album/${encodeURIComponent(albumId)}`;
1117
- const body = stripUndef$6({
1297
+ const body = stripUndef$7({
1118
1298
  name: name,
1119
1299
  description: description,
1120
1300
  photo_id_inclusion_list: photoIdInclusionList,
@@ -1214,7 +1394,7 @@ async function handleResponse(response) {
1214
1394
  }
1215
1395
  }
1216
1396
 
1217
- function stripUndef$5(o) { const r = {}; for (const k in o) if (o[k] !== undefined) r[k] = o[k]; return r; }
1397
+ function stripUndef$6(o) { const r = {}; for (const k in o) if (o[k] !== undefined) r[k] = o[k]; return r; }
1218
1398
 
1219
1399
  class EmailTokens {
1220
1400
  constructor(ctx) { this._ctx = ctx; }
@@ -1245,7 +1425,7 @@ class EmailTokens {
1245
1425
  }
1246
1426
 
1247
1427
  async validateToken(token) {
1248
- const body = stripUndef$5({
1428
+ const body = stripUndef$6({
1249
1429
  token: token,
1250
1430
  });
1251
1431
  const resp = await fetch(this._ctx.baseUrl + `/api/v1/validate-token`, {
@@ -1257,7 +1437,7 @@ class EmailTokens {
1257
1437
  }
1258
1438
 
1259
1439
  async resetPassword(token, newPassword) {
1260
- const body = stripUndef$5({
1440
+ const body = stripUndef$6({
1261
1441
  token: token,
1262
1442
  new_password: newPassword,
1263
1443
  });
@@ -1296,7 +1476,7 @@ class Health {
1296
1476
  }
1297
1477
  }
1298
1478
 
1299
- function stripUndef$4(o) { const r = {}; for (const k in o) if (o[k] !== undefined) r[k] = o[k]; return r; }
1479
+ function stripUndef$5(o) { const r = {}; for (const k in o) if (o[k] !== undefined) r[k] = o[k]; return r; }
1300
1480
 
1301
1481
  class Keywords {
1302
1482
  constructor(ctx) { this._ctx = ctx; }
@@ -1304,7 +1484,7 @@ class Keywords {
1304
1484
  async createKeywordFilteringList(name, projectList = undefined) {
1305
1485
  this._ctx.requireTokens();
1306
1486
  const path = `/api/v1/keyword/`;
1307
- const body = stripUndef$4({
1487
+ const body = stripUndef$5({
1308
1488
  name: name,
1309
1489
  project_list: projectList,
1310
1490
  });
@@ -1357,7 +1537,7 @@ class Keywords {
1357
1537
  async updateKeywordFilteringListLabels(keywordListId, listKeywordsToInclude, listKeywordsToExclude) {
1358
1538
  this._ctx.requireTokens();
1359
1539
  const path = `/api/v1/keyword/${encodeURIComponent(keywordListId)}`;
1360
- const body = stripUndef$4({
1540
+ const body = stripUndef$5({
1361
1541
  list_keywords_to_include: listKeywordsToInclude,
1362
1542
  list_keywords_to_exclude: listKeywordsToExclude,
1363
1543
  });
@@ -1368,7 +1548,7 @@ class Keywords {
1368
1548
  async updateKeywordFilteringListDetails(keywordListId, { name, projectList } = {}) {
1369
1549
  this._ctx.requireTokens();
1370
1550
  const path = `/api/v1/keyword/details/${encodeURIComponent(keywordListId)}`;
1371
- const body = stripUndef$4({
1551
+ const body = stripUndef$5({
1372
1552
  name: name,
1373
1553
  project_list: projectList,
1374
1554
  });
@@ -1633,7 +1813,7 @@ class Person {
1633
1813
  }
1634
1814
  }
1635
1815
 
1636
- function stripUndef$3(o) { const r = {}; for (const k in o) if (o[k] !== undefined) r[k] = o[k]; return r; }
1816
+ function stripUndef$4(o) { const r = {}; for (const k in o) if (o[k] !== undefined) r[k] = o[k]; return r; }
1637
1817
 
1638
1818
  class Projects {
1639
1819
  constructor(ctx) { this._ctx = ctx; }
@@ -1646,7 +1826,7 @@ class Projects {
1646
1826
  if (models !== undefined) (Array.isArray(models) ? models : [models]).forEach(v => query.append('models', v));
1647
1827
  const qs = query.toString();
1648
1828
  if (qs) path += '?' + qs;
1649
- const body = stripUndef$3({
1829
+ const body = stripUndef$4({
1650
1830
  name: name,
1651
1831
  private: private_,
1652
1832
  type: type,
@@ -1716,7 +1896,7 @@ class Projects {
1716
1896
  async updateProject(projectId, { private: private_, type, description, directory, name, thumbnail } = {}) {
1717
1897
  this._ctx.requireTokens();
1718
1898
  const path = `/api/v1/projects/${encodeURIComponent(projectId)}`;
1719
- const body = stripUndef$3({
1899
+ const body = stripUndef$4({
1720
1900
  private: private_,
1721
1901
  type: type,
1722
1902
  description: description,
@@ -1795,7 +1975,7 @@ class Projects {
1795
1975
  async addProjectEvent(projectTableName, event, detail = undefined) {
1796
1976
  this._ctx.requireTokens();
1797
1977
  const path = `/api/v1/projects/${encodeURIComponent(projectTableName)}/event`;
1798
- const body = stripUndef$3({
1978
+ const body = stripUndef$4({
1799
1979
  event: event,
1800
1980
  detail: detail,
1801
1981
  });
@@ -1814,7 +1994,7 @@ class Projects {
1814
1994
  class Photoupload {
1815
1995
  constructor(ctx) { this._ctx = ctx; this._caches = {}; }
1816
1996
 
1817
- async uploadPhotoToMediaviz(fileContent, filePath, mimetype, companyId, userId, projectTableName, blur, colors, faceRecognition, imageClassification, imageComparison, imageDescribe, ocr, { clientSideId, format, size, sourceResolutionX, sourceResolutionY, dateTaken, latitude, longitude } = {}) {
1997
+ async uploadPhotoToMediaviz(fileContent, filePath, mimetype, companyId, userId, projectTableName, blur, colors, faceRecognition, imageClassification, imageComparison, imageDescribe, ocr, judgment, { clientSideId, format, size, sourceResolutionX, sourceResolutionY, dateTaken, latitude, longitude } = {}) {
1818
1998
  this._ctx.requireTokens();
1819
1999
  const baseUrl = this._ctx.requireHost('photoUpload');
1820
2000
  const headers = {
@@ -1824,7 +2004,7 @@ class Photoupload {
1824
2004
  const resp = await fetch(baseUrl + `/photo_upload`, {
1825
2005
  method: 'POST',
1826
2006
  headers,
1827
- body: JSON.stringify({ file_content: fileContent, file_path: filePath, mimetype, company_id: companyId, user_id: userId, project_table_name: projectTableName, blur, colors, face_recognition: faceRecognition, image_classification: imageClassification, image_comparison: imageComparison, image_describe: imageDescribe, ocr, client_side_id: clientSideId, format, size, source_resolution_x: sourceResolutionX, source_resolution_y: sourceResolutionY, date_taken: dateTaken, latitude, longitude }),
2007
+ body: JSON.stringify({ file_content: fileContent, file_path: filePath, mimetype, company_id: companyId, user_id: userId, project_table_name: projectTableName, blur, colors, face_recognition: faceRecognition, image_classification: imageClassification, image_comparison: imageComparison, image_describe: imageDescribe, ocr, judgment, client_side_id: clientSideId, format, size, source_resolution_x: sourceResolutionX, source_resolution_y: sourceResolutionY, date_taken: dateTaken, latitude, longitude }),
1828
2008
  });
1829
2009
  return handleResponse(resp);
1830
2010
  }
@@ -1840,12 +2020,14 @@ class Photoupload {
1840
2020
  this._caches['_get_template'].set(_cacheKey_get_template, template);
1841
2021
  }
1842
2022
 
1843
- const upload_result = await this.uploadPhotoToMediaviz(photo.fileContent, photo.filePath, photo.mimetype, companyId, userId, projectTableName, (((template?.body?.['blur'] ?? template?.headers?.['x-blur']) === true || (template?.body?.['blur'] ?? template?.headers?.['x-blur']) === 'true') ? 'true' : undefined), (((template?.body?.['colors'] ?? template?.headers?.['x-colors']) === true || (template?.body?.['colors'] ?? template?.headers?.['x-colors']) === 'true') ? 'true' : undefined), (((template?.body?.['face_recognition'] ?? template?.headers?.['x-face-recognition']) === true || (template?.body?.['face_recognition'] ?? template?.headers?.['x-face-recognition']) === 'true') ? 'true' : undefined), (((template?.body?.['image_classification'] ?? template?.headers?.['x-image-classification']) === true || (template?.body?.['image_classification'] ?? template?.headers?.['x-image-classification']) === 'true') ? 'true' : undefined), (((template?.body?.['image_comparison'] ?? template?.headers?.['x-image-comparison']) === true || (template?.body?.['image_comparison'] ?? template?.headers?.['x-image-comparison']) === 'true') ? 'true' : undefined), (((template?.body?.['image_describe'] ?? template?.headers?.['x-image-describe']) === true || (template?.body?.['image_describe'] ?? template?.headers?.['x-image-describe']) === 'true') ? 'true' : undefined), (((template?.body?.['ocr'] ?? template?.headers?.['x-ocr']) === true || (template?.body?.['ocr'] ?? template?.headers?.['x-ocr']) === 'true') ? 'true' : undefined), { clientSideId: photo.clientSideId, format: photo.format, size: photo.size, sourceResolutionX: photo.sourceResolutionX, sourceResolutionY: photo.sourceResolutionY, dateTaken: photo.dateTaken, latitude: photo.latitude, longitude: photo.longitude });
2023
+ const upload_result = await this.uploadPhotoToMediaviz(photo.fileContent, photo.filePath, photo.mimetype, companyId, userId, projectTableName, (((template?.body?.['blur'] ?? template?.headers?.['x-blur']) === true || (template?.body?.['blur'] ?? template?.headers?.['x-blur']) === 'true') ? 'true' : undefined), (((template?.body?.['colors'] ?? template?.headers?.['x-colors']) === true || (template?.body?.['colors'] ?? template?.headers?.['x-colors']) === 'true') ? 'true' : undefined), (((template?.body?.['face_recognition'] ?? template?.headers?.['x-face-recognition']) === true || (template?.body?.['face_recognition'] ?? template?.headers?.['x-face-recognition']) === 'true') ? 'true' : undefined), (((template?.body?.['image_classification'] ?? template?.headers?.['x-image-classification']) === true || (template?.body?.['image_classification'] ?? template?.headers?.['x-image-classification']) === 'true') ? 'true' : undefined), (((template?.body?.['image_comparison'] ?? template?.headers?.['x-image-comparison']) === true || (template?.body?.['image_comparison'] ?? template?.headers?.['x-image-comparison']) === 'true') ? 'true' : undefined), (((template?.body?.['image_describe'] ?? template?.headers?.['x-image-describe']) === true || (template?.body?.['image_describe'] ?? template?.headers?.['x-image-describe']) === 'true') ? 'true' : undefined), (((template?.body?.['ocr'] ?? template?.headers?.['x-ocr']) === true || (template?.body?.['ocr'] ?? template?.headers?.['x-ocr']) === 'true') ? 'true' : undefined), (((template?.body?.['judgment'] ?? template?.headers?.['x-judgment']) === true || (template?.body?.['judgment'] ?? template?.headers?.['x-judgment']) === 'true') ? 'true' : undefined), { clientSideId: photo.clientSideId, format: photo.format, size: photo.size, sourceResolutionX: photo.sourceResolutionX, sourceResolutionY: photo.sourceResolutionY, dateTaken: photo.dateTaken, latitude: photo.latitude, longitude: photo.longitude });
1844
2024
 
1845
2025
  return upload_result;
1846
2026
  }
1847
2027
  }
1848
2028
 
2029
+ function stripUndef$3(o) { const r = {}; for (const k in o) if (o[k] !== undefined) r[k] = o[k]; return r; }
2030
+
1849
2031
  class Photos {
1850
2032
  constructor(ctx) { this._ctx = ctx; }
1851
2033
 
@@ -1907,16 +2089,16 @@ class Photos {
1907
2089
  return data;
1908
2090
  }
1909
2091
 
1910
- async updatePhotoInProject({ tableName, photoId, photoData } = {}) {
2092
+ async updatePhotoInProject(tableName, photoId, { filePath, title, description, tags } = {}) {
1911
2093
  this._ctx.requireTokens();
1912
- let path = `/api/v1/photos_update`;
1913
- const query = new URLSearchParams();
1914
- if (tableName !== undefined) (Array.isArray(tableName) ? tableName : [tableName]).forEach(v => query.append('table_name', v));
1915
- if (photoId !== undefined) (Array.isArray(photoId) ? photoId : [photoId]).forEach(v => query.append('photo_id', v));
1916
- if (photoData !== undefined) (Array.isArray(photoData) ? photoData : [photoData]).forEach(v => query.append('photo_data', v));
1917
- const qs = query.toString();
1918
- if (qs) path += '?' + qs;
1919
- const { data } = await this._ctx.client.request(path, 'PUT', this._ctx.accessToken, this._ctx.refreshToken);
2094
+ const path = `/api/v1/photos_update/${encodeURIComponent(tableName)}/id/${encodeURIComponent(photoId)}`;
2095
+ const body = stripUndef$3({
2096
+ file_path: filePath,
2097
+ title: title,
2098
+ description: description,
2099
+ tags: tags,
2100
+ });
2101
+ const { data } = await this._ctx.client.request(path, 'PUT', this._ctx.accessToken, this._ctx.refreshToken, body);
1920
2102
  return data;
1921
2103
  }
1922
2104
 
@@ -2361,4 +2543,4 @@ class MediaViz {
2361
2543
  get refreshToken() { return this._refreshToken; }
2362
2544
  }
2363
2545
 
2364
- export { Admin, AiModelCredits, ApiError, Company, CuratedAlbums, CustomAlbums, EmailTokens, Health, InMemoryWebhookStore, Keywords, MediaViz, NotFoundError, OAuthClient, OAuthError, OAuthErrorCode, OauthAuthorization, OauthLogin, OauthToken, Person, Photos, Photoupload, Projects, RateLimitError, Search, ServerError, Subscription, Users, ValidationError, WEBHOOK_MODEL_COLUMNS, WEBHOOK_OUTCOME_MODELS, WebhookConsumer, handleResponse, selectResultColumns, signWebhookPayload, verifyWebhookSignature };
2546
+ export { Admin, AiModelCredits, ApiError, Company, CuratedAlbums, CustomAlbums, EmailTokens, Health, InMemoryWebhookStore, Keywords, MediaViz, NotFoundError, OAuthClient, OAuthError, OAuthErrorCode, OauthAuthorization, OauthLogin, OauthToken, Person, Photos, Photoupload, Projects, RateLimitError, Search, ServerError, Subscription, Users, ValidationError, WEBHOOK_MODEL_COLUMNS, WEBHOOK_OUTCOME_MODELS, WebhookConsumer, configureCrypto, handleResponse, selectResultColumns, signWebhookPayload, verifyWebhookSignature };