@adventurelabs/scout-core 2.0.16 → 2.0.17
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/client/index.d.ts +1 -0
- package/dist/client/index.js +1 -0
- package/dist/helpers/artifactMedia.js +1 -4
- package/dist/helpers/eventMedia.d.ts +12 -0
- package/dist/helpers/eventMedia.js +29 -0
- package/dist/helpers/lifecycle_server.d.ts +4 -0
- package/dist/helpers/media_urls.d.ts +3 -9
- package/dist/helpers/media_urls.js +3 -7
- package/dist/helpers/storagePath.d.ts +2 -0
- package/dist/helpers/storagePath.js +4 -0
- package/dist/helpers/tags.queries.js +4 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/dist/store/api.js +4 -14
- package/dist/types/db.d.ts +4 -7
- package/dist/types/supabase.d.ts +16 -0
- package/package.json +1 -1
package/dist/client/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from "../types";
|
|
|
3
3
|
export * from "../helpers/artifactMedia";
|
|
4
4
|
export * from "../helpers/bounding_boxes";
|
|
5
5
|
export * from "../helpers/email";
|
|
6
|
+
export * from "../helpers/eventMedia";
|
|
6
7
|
export * from "../helpers/eventUtils";
|
|
7
8
|
export { default as get_gps_center } from "../helpers/gps";
|
|
8
9
|
export * from "../helpers/herd_modules_equal";
|
package/dist/client/index.js
CHANGED
|
@@ -6,6 +6,7 @@ export * from "../types";
|
|
|
6
6
|
export * from "../helpers/artifactMedia";
|
|
7
7
|
export * from "../helpers/bounding_boxes";
|
|
8
8
|
export * from "../helpers/email";
|
|
9
|
+
export * from "../helpers/eventMedia";
|
|
9
10
|
export * from "../helpers/eventUtils";
|
|
10
11
|
export { default as get_gps_center } from "../helpers/gps";
|
|
11
12
|
export * from "../helpers/herd_modules_equal";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isNonEmptyStorageFilePath } from "./storagePath";
|
|
1
|
+
import { isNonEmptyStorageFilePath, signedUrlForPath } from "./storagePath";
|
|
2
2
|
/** Collect unique non-empty storage paths used for artifact media signing. */
|
|
3
3
|
export function collectArtifactStoragePaths(artifacts) {
|
|
4
4
|
const seen = new Set();
|
|
@@ -17,9 +17,6 @@ export function collectArtifactStoragePaths(artifacts) {
|
|
|
17
17
|
}
|
|
18
18
|
return paths;
|
|
19
19
|
}
|
|
20
|
-
function signedUrlForPath(path, urlMap) {
|
|
21
|
-
return isNonEmptyStorageFilePath(path) ? urlMap.get(path) ?? null : null;
|
|
22
|
-
}
|
|
23
20
|
/** Attach signed URLs for original, thumbnail, and proxy storage paths. */
|
|
24
21
|
export function withArtifactMediaUrls(artifact, urlMap) {
|
|
25
22
|
return {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ISignedMediaUrls } from "../types/db";
|
|
2
|
+
/** Events arrive as table rows and as the event_and_tags composite, so match on shape. */
|
|
3
|
+
export type IEventMediaPaths = {
|
|
4
|
+
file_path?: string | null;
|
|
5
|
+
thumbnail_file_path?: string | null;
|
|
6
|
+
proxy_file_path?: string | null;
|
|
7
|
+
media_url?: string | null;
|
|
8
|
+
};
|
|
9
|
+
/** Collect unique non-empty storage paths used for event media signing. */
|
|
10
|
+
export declare function collectEventStoragePaths(events: Iterable<IEventMediaPaths | null | undefined>): string[];
|
|
11
|
+
/** Attach signed URLs for original, thumbnail, and proxy storage paths. */
|
|
12
|
+
export declare function withEventMediaUrls<T extends IEventMediaPaths>(event: T, urlMap: Map<string, string | null | undefined>): T & ISignedMediaUrls;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { isNonEmptyStorageFilePath, signedUrlForPath } from "./storagePath";
|
|
2
|
+
/** Collect unique non-empty storage paths used for event media signing. */
|
|
3
|
+
export function collectEventStoragePaths(events) {
|
|
4
|
+
const seen = new Set();
|
|
5
|
+
const paths = [];
|
|
6
|
+
for (const event of events) {
|
|
7
|
+
for (const path of [
|
|
8
|
+
event?.file_path,
|
|
9
|
+
event?.thumbnail_file_path,
|
|
10
|
+
event?.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
|
+
/** Attach signed URLs for original, thumbnail, and proxy storage paths. */
|
|
21
|
+
export function withEventMediaUrls(event, urlMap) {
|
|
22
|
+
return {
|
|
23
|
+
...event,
|
|
24
|
+
// Events predating file_path carry an absolute media_url with nothing to sign.
|
|
25
|
+
media_url: signedUrlForPath(event.file_path, urlMap) ?? event.media_url ?? null,
|
|
26
|
+
thumbnail_url: signedUrlForPath(event.thumbnail_file_path, urlMap),
|
|
27
|
+
proxy_url: signedUrlForPath(event.proxy_file_path, urlMap),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -103,12 +103,16 @@ export declare function server_update_event_lifecycle(event_id: number, lifecycl
|
|
|
103
103
|
origin_roll: number | null;
|
|
104
104
|
processing_blocked_at: string | null;
|
|
105
105
|
processing_blocked_reason: string | null;
|
|
106
|
+
proxy_file_path: string | null;
|
|
107
|
+
proxy_generated_at: string | null;
|
|
106
108
|
segmented_at: string | null;
|
|
107
109
|
sensor_pitch: number | null;
|
|
108
110
|
sensor_roll: number | null;
|
|
109
111
|
sensor_yaw: number | null;
|
|
110
112
|
session_id: number | null;
|
|
111
113
|
tagged_at: string | null;
|
|
114
|
+
thumbnail_file_path: string | null;
|
|
115
|
+
thumbnail_generated_at: string | null;
|
|
112
116
|
timestamp_observation: string;
|
|
113
117
|
tracked_at: string | null;
|
|
114
118
|
} | null>>;
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import type { SupabaseClient } from "@supabase/supabase-js";
|
|
2
|
-
import type { IArtifact, IArtifactWithMediaUrl } from "../types/db";
|
|
2
|
+
import type { IArtifact, IArtifactWithMediaUrl, ISignedMediaUrls } from "../types/db";
|
|
3
3
|
import type { Database } from "../types/supabase";
|
|
4
|
-
type
|
|
5
|
-
file_path?: string | null;
|
|
6
|
-
media_url?: string | null;
|
|
7
|
-
};
|
|
4
|
+
import { type IEventMediaPaths } from "./eventMedia";
|
|
8
5
|
export declare function createSignedUrlMap(client: SupabaseClient<Database>, paths: Iterable<string | null | undefined>): Promise<Map<string, string | null>>;
|
|
9
|
-
export declare function addEventMediaUrls<T extends
|
|
10
|
-
media_url: string | null;
|
|
11
|
-
}>>;
|
|
6
|
+
export declare function addEventMediaUrls<T extends IEventMediaPaths>(client: SupabaseClient<Database>, events: T[]): Promise<Array<T & ISignedMediaUrls>>;
|
|
12
7
|
export declare function addArtifactMediaUrls(client: SupabaseClient<Database>, artifacts: IArtifact[]): Promise<IArtifactWithMediaUrl[]>;
|
|
13
|
-
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { collectArtifactStoragePaths, withArtifactMediaUrls, } from "./artifactMedia";
|
|
2
|
+
import { collectEventStoragePaths, withEventMediaUrls, } from "./eventMedia";
|
|
2
3
|
import { generateSignedUrlsBatchWithClient } from "./storage_internal";
|
|
3
4
|
import { isNonEmptyStorageFilePath } from "./storagePath";
|
|
4
5
|
export async function createSignedUrlMap(client, paths) {
|
|
@@ -7,13 +8,8 @@ export async function createSignedUrlMap(client, paths) {
|
|
|
7
8
|
return new Map(uniquePaths.map((path, index) => [path, urls[index]]));
|
|
8
9
|
}
|
|
9
10
|
export async function addEventMediaUrls(client, events) {
|
|
10
|
-
const urlMap = await createSignedUrlMap(client, events
|
|
11
|
-
return events.map((event) => (
|
|
12
|
-
...event,
|
|
13
|
-
media_url: isNonEmptyStorageFilePath(event.file_path)
|
|
14
|
-
? urlMap.get(event.file_path) ?? event.media_url ?? null
|
|
15
|
-
: event.media_url ?? null,
|
|
16
|
-
}));
|
|
11
|
+
const urlMap = await createSignedUrlMap(client, collectEventStoragePaths(events));
|
|
12
|
+
return events.map((event) => withEventMediaUrls(event, urlMap));
|
|
17
13
|
}
|
|
18
14
|
export async function addArtifactMediaUrls(client, artifacts) {
|
|
19
15
|
const urlMap = await createSignedUrlMap(client, collectArtifactStoragePaths(artifacts));
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/** True when we can sign storage: non-null and not blank after trim. */
|
|
2
2
|
export declare function isNonEmptyStorageFilePath(path: string | null | undefined): path is string;
|
|
3
|
+
/** Signed URL for a storage path, or null when the path is blank or went unsigned. */
|
|
4
|
+
export declare function signedUrlForPath(path: string | null | undefined, urlMap: Map<string, string | null | undefined>): string | null;
|
|
3
5
|
/** Assumes DB `file_path` is always `bucket/object/...` */
|
|
4
6
|
export declare function parseStorageFilePath(filePath: string): {
|
|
5
7
|
bucket: string;
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
export function isNonEmptyStorageFilePath(path) {
|
|
3
3
|
return path != null && path.trim() !== "";
|
|
4
4
|
}
|
|
5
|
+
/** Signed URL for a storage path, or null when the path is blank or went unsigned. */
|
|
6
|
+
export function signedUrlForPath(path, urlMap) {
|
|
7
|
+
return isNonEmptyStorageFilePath(path) ? urlMap.get(path) ?? null : null;
|
|
8
|
+
}
|
|
5
9
|
/** Assumes DB `file_path` is always `bucket/object/...` */
|
|
6
10
|
export function parseStorageFilePath(filePath) {
|
|
7
11
|
const cleaned = filePath.trim().replace(/^\/+|\/+$/g, "");
|
|
@@ -340,6 +340,10 @@ export async function get_event_and_tags_by_event_id_query(client, event_id) {
|
|
|
340
340
|
embedded_at: data[0].embedded_at ?? null,
|
|
341
341
|
segmented_at: data[0].segmented_at ?? null,
|
|
342
342
|
tagged_at: data[0].tagged_at ?? null,
|
|
343
|
+
thumbnail_file_path: data[0].thumbnail_file_path ?? null,
|
|
344
|
+
thumbnail_generated_at: data[0].thumbnail_generated_at ?? null,
|
|
345
|
+
proxy_file_path: data[0].proxy_file_path ?? null,
|
|
346
|
+
proxy_generated_at: data[0].proxy_generated_at ?? null,
|
|
343
347
|
};
|
|
344
348
|
const [eventWithUrl] = await addEventMediaUrls(client, [transformedData]);
|
|
345
349
|
return IWebResponse.success(eventWithUrl).to_compatible();
|
package/dist/server/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from "../types";
|
|
|
4
4
|
export * from "../helpers/artifactMedia";
|
|
5
5
|
export * from "../helpers/bounding_boxes";
|
|
6
6
|
export * from "../helpers/email";
|
|
7
|
+
export * from "../helpers/eventMedia";
|
|
7
8
|
export * from "../helpers/eventUtils";
|
|
8
9
|
export { default as get_gps_center } from "../helpers/gps";
|
|
9
10
|
export * from "../helpers/herd_modules_equal";
|
package/dist/server/index.js
CHANGED
|
@@ -6,6 +6,7 @@ export * from "../types";
|
|
|
6
6
|
export * from "../helpers/artifactMedia";
|
|
7
7
|
export * from "../helpers/bounding_boxes";
|
|
8
8
|
export * from "../helpers/email";
|
|
9
|
+
export * from "../helpers/eventMedia";
|
|
9
10
|
export * from "../helpers/eventUtils";
|
|
10
11
|
export { default as get_gps_center } from "../helpers/gps";
|
|
11
12
|
export * from "../helpers/herd_modules_equal";
|
package/dist/store/api.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import { createApi, fakeBaseQuery } from "@reduxjs/toolkit/query/react";
|
|
3
3
|
import { addArtifactMediaUrls, addEventMediaUrls, createSignedUrlMap, } from "../helpers/media_urls";
|
|
4
4
|
import { collectArtifactStoragePaths, withArtifactMediaUrls, } from "../helpers/artifactMedia";
|
|
5
|
-
import {
|
|
5
|
+
import { collectEventStoragePaths, withEventMediaUrls, } from "../helpers/eventMedia";
|
|
6
6
|
async function signedUrlMapForFeedRows(supabase, rows) {
|
|
7
7
|
return createSignedUrlMap(supabase, rows.flatMap((row) => [
|
|
8
|
-
row.event_data
|
|
8
|
+
...collectEventStoragePaths([row.event_data]),
|
|
9
9
|
...(row.artifact_data
|
|
10
10
|
? collectArtifactStoragePaths([row.artifact_data])
|
|
11
11
|
: []),
|
|
@@ -434,12 +434,7 @@ export const scoutApi = createApi({
|
|
|
434
434
|
const items = resultRows.map((row) => ({
|
|
435
435
|
...row,
|
|
436
436
|
event_data: row.event_data
|
|
437
|
-
?
|
|
438
|
-
...row.event_data,
|
|
439
|
-
media_url: isNonEmptyStorageFilePath(row.event_data.file_path)
|
|
440
|
-
? urlMap.get(row.event_data.file_path) ?? null
|
|
441
|
-
: null,
|
|
442
|
-
}
|
|
437
|
+
? withEventMediaUrls(row.event_data, urlMap)
|
|
443
438
|
: null,
|
|
444
439
|
artifact_data: row.artifact_data
|
|
445
440
|
? withArtifactMediaUrls(row.artifact_data, urlMap)
|
|
@@ -504,12 +499,7 @@ export const scoutApi = createApi({
|
|
|
504
499
|
const items = resultRows.map((row) => ({
|
|
505
500
|
...row,
|
|
506
501
|
event_data: row.event_data
|
|
507
|
-
?
|
|
508
|
-
...row.event_data,
|
|
509
|
-
media_url: isNonEmptyStorageFilePath(row.event_data.file_path)
|
|
510
|
-
? urlMap.get(row.event_data.file_path) ?? null
|
|
511
|
-
: null,
|
|
512
|
-
}
|
|
502
|
+
? withEventMediaUrls(row.event_data, urlMap)
|
|
513
503
|
: null,
|
|
514
504
|
artifact_data: row.artifact_data
|
|
515
505
|
? withArtifactMediaUrls(row.artifact_data, urlMap)
|
package/dist/types/db.d.ts
CHANGED
|
@@ -217,14 +217,13 @@ export type BatteryCycleCountUpdate = Database["public"]["Tables"]["battery_cycl
|
|
|
217
217
|
export type IMinimalSubjectForArtifact = Database["public"]["Functions"]["get_minimal_subjects_for_artifact"]["Returns"][number];
|
|
218
218
|
export type IAnalysisJob = Database["public"]["Tables"]["analysis_jobs"]["Row"];
|
|
219
219
|
export type IAnalysisTask = Database["public"]["Tables"]["analysis_tasks"]["Row"];
|
|
220
|
-
export type
|
|
220
|
+
export type ISignedMediaUrls = {
|
|
221
221
|
media_url?: string | null;
|
|
222
222
|
thumbnail_url?: string | null;
|
|
223
223
|
proxy_url?: string | null;
|
|
224
224
|
};
|
|
225
|
-
export type
|
|
226
|
-
|
|
227
|
-
};
|
|
225
|
+
export type IArtifactWithMediaUrl = IArtifact & ISignedMediaUrls;
|
|
226
|
+
export type IEventWithMediaUrl = IEvent & ISignedMediaUrls;
|
|
228
227
|
export type IVersionsSoftwareWithBuildUrl = IVersionsSoftware & {
|
|
229
228
|
build_artifact_url?: string | null;
|
|
230
229
|
};
|
|
@@ -368,9 +367,7 @@ export type IFeedItem = {
|
|
|
368
367
|
feed_type: string | null;
|
|
369
368
|
sort_ts: string | null;
|
|
370
369
|
sort_id: number | null;
|
|
371
|
-
event_data: (IEventAndTagsPrettyLocation &
|
|
372
|
-
media_url?: string | null;
|
|
373
|
-
}) | null;
|
|
370
|
+
event_data: (IEventAndTagsPrettyLocation & ISignedMediaUrls) | null;
|
|
374
371
|
artifact_data: IArtifactWithMediaUrl | null;
|
|
375
372
|
};
|
|
376
373
|
export type ISessionWithCoordinates = Database["public"]["CompositeTypes"]["session_with_coordinates"];
|
package/dist/types/supabase.d.ts
CHANGED
|
@@ -1504,12 +1504,16 @@ export type Database = {
|
|
|
1504
1504
|
origin_roll: number | null;
|
|
1505
1505
|
processing_blocked_at: string | null;
|
|
1506
1506
|
processing_blocked_reason: string | null;
|
|
1507
|
+
proxy_file_path: string | null;
|
|
1508
|
+
proxy_generated_at: string | null;
|
|
1507
1509
|
segmented_at: string | null;
|
|
1508
1510
|
sensor_pitch: number | null;
|
|
1509
1511
|
sensor_roll: number | null;
|
|
1510
1512
|
sensor_yaw: number | null;
|
|
1511
1513
|
session_id: number | null;
|
|
1512
1514
|
tagged_at: string | null;
|
|
1515
|
+
thumbnail_file_path: string | null;
|
|
1516
|
+
thumbnail_generated_at: string | null;
|
|
1513
1517
|
timestamp_observation: string;
|
|
1514
1518
|
tracked_at: string | null;
|
|
1515
1519
|
};
|
|
@@ -1538,12 +1542,16 @@ export type Database = {
|
|
|
1538
1542
|
origin_roll?: number | null;
|
|
1539
1543
|
processing_blocked_at?: string | null;
|
|
1540
1544
|
processing_blocked_reason?: string | null;
|
|
1545
|
+
proxy_file_path?: string | null;
|
|
1546
|
+
proxy_generated_at?: string | null;
|
|
1541
1547
|
segmented_at?: string | null;
|
|
1542
1548
|
sensor_pitch?: number | null;
|
|
1543
1549
|
sensor_roll?: number | null;
|
|
1544
1550
|
sensor_yaw?: number | null;
|
|
1545
1551
|
session_id?: number | null;
|
|
1546
1552
|
tagged_at?: string | null;
|
|
1553
|
+
thumbnail_file_path?: string | null;
|
|
1554
|
+
thumbnail_generated_at?: string | null;
|
|
1547
1555
|
timestamp_observation?: string;
|
|
1548
1556
|
tracked_at?: string | null;
|
|
1549
1557
|
};
|
|
@@ -1572,12 +1580,16 @@ export type Database = {
|
|
|
1572
1580
|
origin_roll?: number | null;
|
|
1573
1581
|
processing_blocked_at?: string | null;
|
|
1574
1582
|
processing_blocked_reason?: string | null;
|
|
1583
|
+
proxy_file_path?: string | null;
|
|
1584
|
+
proxy_generated_at?: string | null;
|
|
1575
1585
|
segmented_at?: string | null;
|
|
1576
1586
|
sensor_pitch?: number | null;
|
|
1577
1587
|
sensor_roll?: number | null;
|
|
1578
1588
|
sensor_yaw?: number | null;
|
|
1579
1589
|
session_id?: number | null;
|
|
1580
1590
|
tagged_at?: string | null;
|
|
1591
|
+
thumbnail_file_path?: string | null;
|
|
1592
|
+
thumbnail_generated_at?: string | null;
|
|
1581
1593
|
timestamp_observation?: string;
|
|
1582
1594
|
tracked_at?: string | null;
|
|
1583
1595
|
};
|
|
@@ -7015,6 +7027,10 @@ export type Database = {
|
|
|
7015
7027
|
embedded_at: string | null;
|
|
7016
7028
|
segmented_at: string | null;
|
|
7017
7029
|
tagged_at: string | null;
|
|
7030
|
+
thumbnail_file_path: string | null;
|
|
7031
|
+
thumbnail_generated_at: string | null;
|
|
7032
|
+
proxy_file_path: string | null;
|
|
7033
|
+
proxy_generated_at: string | null;
|
|
7018
7034
|
};
|
|
7019
7035
|
event_plus_tags: {
|
|
7020
7036
|
id: number | null;
|