@adventurelabs/scout-core 1.4.60 → 1.4.61
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/artifacts.js +11 -11
- package/dist/helpers/events.js +2 -2
- package/dist/helpers/sessions.js +5 -3
- package/dist/helpers/storage.d.ts +1 -1
- package/dist/helpers/storage.js +1 -1
- package/dist/helpers/storagePath.d.ts +2 -0
- package/dist/helpers/storagePath.js +4 -0
- package/dist/helpers/tags.js +15 -8
- package/dist/store/api.js +19 -19
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
import { newServerClient } from "../supabase/server";
|
|
3
3
|
import { IWebResponse } from "../types/requests";
|
|
4
|
-
import { generateSignedUrlsBatch, generateSignedUrl } from "./storage";
|
|
4
|
+
import { generateSignedUrlsBatch, generateSignedUrl, isNonEmptyStorageFilePath, } from "./storage";
|
|
5
5
|
export async function server_get_artifact_by_id(id, client) {
|
|
6
6
|
const supabase = client || (await newServerClient());
|
|
7
7
|
const { data, error } = await supabase
|
|
@@ -17,7 +17,7 @@ export async function server_get_artifact_by_id(id, client) {
|
|
|
17
17
|
}
|
|
18
18
|
const artifact = data;
|
|
19
19
|
let media_url = null;
|
|
20
|
-
if (artifact.file_path) {
|
|
20
|
+
if (isNonEmptyStorageFilePath(artifact.file_path)) {
|
|
21
21
|
media_url = await generateSignedUrl(artifact.file_path, undefined, client);
|
|
22
22
|
}
|
|
23
23
|
return IWebResponse.success({
|
|
@@ -43,7 +43,7 @@ export async function server_get_artifacts_by_herd(herd_id, limit = 50, offset =
|
|
|
43
43
|
// Generate signed URLs for artifacts
|
|
44
44
|
const uniqueFilePaths = Array.from(new Set(data
|
|
45
45
|
.map((artifact) => artifact.file_path)
|
|
46
|
-
.filter(
|
|
46
|
+
.filter(isNonEmptyStorageFilePath)));
|
|
47
47
|
if (uniqueFilePaths.length === 0) {
|
|
48
48
|
return IWebResponse.success(data).to_compatible();
|
|
49
49
|
}
|
|
@@ -54,8 +54,8 @@ export async function server_get_artifacts_by_herd(herd_id, limit = 50, offset =
|
|
|
54
54
|
});
|
|
55
55
|
const artifactsWithUrls = data.map((artifact) => ({
|
|
56
56
|
...artifact,
|
|
57
|
-
media_url: artifact.file_path
|
|
58
|
-
? urlMap.get(artifact.file_path)
|
|
57
|
+
media_url: isNonEmptyStorageFilePath(artifact.file_path)
|
|
58
|
+
? urlMap.get(artifact.file_path) ?? null
|
|
59
59
|
: null,
|
|
60
60
|
}));
|
|
61
61
|
return IWebResponse.success(artifactsWithUrls).to_compatible();
|
|
@@ -76,7 +76,7 @@ export async function server_get_artifacts_by_device_id(device_id, limit = 50, o
|
|
|
76
76
|
// Generate signed URLs for artifacts
|
|
77
77
|
const uniqueFilePaths = Array.from(new Set(data
|
|
78
78
|
.map((artifact) => artifact.file_path)
|
|
79
|
-
.filter(
|
|
79
|
+
.filter(isNonEmptyStorageFilePath)));
|
|
80
80
|
if (uniqueFilePaths.length === 0) {
|
|
81
81
|
return IWebResponse.success(data).to_compatible();
|
|
82
82
|
}
|
|
@@ -87,8 +87,8 @@ export async function server_get_artifacts_by_device_id(device_id, limit = 50, o
|
|
|
87
87
|
});
|
|
88
88
|
const artifactsWithUrls = data.map((artifact) => ({
|
|
89
89
|
...artifact,
|
|
90
|
-
media_url: artifact.file_path
|
|
91
|
-
? urlMap.get(artifact.file_path)
|
|
90
|
+
media_url: isNonEmptyStorageFilePath(artifact.file_path)
|
|
91
|
+
? urlMap.get(artifact.file_path) ?? null
|
|
92
92
|
: null,
|
|
93
93
|
}));
|
|
94
94
|
return IWebResponse.success(artifactsWithUrls).to_compatible();
|
|
@@ -121,7 +121,7 @@ export async function server_get_artifacts_by_device_ids_batch(device_ids, limit
|
|
|
121
121
|
// Generate signed URLs for artifacts
|
|
122
122
|
const uniqueFilePaths = Array.from(new Set(data
|
|
123
123
|
.map((artifact) => artifact.file_path)
|
|
124
|
-
.filter(
|
|
124
|
+
.filter(isNonEmptyStorageFilePath)));
|
|
125
125
|
let artifactsWithUrls = data;
|
|
126
126
|
if (uniqueFilePaths.length > 0) {
|
|
127
127
|
const signedUrls = await generateSignedUrlsBatch(uniqueFilePaths, undefined, options?.client);
|
|
@@ -131,8 +131,8 @@ export async function server_get_artifacts_by_device_ids_batch(device_ids, limit
|
|
|
131
131
|
});
|
|
132
132
|
artifactsWithUrls = data.map((artifact) => ({
|
|
133
133
|
...artifact,
|
|
134
|
-
media_url: artifact.file_path
|
|
135
|
-
? urlMap.get(artifact.file_path)
|
|
134
|
+
media_url: isNonEmptyStorageFilePath(artifact.file_path)
|
|
135
|
+
? urlMap.get(artifact.file_path) ?? null
|
|
136
136
|
: null,
|
|
137
137
|
}));
|
|
138
138
|
}
|
package/dist/helpers/events.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { newServerClient } from "../supabase/server";
|
|
3
3
|
import { EnumWebResponse, IWebResponse, } from "../types/requests";
|
|
4
4
|
import { EnumSessionsVisibility } from "../types/events";
|
|
5
|
-
import { generateSignedUrl } from "./storage";
|
|
5
|
+
import { generateSignedUrl, isNonEmptyStorageFilePath } from "./storage";
|
|
6
6
|
export async function server_get_event_by_id(id, client) {
|
|
7
7
|
const supabase = client || (await newServerClient());
|
|
8
8
|
const { data, error } = await supabase
|
|
@@ -18,7 +18,7 @@ export async function server_get_event_by_id(id, client) {
|
|
|
18
18
|
}
|
|
19
19
|
const event = data;
|
|
20
20
|
let media_url = null;
|
|
21
|
-
if (event.file_path) {
|
|
21
|
+
if (isNonEmptyStorageFilePath(event.file_path)) {
|
|
22
22
|
media_url = await generateSignedUrl(event.file_path, undefined, client);
|
|
23
23
|
}
|
|
24
24
|
return IWebResponse.success({
|
package/dist/helpers/sessions.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
import { newServerClient } from "../supabase/server";
|
|
3
3
|
import { EnumWebResponse, IWebResponse, } from "../types/requests";
|
|
4
|
-
import { generateSignedUrlsBatch } from "./storage";
|
|
4
|
+
import { generateSignedUrlsBatch, isNonEmptyStorageFilePath, } from "./storage";
|
|
5
5
|
// Get session by ID with coordinates
|
|
6
6
|
export async function server_get_session_by_id(sessionId, client) {
|
|
7
7
|
const supabase = client || (await newServerClient());
|
|
@@ -79,7 +79,7 @@ export async function server_get_events_and_tags_by_session_id(sessionId, limit
|
|
|
79
79
|
const eventData = (data || []);
|
|
80
80
|
const filePaths = eventData
|
|
81
81
|
.map((event) => event.file_path)
|
|
82
|
-
.filter(
|
|
82
|
+
.filter(isNonEmptyStorageFilePath);
|
|
83
83
|
let eventsWithSignedUrls = eventData;
|
|
84
84
|
if (filePaths.length > 0) {
|
|
85
85
|
const signedUrls = await generateSignedUrlsBatch(filePaths, undefined, supabase);
|
|
@@ -89,7 +89,9 @@ export async function server_get_events_and_tags_by_session_id(sessionId, limit
|
|
|
89
89
|
});
|
|
90
90
|
eventsWithSignedUrls = eventData.map((event) => ({
|
|
91
91
|
...event,
|
|
92
|
-
media_url:
|
|
92
|
+
media_url: isNonEmptyStorageFilePath(event.file_path)
|
|
93
|
+
? urlMap.get(event.file_path) ?? null
|
|
94
|
+
: null,
|
|
93
95
|
}));
|
|
94
96
|
}
|
|
95
97
|
return IWebResponse.success(eventsWithSignedUrls).to_compatible();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SupabaseClient } from "@supabase/supabase-js";
|
|
2
2
|
import { Database } from "../types/supabase";
|
|
3
|
-
export { parseStorageFilePath } from "./storagePath";
|
|
3
|
+
export { parseStorageFilePath, isNonEmptyStorageFilePath } from "./storagePath";
|
|
4
4
|
export declare function generateSignedUrl(filePath: string, expiresIn?: number, supabaseClient?: SupabaseClient<Database>): Promise<string | null>;
|
|
5
5
|
export declare function generateSignedUrlsBatch(filePaths: string[], expiresIn?: number, supabaseClient?: SupabaseClient<Database>): Promise<(string | null)[]>;
|
package/dist/helpers/storage.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { newServerClient } from "../supabase/server";
|
|
2
2
|
import { SIGNED_URL_EXPIRATION_SECONDS } from "../constants/db";
|
|
3
3
|
import { parseStorageFilePath } from "./storagePath";
|
|
4
|
-
export { parseStorageFilePath } from "./storagePath";
|
|
4
|
+
export { parseStorageFilePath, isNonEmptyStorageFilePath } from "./storagePath";
|
|
5
5
|
export async function generateSignedUrl(filePath, expiresIn = SIGNED_URL_EXPIRATION_SECONDS, supabaseClient) {
|
|
6
6
|
try {
|
|
7
7
|
const supabase = supabaseClient || (await newServerClient());
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** True when we can sign storage: non-null and not blank after trim. */
|
|
2
|
+
export declare function isNonEmptyStorageFilePath(path: string | null | undefined): path is string;
|
|
1
3
|
/** Assumes DB `file_path` is always `bucket/object/...` */
|
|
2
4
|
export declare function parseStorageFilePath(filePath: string): {
|
|
3
5
|
bucket: string;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/** True when we can sign storage: non-null and not blank after trim. */
|
|
2
|
+
export function isNonEmptyStorageFilePath(path) {
|
|
3
|
+
return path != null && path.trim() !== "";
|
|
4
|
+
}
|
|
1
5
|
/** Assumes DB `file_path` is always `bucket/object/...` */
|
|
2
6
|
export function parseStorageFilePath(filePath) {
|
|
3
7
|
const cleaned = filePath.trim().replace(/^\/+|\/+$/g, "");
|
package/dist/helpers/tags.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// add tag to db
|
|
3
3
|
import { newServerClient } from "../supabase/server";
|
|
4
4
|
import { EnumWebResponse, IWebResponse, } from "../types/requests";
|
|
5
|
-
import { generateSignedUrlsBatch, generateSignedUrl } from "./storage";
|
|
5
|
+
import { generateSignedUrlsBatch, generateSignedUrl, isNonEmptyStorageFilePath, } from "./storage";
|
|
6
6
|
// Helper functions to extract coordinates from location field
|
|
7
7
|
function extractLatitude(location) {
|
|
8
8
|
try {
|
|
@@ -178,7 +178,7 @@ export async function server_get_more_events_with_tags_by_herd(herd_id, offset,
|
|
|
178
178
|
// Generate signed URLs for events
|
|
179
179
|
const filePaths = filtered_data
|
|
180
180
|
.map((event) => event.file_path)
|
|
181
|
-
.filter(
|
|
181
|
+
.filter(isNonEmptyStorageFilePath);
|
|
182
182
|
let eventsWithSignedUrls = filtered_data;
|
|
183
183
|
if (filePaths.length > 0) {
|
|
184
184
|
const signedUrls = await generateSignedUrlsBatch(filePaths, undefined, supabase);
|
|
@@ -188,7 +188,9 @@ export async function server_get_more_events_with_tags_by_herd(herd_id, offset,
|
|
|
188
188
|
});
|
|
189
189
|
eventsWithSignedUrls = filtered_data.map((event) => ({
|
|
190
190
|
...event,
|
|
191
|
-
media_url:
|
|
191
|
+
media_url: isNonEmptyStorageFilePath(event.file_path)
|
|
192
|
+
? urlMap.get(event.file_path) ?? null
|
|
193
|
+
: null,
|
|
192
194
|
}));
|
|
193
195
|
}
|
|
194
196
|
return IWebResponse.success(eventsWithSignedUrls).to_compatible();
|
|
@@ -212,7 +214,7 @@ export async function server_get_events_and_tags_for_device(device_id, limit = 3
|
|
|
212
214
|
const eventData = data || [];
|
|
213
215
|
const filePaths = eventData
|
|
214
216
|
.map((event) => event.file_path)
|
|
215
|
-
.filter(
|
|
217
|
+
.filter(isNonEmptyStorageFilePath);
|
|
216
218
|
let eventsWithSignedUrls = eventData;
|
|
217
219
|
if (filePaths.length > 0) {
|
|
218
220
|
const signedUrls = await generateSignedUrlsBatch(filePaths, undefined, supabase);
|
|
@@ -222,7 +224,9 @@ export async function server_get_events_and_tags_for_device(device_id, limit = 3
|
|
|
222
224
|
});
|
|
223
225
|
eventsWithSignedUrls = eventData.map((event) => ({
|
|
224
226
|
...event,
|
|
225
|
-
media_url:
|
|
227
|
+
media_url: isNonEmptyStorageFilePath(event.file_path)
|
|
228
|
+
? urlMap.get(event.file_path) ?? null
|
|
229
|
+
: null,
|
|
226
230
|
}));
|
|
227
231
|
}
|
|
228
232
|
return IWebResponse.success(eventsWithSignedUrls).to_compatible();
|
|
@@ -296,7 +300,8 @@ export async function server_get_events_and_tags_for_devices_batch(device_ids, l
|
|
|
296
300
|
for (const device_id in eventsByDevice) {
|
|
297
301
|
const events = eventsByDevice[device_id];
|
|
298
302
|
events.forEach((event) => {
|
|
299
|
-
if (
|
|
303
|
+
if (isNonEmptyStorageFilePath(event.file_path) &&
|
|
304
|
+
!allFilePaths.includes(event.file_path)) {
|
|
300
305
|
allFilePaths.push(event.file_path);
|
|
301
306
|
}
|
|
302
307
|
});
|
|
@@ -314,7 +319,9 @@ export async function server_get_events_and_tags_for_devices_batch(device_ids, l
|
|
|
314
319
|
const events = eventsByDevice[device_id];
|
|
315
320
|
const eventsWithSignedUrls = events.map((event) => ({
|
|
316
321
|
...event,
|
|
317
|
-
media_url:
|
|
322
|
+
media_url: isNonEmptyStorageFilePath(event.file_path)
|
|
323
|
+
? urlMap.get(event.file_path) ?? null
|
|
324
|
+
: null,
|
|
318
325
|
}));
|
|
319
326
|
result[parseInt(device_id)] = eventsWithSignedUrls;
|
|
320
327
|
}
|
|
@@ -454,7 +461,7 @@ export async function get_event_and_tags_by_event_id(event_id) {
|
|
|
454
461
|
};
|
|
455
462
|
// Generate signed URL for event
|
|
456
463
|
let eventWithSignedUrl = transformedData;
|
|
457
|
-
if (transformedData.file_path) {
|
|
464
|
+
if (isNonEmptyStorageFilePath(transformedData.file_path)) {
|
|
458
465
|
const signedUrl = await generateSignedUrl(transformedData.file_path, undefined, supabase);
|
|
459
466
|
eventWithSignedUrl = {
|
|
460
467
|
...transformedData,
|
package/dist/store/api.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { createApi, fakeBaseQuery } from "@reduxjs/toolkit/query/react";
|
|
2
|
-
import { generateSignedUrlsBatch } from "../helpers/storage";
|
|
2
|
+
import { generateSignedUrlsBatch, isNonEmptyStorageFilePath, } from "../helpers/storage";
|
|
3
3
|
async function signedUrlMapForFeedRows(rows) {
|
|
4
4
|
const seen = new Set();
|
|
5
5
|
const paths = [];
|
|
6
6
|
for (const row of rows) {
|
|
7
7
|
const ep = row.event_data?.file_path;
|
|
8
|
-
if (ep && !seen.has(ep)) {
|
|
8
|
+
if (isNonEmptyStorageFilePath(ep) && !seen.has(ep)) {
|
|
9
9
|
seen.add(ep);
|
|
10
10
|
paths.push(ep);
|
|
11
11
|
}
|
|
12
12
|
const ap = row.artifact_data?.file_path;
|
|
13
|
-
if (ap && !seen.has(ap)) {
|
|
13
|
+
if (isNonEmptyStorageFilePath(ap) && !seen.has(ap)) {
|
|
14
14
|
seen.add(ap);
|
|
15
15
|
paths.push(ap);
|
|
16
16
|
}
|
|
@@ -185,7 +185,7 @@ export const scoutApi = createApi({
|
|
|
185
185
|
// Generate signed URLs for events
|
|
186
186
|
const uniqueFilePaths = Array.from(new Set(resultEvents
|
|
187
187
|
.map((event) => event.file_path)
|
|
188
|
-
.filter(
|
|
188
|
+
.filter(isNonEmptyStorageFilePath)));
|
|
189
189
|
let urlMap = new Map();
|
|
190
190
|
if (uniqueFilePaths.length > 0) {
|
|
191
191
|
try {
|
|
@@ -202,8 +202,8 @@ export const scoutApi = createApi({
|
|
|
202
202
|
}
|
|
203
203
|
const eventsWithUrls = resultEvents.map((event) => ({
|
|
204
204
|
...event,
|
|
205
|
-
media_url: event.file_path
|
|
206
|
-
? urlMap.get(event.file_path)
|
|
205
|
+
media_url: isNonEmptyStorageFilePath(event.file_path)
|
|
206
|
+
? urlMap.get(event.file_path) ?? null
|
|
207
207
|
: null,
|
|
208
208
|
}));
|
|
209
209
|
const nextCursor = hasMore && resultEvents.length > 0
|
|
@@ -263,7 +263,7 @@ export const scoutApi = createApi({
|
|
|
263
263
|
// Generate signed URLs for events
|
|
264
264
|
const uniqueFilePaths = Array.from(new Set(resultEvents
|
|
265
265
|
.map((event) => event.file_path)
|
|
266
|
-
.filter(
|
|
266
|
+
.filter(isNonEmptyStorageFilePath)));
|
|
267
267
|
let urlMap = new Map();
|
|
268
268
|
if (uniqueFilePaths.length > 0) {
|
|
269
269
|
try {
|
|
@@ -280,8 +280,8 @@ export const scoutApi = createApi({
|
|
|
280
280
|
}
|
|
281
281
|
const eventsWithUrls = resultEvents.map((event) => ({
|
|
282
282
|
...event,
|
|
283
|
-
media_url: event.file_path
|
|
284
|
-
? urlMap.get(event.file_path)
|
|
283
|
+
media_url: isNonEmptyStorageFilePath(event.file_path)
|
|
284
|
+
? urlMap.get(event.file_path) ?? null
|
|
285
285
|
: null,
|
|
286
286
|
}));
|
|
287
287
|
const nextCursor = hasMore && resultEvents.length > 0
|
|
@@ -346,7 +346,7 @@ export const scoutApi = createApi({
|
|
|
346
346
|
// Generate signed URLs for artifacts
|
|
347
347
|
const uniqueFilePaths = Array.from(new Set(resultArtifacts
|
|
348
348
|
.map((artifact) => artifact.file_path)
|
|
349
|
-
.filter(
|
|
349
|
+
.filter(isNonEmptyStorageFilePath)));
|
|
350
350
|
let urlMap = new Map();
|
|
351
351
|
if (uniqueFilePaths.length > 0) {
|
|
352
352
|
try {
|
|
@@ -363,8 +363,8 @@ export const scoutApi = createApi({
|
|
|
363
363
|
}
|
|
364
364
|
const artifactsWithUrls = resultArtifacts.map((artifact) => ({
|
|
365
365
|
...artifact,
|
|
366
|
-
media_url: artifact.file_path
|
|
367
|
-
? urlMap.get(artifact.file_path)
|
|
366
|
+
media_url: isNonEmptyStorageFilePath(artifact.file_path)
|
|
367
|
+
? urlMap.get(artifact.file_path) ?? null
|
|
368
368
|
: null,
|
|
369
369
|
}));
|
|
370
370
|
const nextCursor = hasMore && resultArtifacts.length > 0
|
|
@@ -425,7 +425,7 @@ export const scoutApi = createApi({
|
|
|
425
425
|
// Generate signed URLs for artifacts
|
|
426
426
|
const uniqueFilePaths = Array.from(new Set(resultArtifacts
|
|
427
427
|
.map((artifact) => artifact.file_path)
|
|
428
|
-
.filter(
|
|
428
|
+
.filter(isNonEmptyStorageFilePath)));
|
|
429
429
|
let urlMap = new Map();
|
|
430
430
|
if (uniqueFilePaths.length > 0) {
|
|
431
431
|
try {
|
|
@@ -442,8 +442,8 @@ export const scoutApi = createApi({
|
|
|
442
442
|
}
|
|
443
443
|
const artifactsWithUrls = resultArtifacts.map((artifact) => ({
|
|
444
444
|
...artifact,
|
|
445
|
-
media_url: artifact.file_path
|
|
446
|
-
? urlMap.get(artifact.file_path)
|
|
445
|
+
media_url: isNonEmptyStorageFilePath(artifact.file_path)
|
|
446
|
+
? urlMap.get(artifact.file_path) ?? null
|
|
447
447
|
: null,
|
|
448
448
|
}));
|
|
449
449
|
const nextCursor = hasMore && resultArtifacts.length > 0
|
|
@@ -516,7 +516,7 @@ export const scoutApi = createApi({
|
|
|
516
516
|
event_data: row.event_data
|
|
517
517
|
? {
|
|
518
518
|
...row.event_data,
|
|
519
|
-
media_url: row.event_data.file_path
|
|
519
|
+
media_url: isNonEmptyStorageFilePath(row.event_data.file_path)
|
|
520
520
|
? urlMap.get(row.event_data.file_path) ?? null
|
|
521
521
|
: null,
|
|
522
522
|
}
|
|
@@ -524,7 +524,7 @@ export const scoutApi = createApi({
|
|
|
524
524
|
artifact_data: row.artifact_data
|
|
525
525
|
? {
|
|
526
526
|
...row.artifact_data,
|
|
527
|
-
media_url: row.artifact_data.file_path
|
|
527
|
+
media_url: isNonEmptyStorageFilePath(row.artifact_data.file_path)
|
|
528
528
|
? urlMap.get(row.artifact_data.file_path) ?? null
|
|
529
529
|
: null,
|
|
530
530
|
}
|
|
@@ -591,7 +591,7 @@ export const scoutApi = createApi({
|
|
|
591
591
|
event_data: row.event_data
|
|
592
592
|
? {
|
|
593
593
|
...row.event_data,
|
|
594
|
-
media_url: row.event_data.file_path
|
|
594
|
+
media_url: isNonEmptyStorageFilePath(row.event_data.file_path)
|
|
595
595
|
? urlMap.get(row.event_data.file_path) ?? null
|
|
596
596
|
: null,
|
|
597
597
|
}
|
|
@@ -599,7 +599,7 @@ export const scoutApi = createApi({
|
|
|
599
599
|
artifact_data: row.artifact_data
|
|
600
600
|
? {
|
|
601
601
|
...row.artifact_data,
|
|
602
|
-
media_url: row.artifact_data.file_path
|
|
602
|
+
media_url: isNonEmptyStorageFilePath(row.artifact_data.file_path)
|
|
603
603
|
? urlMap.get(row.artifact_data.file_path) ?? null
|
|
604
604
|
: null,
|
|
605
605
|
}
|