@adventurelabs/scout-core 1.5.1 → 1.5.2
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/helpers/artifactMedia.d.ts +5 -0
- package/dist/helpers/artifactMedia.js +31 -0
- package/dist/helpers/artifacts.js +13 -19
- package/dist/store/api.js +14 -34
- package/dist/types/db.d.ts +3 -0
- package/dist/types/supabase.d.ts +48 -0
- package/package.json +1 -1
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { IArtifact, IArtifactWithMediaUrl } from "../types/db";
|
|
2
|
+
/** Collect unique non-empty storage paths used for artifact media signing. */
|
|
3
|
+
export declare function collectArtifactStoragePaths(artifacts: Iterable<Pick<IArtifact, "file_path" | "thumbnail_file_path" | "proxy_file_path">>): string[];
|
|
4
|
+
/** Attach signed URLs for original, thumbnail, and proxy storage paths. */
|
|
5
|
+
export declare function withArtifactMediaUrls(artifact: IArtifact, urlMap: Map<string, string | null | undefined>): IArtifactWithMediaUrl;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { isNonEmptyStorageFilePath } from "./storagePath";
|
|
2
|
+
/** Collect unique non-empty storage paths used for artifact media signing. */
|
|
3
|
+
export function collectArtifactStoragePaths(artifacts) {
|
|
4
|
+
const seen = new Set();
|
|
5
|
+
const paths = [];
|
|
6
|
+
for (const artifact of artifacts) {
|
|
7
|
+
for (const path of [
|
|
8
|
+
artifact.file_path,
|
|
9
|
+
artifact.thumbnail_file_path,
|
|
10
|
+
artifact.proxy_file_path,
|
|
11
|
+
]) {
|
|
12
|
+
if (isNonEmptyStorageFilePath(path) && !seen.has(path)) {
|
|
13
|
+
seen.add(path);
|
|
14
|
+
paths.push(path);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return paths;
|
|
19
|
+
}
|
|
20
|
+
function signedUrlForPath(path, urlMap) {
|
|
21
|
+
return isNonEmptyStorageFilePath(path) ? urlMap.get(path) ?? null : null;
|
|
22
|
+
}
|
|
23
|
+
/** Attach signed URLs for original, thumbnail, and proxy storage paths. */
|
|
24
|
+
export function withArtifactMediaUrls(artifact, urlMap) {
|
|
25
|
+
return {
|
|
26
|
+
...artifact,
|
|
27
|
+
media_url: signedUrlForPath(artifact.file_path, urlMap),
|
|
28
|
+
thumbnail_url: signedUrlForPath(artifact.thumbnail_file_path, urlMap),
|
|
29
|
+
proxy_url: signedUrlForPath(artifact.proxy_file_path, urlMap),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -1,26 +1,19 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
import { newServerClient } from "../supabase/server";
|
|
3
3
|
import { IWebResponse } from "../types/requests";
|
|
4
|
-
import { generateSignedUrlsBatchWithClient,
|
|
5
|
-
import {
|
|
4
|
+
import { generateSignedUrlsBatchWithClient, } from "./storage_internal";
|
|
5
|
+
import { collectArtifactStoragePaths, withArtifactMediaUrls, } from "./artifactMedia";
|
|
6
6
|
async function addArtifactMediaUrls(data, client) {
|
|
7
|
-
const uniqueFilePaths =
|
|
8
|
-
.map((artifact) => artifact.file_path)
|
|
9
|
-
.filter(isNonEmptyStorageFilePath)));
|
|
7
|
+
const uniqueFilePaths = collectArtifactStoragePaths(data);
|
|
10
8
|
if (uniqueFilePaths.length === 0) {
|
|
11
|
-
return data;
|
|
9
|
+
return data.map((artifact) => withArtifactMediaUrls(artifact, new Map()));
|
|
12
10
|
}
|
|
13
11
|
const signedUrls = await generateSignedUrlsBatchWithClient(client, uniqueFilePaths);
|
|
14
12
|
const urlMap = new Map();
|
|
15
13
|
uniqueFilePaths.forEach((path, index) => {
|
|
16
14
|
urlMap.set(path, signedUrls[index]);
|
|
17
15
|
});
|
|
18
|
-
return data.map((artifact) => (
|
|
19
|
-
...artifact,
|
|
20
|
-
media_url: isNonEmptyStorageFilePath(artifact.file_path)
|
|
21
|
-
? urlMap.get(artifact.file_path) ?? null
|
|
22
|
-
: null,
|
|
23
|
-
}));
|
|
16
|
+
return data.map((artifact) => withArtifactMediaUrls(artifact, urlMap));
|
|
24
17
|
}
|
|
25
18
|
export async function server_get_artifact_by_id(id) {
|
|
26
19
|
const client = await newServerClient();
|
|
@@ -36,14 +29,15 @@ export async function server_get_artifact_by_id(id) {
|
|
|
36
29
|
return IWebResponse.success(null).to_compatible();
|
|
37
30
|
}
|
|
38
31
|
const artifact = data;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
const paths = collectArtifactStoragePaths([artifact]);
|
|
33
|
+
const urlMap = new Map();
|
|
34
|
+
if (paths.length > 0) {
|
|
35
|
+
const signedUrls = await generateSignedUrlsBatchWithClient(client, paths);
|
|
36
|
+
paths.forEach((path, index) => {
|
|
37
|
+
urlMap.set(path, signedUrls[index]);
|
|
38
|
+
});
|
|
42
39
|
}
|
|
43
|
-
return IWebResponse.success(
|
|
44
|
-
...artifact,
|
|
45
|
-
media_url,
|
|
46
|
-
}).to_compatible();
|
|
40
|
+
return IWebResponse.success(withArtifactMediaUrls(artifact, urlMap)).to_compatible();
|
|
47
41
|
}
|
|
48
42
|
export async function server_get_artifacts_by_herd(herd_id, limit = 50, offset = 0, options) {
|
|
49
43
|
const client = await newServerClient();
|
package/dist/store/api.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createApi, fakeBaseQuery } from "@reduxjs/toolkit/query/react";
|
|
2
2
|
import { generateSignedUrlsBatch, } from "../helpers/storage";
|
|
3
|
+
import { collectArtifactStoragePaths, withArtifactMediaUrls, } from "../helpers/artifactMedia";
|
|
3
4
|
import { isNonEmptyStorageFilePath } from "../helpers/storagePath";
|
|
4
5
|
async function signedUrlMapForFeedRows(rows) {
|
|
5
6
|
const seen = new Set();
|
|
@@ -10,10 +11,13 @@ async function signedUrlMapForFeedRows(rows) {
|
|
|
10
11
|
seen.add(ep);
|
|
11
12
|
paths.push(ep);
|
|
12
13
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
if (row.artifact_data) {
|
|
15
|
+
for (const path of collectArtifactStoragePaths([row.artifact_data])) {
|
|
16
|
+
if (!seen.has(path)) {
|
|
17
|
+
seen.add(path);
|
|
18
|
+
paths.push(path);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
17
21
|
}
|
|
18
22
|
}
|
|
19
23
|
const map = new Map();
|
|
@@ -345,9 +349,7 @@ export const scoutApi = createApi({
|
|
|
345
349
|
? artifacts.slice(0, limit)
|
|
346
350
|
: artifacts;
|
|
347
351
|
// Generate signed URLs for artifacts
|
|
348
|
-
const uniqueFilePaths =
|
|
349
|
-
.map((artifact) => artifact.file_path)
|
|
350
|
-
.filter(isNonEmptyStorageFilePath)));
|
|
352
|
+
const uniqueFilePaths = collectArtifactStoragePaths(resultArtifacts);
|
|
351
353
|
let urlMap = new Map();
|
|
352
354
|
if (uniqueFilePaths.length > 0) {
|
|
353
355
|
try {
|
|
@@ -362,12 +364,7 @@ export const scoutApi = createApi({
|
|
|
362
364
|
console.warn("Failed to generate signed URLs for artifacts:", urlError);
|
|
363
365
|
}
|
|
364
366
|
}
|
|
365
|
-
const artifactsWithUrls = resultArtifacts.map((artifact) => (
|
|
366
|
-
...artifact,
|
|
367
|
-
media_url: isNonEmptyStorageFilePath(artifact.file_path)
|
|
368
|
-
? urlMap.get(artifact.file_path) ?? null
|
|
369
|
-
: null,
|
|
370
|
-
}));
|
|
367
|
+
const artifactsWithUrls = resultArtifacts.map((artifact) => withArtifactMediaUrls(artifact, urlMap));
|
|
371
368
|
const nextCursor = hasMore && resultArtifacts.length > 0
|
|
372
369
|
? {
|
|
373
370
|
timestamp: resultArtifacts[resultArtifacts.length - 1].created_at,
|
|
@@ -424,9 +421,7 @@ export const scoutApi = createApi({
|
|
|
424
421
|
? artifacts.slice(0, limit)
|
|
425
422
|
: artifacts;
|
|
426
423
|
// Generate signed URLs for artifacts
|
|
427
|
-
const uniqueFilePaths =
|
|
428
|
-
.map((artifact) => artifact.file_path)
|
|
429
|
-
.filter(isNonEmptyStorageFilePath)));
|
|
424
|
+
const uniqueFilePaths = collectArtifactStoragePaths(resultArtifacts);
|
|
430
425
|
let urlMap = new Map();
|
|
431
426
|
if (uniqueFilePaths.length > 0) {
|
|
432
427
|
try {
|
|
@@ -441,12 +436,7 @@ export const scoutApi = createApi({
|
|
|
441
436
|
console.warn("Failed to generate signed URLs for artifacts:", urlError);
|
|
442
437
|
}
|
|
443
438
|
}
|
|
444
|
-
const artifactsWithUrls = resultArtifacts.map((artifact) => (
|
|
445
|
-
...artifact,
|
|
446
|
-
media_url: isNonEmptyStorageFilePath(artifact.file_path)
|
|
447
|
-
? urlMap.get(artifact.file_path) ?? null
|
|
448
|
-
: null,
|
|
449
|
-
}));
|
|
439
|
+
const artifactsWithUrls = resultArtifacts.map((artifact) => withArtifactMediaUrls(artifact, urlMap));
|
|
450
440
|
const nextCursor = hasMore && resultArtifacts.length > 0
|
|
451
441
|
? {
|
|
452
442
|
timestamp: resultArtifacts[resultArtifacts.length - 1].created_at,
|
|
@@ -523,12 +513,7 @@ export const scoutApi = createApi({
|
|
|
523
513
|
}
|
|
524
514
|
: null,
|
|
525
515
|
artifact_data: row.artifact_data
|
|
526
|
-
?
|
|
527
|
-
...row.artifact_data,
|
|
528
|
-
media_url: isNonEmptyStorageFilePath(row.artifact_data.file_path)
|
|
529
|
-
? urlMap.get(row.artifact_data.file_path) ?? null
|
|
530
|
-
: null,
|
|
531
|
-
}
|
|
516
|
+
? withArtifactMediaUrls(row.artifact_data, urlMap)
|
|
532
517
|
: null,
|
|
533
518
|
}));
|
|
534
519
|
const last = resultRows[resultRows.length - 1];
|
|
@@ -598,12 +583,7 @@ export const scoutApi = createApi({
|
|
|
598
583
|
}
|
|
599
584
|
: null,
|
|
600
585
|
artifact_data: row.artifact_data
|
|
601
|
-
?
|
|
602
|
-
...row.artifact_data,
|
|
603
|
-
media_url: isNonEmptyStorageFilePath(row.artifact_data.file_path)
|
|
604
|
-
? urlMap.get(row.artifact_data.file_path) ?? null
|
|
605
|
-
: null,
|
|
606
|
-
}
|
|
586
|
+
? withArtifactMediaUrls(row.artifact_data, urlMap)
|
|
607
587
|
: null,
|
|
608
588
|
}));
|
|
609
589
|
const last = resultRows[resultRows.length - 1];
|
package/dist/types/db.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export type MediaType = Database["public"]["Enums"]["media_type"];
|
|
|
6
6
|
export type TagObservationType = Database["public"]["Enums"]["tag_observation_type"];
|
|
7
7
|
export type AnalysisWorkStatus = Database["public"]["Enums"]["analysis_work_status"];
|
|
8
8
|
export type EntityLifecycle = Database["public"]["Enums"]["entity_lifecycle"];
|
|
9
|
+
export type DocumentEntity = Database["public"]["Enums"]["document_entity"];
|
|
9
10
|
/** Supabase Auth user (`auth.getUser()`); not `public.users`. */
|
|
10
11
|
export type IUser = User;
|
|
11
12
|
/** Full `public.users` profile row (generated from DB). */
|
|
@@ -148,6 +149,8 @@ export type IAnalysisJob = Database["public"]["Tables"]["analysis_jobs"]["Row"];
|
|
|
148
149
|
export type IAnalysisTask = Database["public"]["Tables"]["analysis_tasks"]["Row"];
|
|
149
150
|
export type IArtifactWithMediaUrl = IArtifact & {
|
|
150
151
|
media_url?: string | null;
|
|
152
|
+
thumbnail_url?: string | null;
|
|
153
|
+
proxy_url?: string | null;
|
|
151
154
|
};
|
|
152
155
|
export type IEventWithMediaUrl = IEvent & {
|
|
153
156
|
media_url?: string | null;
|
package/dist/types/supabase.d.ts
CHANGED
|
@@ -257,9 +257,13 @@ export type Database = {
|
|
|
257
257
|
lifecycle_changed_by: string | null;
|
|
258
258
|
lifecycle_reason: string | null;
|
|
259
259
|
modality: string | null;
|
|
260
|
+
proxy_file_path: string | null;
|
|
261
|
+
proxy_generated_at: string | null;
|
|
260
262
|
segmented_at: string | null;
|
|
261
263
|
session_id: number | null;
|
|
262
264
|
tagged_at: string | null;
|
|
265
|
+
thumbnail_file_path: string | null;
|
|
266
|
+
thumbnail_generated_at: string | null;
|
|
263
267
|
timestamp_observation: string | null;
|
|
264
268
|
timestamp_observation_end: string;
|
|
265
269
|
tracked_at: string | null;
|
|
@@ -277,9 +281,13 @@ export type Database = {
|
|
|
277
281
|
lifecycle_changed_by?: string | null;
|
|
278
282
|
lifecycle_reason?: string | null;
|
|
279
283
|
modality?: string | null;
|
|
284
|
+
proxy_file_path?: string | null;
|
|
285
|
+
proxy_generated_at?: string | null;
|
|
280
286
|
segmented_at?: string | null;
|
|
281
287
|
session_id?: number | null;
|
|
282
288
|
tagged_at?: string | null;
|
|
289
|
+
thumbnail_file_path?: string | null;
|
|
290
|
+
thumbnail_generated_at?: string | null;
|
|
283
291
|
timestamp_observation?: string | null;
|
|
284
292
|
timestamp_observation_end?: string;
|
|
285
293
|
tracked_at?: string | null;
|
|
@@ -297,9 +305,13 @@ export type Database = {
|
|
|
297
305
|
lifecycle_changed_by?: string | null;
|
|
298
306
|
lifecycle_reason?: string | null;
|
|
299
307
|
modality?: string | null;
|
|
308
|
+
proxy_file_path?: string | null;
|
|
309
|
+
proxy_generated_at?: string | null;
|
|
300
310
|
segmented_at?: string | null;
|
|
301
311
|
session_id?: number | null;
|
|
302
312
|
tagged_at?: string | null;
|
|
313
|
+
thumbnail_file_path?: string | null;
|
|
314
|
+
thumbnail_generated_at?: string | null;
|
|
303
315
|
timestamp_observation?: string | null;
|
|
304
316
|
timestamp_observation_end?: string;
|
|
305
317
|
tracked_at?: string | null;
|
|
@@ -4231,9 +4243,13 @@ export type Database = {
|
|
|
4231
4243
|
lifecycle_changed_by: string | null;
|
|
4232
4244
|
lifecycle_reason: string | null;
|
|
4233
4245
|
modality: string | null;
|
|
4246
|
+
proxy_file_path: string | null;
|
|
4247
|
+
proxy_generated_at: string | null;
|
|
4234
4248
|
segmented_at: string | null;
|
|
4235
4249
|
session_id: number | null;
|
|
4236
4250
|
tagged_at: string | null;
|
|
4251
|
+
thumbnail_file_path: string | null;
|
|
4252
|
+
thumbnail_generated_at: string | null;
|
|
4237
4253
|
timestamp_observation: string | null;
|
|
4238
4254
|
timestamp_observation_end: string;
|
|
4239
4255
|
tracked_at: string | null;
|
|
@@ -4263,9 +4279,13 @@ export type Database = {
|
|
|
4263
4279
|
lifecycle_changed_by: string | null;
|
|
4264
4280
|
lifecycle_reason: string | null;
|
|
4265
4281
|
modality: string | null;
|
|
4282
|
+
proxy_file_path: string | null;
|
|
4283
|
+
proxy_generated_at: string | null;
|
|
4266
4284
|
segmented_at: string | null;
|
|
4267
4285
|
session_id: number | null;
|
|
4268
4286
|
tagged_at: string | null;
|
|
4287
|
+
thumbnail_file_path: string | null;
|
|
4288
|
+
thumbnail_generated_at: string | null;
|
|
4269
4289
|
timestamp_observation: string | null;
|
|
4270
4290
|
timestamp_observation_end: string;
|
|
4271
4291
|
tracked_at: string | null;
|
|
@@ -4296,9 +4316,13 @@ export type Database = {
|
|
|
4296
4316
|
lifecycle_changed_by: string | null;
|
|
4297
4317
|
lifecycle_reason: string | null;
|
|
4298
4318
|
modality: string | null;
|
|
4319
|
+
proxy_file_path: string | null;
|
|
4320
|
+
proxy_generated_at: string | null;
|
|
4299
4321
|
segmented_at: string | null;
|
|
4300
4322
|
session_id: number | null;
|
|
4301
4323
|
tagged_at: string | null;
|
|
4324
|
+
thumbnail_file_path: string | null;
|
|
4325
|
+
thumbnail_generated_at: string | null;
|
|
4302
4326
|
timestamp_observation: string | null;
|
|
4303
4327
|
timestamp_observation_end: string;
|
|
4304
4328
|
tracked_at: string | null;
|
|
@@ -4329,9 +4353,13 @@ export type Database = {
|
|
|
4329
4353
|
lifecycle_changed_by: string | null;
|
|
4330
4354
|
lifecycle_reason: string | null;
|
|
4331
4355
|
modality: string | null;
|
|
4356
|
+
proxy_file_path: string | null;
|
|
4357
|
+
proxy_generated_at: string | null;
|
|
4332
4358
|
segmented_at: string | null;
|
|
4333
4359
|
session_id: number | null;
|
|
4334
4360
|
tagged_at: string | null;
|
|
4361
|
+
thumbnail_file_path: string | null;
|
|
4362
|
+
thumbnail_generated_at: string | null;
|
|
4335
4363
|
timestamp_observation: string | null;
|
|
4336
4364
|
timestamp_observation_end: string;
|
|
4337
4365
|
tracked_at: string | null;
|
|
@@ -4363,9 +4391,13 @@ export type Database = {
|
|
|
4363
4391
|
lifecycle_changed_by: string | null;
|
|
4364
4392
|
lifecycle_reason: string | null;
|
|
4365
4393
|
modality: string | null;
|
|
4394
|
+
proxy_file_path: string | null;
|
|
4395
|
+
proxy_generated_at: string | null;
|
|
4366
4396
|
segmented_at: string | null;
|
|
4367
4397
|
session_id: number | null;
|
|
4368
4398
|
tagged_at: string | null;
|
|
4399
|
+
thumbnail_file_path: string | null;
|
|
4400
|
+
thumbnail_generated_at: string | null;
|
|
4369
4401
|
timestamp_observation: string | null;
|
|
4370
4402
|
timestamp_observation_end: string;
|
|
4371
4403
|
tracked_at: string | null;
|
|
@@ -4397,9 +4429,13 @@ export type Database = {
|
|
|
4397
4429
|
lifecycle_changed_by: string | null;
|
|
4398
4430
|
lifecycle_reason: string | null;
|
|
4399
4431
|
modality: string | null;
|
|
4432
|
+
proxy_file_path: string | null;
|
|
4433
|
+
proxy_generated_at: string | null;
|
|
4400
4434
|
segmented_at: string | null;
|
|
4401
4435
|
session_id: number | null;
|
|
4402
4436
|
tagged_at: string | null;
|
|
4437
|
+
thumbnail_file_path: string | null;
|
|
4438
|
+
thumbnail_generated_at: string | null;
|
|
4403
4439
|
timestamp_observation: string | null;
|
|
4404
4440
|
timestamp_observation_end: string;
|
|
4405
4441
|
tracked_at: string | null;
|
|
@@ -4432,9 +4468,13 @@ export type Database = {
|
|
|
4432
4468
|
lifecycle_changed_by: string | null;
|
|
4433
4469
|
lifecycle_reason: string | null;
|
|
4434
4470
|
modality: string | null;
|
|
4471
|
+
proxy_file_path: string | null;
|
|
4472
|
+
proxy_generated_at: string | null;
|
|
4435
4473
|
segmented_at: string | null;
|
|
4436
4474
|
session_id: number | null;
|
|
4437
4475
|
tagged_at: string | null;
|
|
4476
|
+
thumbnail_file_path: string | null;
|
|
4477
|
+
thumbnail_generated_at: string | null;
|
|
4438
4478
|
timestamp_observation: string | null;
|
|
4439
4479
|
timestamp_observation_end: string;
|
|
4440
4480
|
tracked_at: string | null;
|
|
@@ -4466,9 +4506,13 @@ export type Database = {
|
|
|
4466
4506
|
lifecycle_changed_by: string | null;
|
|
4467
4507
|
lifecycle_reason: string | null;
|
|
4468
4508
|
modality: string | null;
|
|
4509
|
+
proxy_file_path: string | null;
|
|
4510
|
+
proxy_generated_at: string | null;
|
|
4469
4511
|
segmented_at: string | null;
|
|
4470
4512
|
session_id: number | null;
|
|
4471
4513
|
tagged_at: string | null;
|
|
4514
|
+
thumbnail_file_path: string | null;
|
|
4515
|
+
thumbnail_generated_at: string | null;
|
|
4472
4516
|
timestamp_observation: string | null;
|
|
4473
4517
|
timestamp_observation_end: string;
|
|
4474
4518
|
tracked_at: string | null;
|
|
@@ -4501,9 +4545,13 @@ export type Database = {
|
|
|
4501
4545
|
lifecycle_changed_by: string | null;
|
|
4502
4546
|
lifecycle_reason: string | null;
|
|
4503
4547
|
modality: string | null;
|
|
4548
|
+
proxy_file_path: string | null;
|
|
4549
|
+
proxy_generated_at: string | null;
|
|
4504
4550
|
segmented_at: string | null;
|
|
4505
4551
|
session_id: number | null;
|
|
4506
4552
|
tagged_at: string | null;
|
|
4553
|
+
thumbnail_file_path: string | null;
|
|
4554
|
+
thumbnail_generated_at: string | null;
|
|
4507
4555
|
timestamp_observation: string | null;
|
|
4508
4556
|
timestamp_observation_end: string;
|
|
4509
4557
|
tracked_at: string | null;
|