@morscherlab/mint-sdk 1.2.2 → 1.2.4
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/__tests__/composables/createFilePickerAdapter.test.d.ts +1 -0
- package/dist/__tests__/composables/usePickerNavigation.test.d.ts +1 -0
- package/dist/components/index.js +1 -1
- package/dist/{components-CxQVQCpP.js → components-CZzBCakZ.js} +38 -3
- package/dist/{components-CxQVQCpP.js.map → components-CZzBCakZ.js.map} +1 -1
- package/dist/composables/createFilePickerAdapter.d.ts +18 -0
- package/dist/composables/index.d.ts +2 -0
- package/dist/composables/index.js +2 -2
- package/dist/composables/usePlatformFilePickerAdapter.d.ts +3 -7
- package/dist/{composables-DAqOU8Aq.js → composables-BCbYb2lA.js} +125 -42
- package/dist/composables-BCbYb2lA.js.map +1 -0
- package/dist/index.js +3 -3
- package/dist/install.js +1 -1
- package/dist/types/filePicker.d.ts +2 -0
- package/package.json +1 -1
- package/src/__tests__/components/FilePicker.state.test.ts +19 -0
- package/src/__tests__/composables/createFilePickerAdapter.test.ts +142 -0
- package/src/__tests__/composables/useFileBrowser.test.ts +12 -0
- package/src/__tests__/composables/usePickerNavigation.test.ts +149 -0
- package/src/__tests__/composables/usePlatformFilePickerAdapter.test.ts +18 -0
- package/src/composables/createFilePickerAdapter.ts +145 -0
- package/src/composables/filePicker/usePickerNavigation.ts +42 -2
- package/src/composables/index.ts +2 -0
- package/src/composables/useFileBrowser.ts +6 -5
- package/src/composables/usePlatformFilePickerAdapter.ts +24 -91
- package/src/types/filePicker.ts +2 -0
- package/dist/composables-DAqOU8Aq.js.map +0 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { PickerAdapter, PickerRequest } from '../types/filePicker';
|
|
2
|
+
import { FileBrowserLocation, FileDirectoryListing, ServerMount } from '../types/fileBrowserTypes';
|
|
3
|
+
export interface FilePickerTransport {
|
|
4
|
+
listMounts(request?: PickerRequest): Promise<ServerMount[]>;
|
|
5
|
+
browse(location: FileBrowserLocation, request?: PickerRequest): Promise<FileDirectoryListing>;
|
|
6
|
+
}
|
|
7
|
+
export interface FilePickerAdapterOptions {
|
|
8
|
+
/** Show this directory's contents directly and prevent navigation outside it. */
|
|
9
|
+
rootLocation?: FileBrowserLocation;
|
|
10
|
+
}
|
|
11
|
+
/** Opaque picker identity; decode before passing a selection to a mount-scoped API. */
|
|
12
|
+
export declare function encodePlatformPickerPath(mountId: string, path?: string): string;
|
|
13
|
+
export declare function decodePlatformPickerPath(path: string): {
|
|
14
|
+
mountId: string;
|
|
15
|
+
path: string;
|
|
16
|
+
};
|
|
17
|
+
/** Mount browsing and search shared by platform and generated plugin clients. */
|
|
18
|
+
export declare function createFilePickerAdapter(transport: FilePickerTransport, options?: FilePickerAdapterOptions): PickerAdapter;
|
|
@@ -70,3 +70,5 @@ export { useRovingFocus, type UseRovingFocusOptions, type UseRovingFocusReturn,
|
|
|
70
70
|
export { reorderList, useListReorder, useReorderAnnouncer, REORDER_ANNOUNCER_STYLE, type ListReorderMove, type UseListReorderOptions, type UseListReorderReturn, type UseReorderAnnouncerReturn, } from './useListReorder';
|
|
71
71
|
export { useMenuKeyboard, type UseMenuKeyboardOptions, type UseMenuKeyboardReturn, } from './useMenuKeyboard';
|
|
72
72
|
export { usePlatformFilePickerAdapter, encodePlatformPickerPath, decodePlatformPickerPath } from './usePlatformFilePickerAdapter';
|
|
73
|
+
export { createFilePickerAdapter } from './createFilePickerAdapter';
|
|
74
|
+
export type { FilePickerTransport, FilePickerAdapterOptions } from './createFilePickerAdapter';
|
|
@@ -7,5 +7,5 @@ import { i as usePlatformContext, n as evaluateCondition, r as useForm, t as use
|
|
|
7
7
|
import { t as ANALYSIS_FILE_ARTIFACT_SCHEMA } from "../analysisArtifactTypes-DQ0MjwHZ.js";
|
|
8
8
|
import { B as toBioTemplateComponentProps, H as toBioTemplateComponentPropsById, L as toBioTemplateComponentBindings, P as getBioTemplateComponentBindings, R as toBioTemplateComponentBindingsById, l as requireBioTemplateControlSchema, o as getBioTemplateControlSchema } from "../templates-NuaNHohp.js";
|
|
9
9
|
import { n as useDebouncedWatch, t as useExperimentSelector } from "../useExperimentSelector-G_CAOFTX.js";
|
|
10
|
-
import { A as
|
|
11
|
-
export { ANALYSIS_FILE_ARTIFACT_SCHEMA, APP_EXPERIMENT_KEY, ATOMIC_WEIGHTS, AuthenticationRequiredError, DATE_PRESET_OPTIONS, DEFAULT_COLORS, DEFAULT_MOBILE_VIEWPORT_QUERY, DEFAULT_PRESETS, DEFAULT_UNITS, EXPERIMENT_STATUS_LABELS, EXPERIMENT_STATUS_OPTIONS, EXPERIMENT_STATUS_VARIANT_MAP, REORDER_ANNOUNCER_STYLE, SORT_OPTIONS, addMinutes, buildAnalysisArtifactTargetQuery, buildPluginEndpointUrl, candidateMatchesSearch, combinePluginJobSources, compareSortValues, compareTime, controlValuesToComponentBindings, controlValuesToComponentBindingsById, controlValuesToComponentProps, controlsToFormSchema, controlsToSectionFormSchema, controlsToSectionFormSchemas, controlsToSettingsSchema, controlsToSidebarPanels, controlsToTopBarSettingsConfig, controlsToViewIds, controlsToViewItems, coordinateToWellId, createColumnConditions, createGeneratedAnalysisTransport, createPluginClient, createPluginResourceClient, createRowConditions, createWellPlateWells, datePresetToISO, decodePlatformPickerPath, defineControlComponentBindings, defineControlModel, defineControls, defineDoseCalculatorControlProps, defineDoseDesignControlModel, defineWellPlateControlProps, defineWellPlateDoseComponentBindings, defineWellPlateDoseControlProps, detectDelimiter, downloadBlob, downloadPluginEndpoint, durationMinutes, encodePlatformPickerPath, evaluateCondition, experimentIdFromRoute, extractSampleNamesFromDesignData, extractSampleOptionsFromDesignData, extractSamplesFromDesignData, findAvailableSlots, findNearestTimeSlotIndex, formatDuration, formatExperimentDate, formatExperimentStatus, formatTime, formatTimeSlot, fromMinutes, generateDilutionSeries, generateTimeSlots, getBioTemplateComponentBindings, getBioTemplateComponentProps, getBioTemplateControlSchema, getControlDefaults, getDefaultControlView, getExperimentStatusVariant, getFieldRegistryEntry, getInjectedFrontendRevision, getPluginPageSelectorItems, getPresenceClientId, getTypeDefault, isTimeInRange, normalizeSearchQuery, parseAnalysisArtifactTarget, parseDelimitedText, parseTime, pluginFormDataFromPayload, rangesOverlap, readFileAsText, reorderList, requireBioTemplateControlSchema, resizedLeadingPanelWidth, resizedTrailingPanelWidth, resizedVerticalSplitPercent, resolveCurrentPluginId, resolveExperimentCode, resolvePluginBaseUrl, resolvePluginFrontendBase, runWellPlateValidation, snapToSlot, toBioTemplateComponentBindings, toBioTemplateComponentBindingsById, toBioTemplateComponentProps, toBioTemplateComponentPropsByComponent, toBioTemplateComponentPropsById, toMinutes, unwrapExperimentDesignData, uploadPluginEndpoint, useAnalysisArtifacts, useApi, useAppExperiment, useAsync, useAsyncBatch, useAuth, useAutoGroup, useBioTemplateComponents, useBioTemplateControls, useBioTemplatePackWorkspace, useBioTemplatePresetWorkspace, useBioTemplateWorkspace, useChemicalFormula, useCommandHistory, useConcentrationUnits, useControlSchema, useControlWorkspace, useCurrentExperiment, useDebouncedWatch, useDoseCalculator, useEventListener, useExpansionSet, useExperimentData, useExperimentSamples, useExperimentSave, useExperimentSelector, useFileBrowser, useFileImport, useFocusTrap, useForm, useFormBuilder, useGeneratedAnalysis, useGroupAssignment, useJobsStatusTray, useListReorder, useListSelection, useManualLayoutResize, useMenuKeyboard, useMobileSupportGate, useOptimisticMutation, usePasskey, usePlatformContext, usePlatformFilePickerAdapter, usePluginClient, usePluginConfig, usePluginEventStream, usePluginJobCenter, usePluginJobs, usePluginSettings, usePluginWorkspace, usePresenceHeartbeat, useProtocolTemplates, useRackEditor, useReagentSeries, useReorderAnnouncer, useRequestSyncState, useResourceCrud, useRovingFocus, useRuntimeAlignment, useSampleGroups, useScheduleDrag, useSelectionLimit, useSequenceUtils, useSortedItems, useTemplateCollection, useTextSearch, useTheme, useTimeUtils, useToast, useWellPainting, useWellPlateAdapter, useWellPlateEditor, useWellPlateValidation, validateImportFile, wellIdToCoordinate, wellIdsInRectangle };
|
|
10
|
+
import { A as useCommandHistory, B as useAsyncBatch, C as coordinateToWellId, D as createPluginResourceClient, E as wellIdsInRectangle, F as resizedLeadingPanelWidth, H as usePasskey, I as resizedTrailingPanelWidth, L as resizedVerticalSplitPercent, M as parseAnalysisArtifactTarget, N as useFileBrowser, O as useResourceCrud, P as usePluginConfig, R as useManualLayoutResize, S as useWellPlateAdapter, T as wellIdToCoordinate, U as useAuth, V as resolvePluginFrontendBase, _ as runWellPlateValidation, a as createPluginClient, b as createRowConditions, c as getPluginPageSelectorItems, d as useCurrentExperiment, f as usePluginClient, g as resolvePluginBaseUrl, h as buildPluginEndpointUrl, i as encodePlatformPickerPath, j as buildAnalysisArtifactTargetQuery, k as useOptimisticMutation, l as pluginFormDataFromPayload, m as usePluginSettings, n as createFilePickerAdapter, o as downloadBlob, p as usePluginEventStream, r as decodePlatformPickerPath, s as downloadPluginEndpoint, t as usePlatformFilePickerAdapter, u as uploadPluginEndpoint, v as useWellPlateValidation, w as useWellPainting, x as createWellPlateWells, y as createColumnConditions, z as useAsync } from "../composables-BCbYb2lA.js";
|
|
11
|
+
export { ANALYSIS_FILE_ARTIFACT_SCHEMA, APP_EXPERIMENT_KEY, ATOMIC_WEIGHTS, AuthenticationRequiredError, DATE_PRESET_OPTIONS, DEFAULT_COLORS, DEFAULT_MOBILE_VIEWPORT_QUERY, DEFAULT_PRESETS, DEFAULT_UNITS, EXPERIMENT_STATUS_LABELS, EXPERIMENT_STATUS_OPTIONS, EXPERIMENT_STATUS_VARIANT_MAP, REORDER_ANNOUNCER_STYLE, SORT_OPTIONS, addMinutes, buildAnalysisArtifactTargetQuery, buildPluginEndpointUrl, candidateMatchesSearch, combinePluginJobSources, compareSortValues, compareTime, controlValuesToComponentBindings, controlValuesToComponentBindingsById, controlValuesToComponentProps, controlsToFormSchema, controlsToSectionFormSchema, controlsToSectionFormSchemas, controlsToSettingsSchema, controlsToSidebarPanels, controlsToTopBarSettingsConfig, controlsToViewIds, controlsToViewItems, coordinateToWellId, createColumnConditions, createFilePickerAdapter, createGeneratedAnalysisTransport, createPluginClient, createPluginResourceClient, createRowConditions, createWellPlateWells, datePresetToISO, decodePlatformPickerPath, defineControlComponentBindings, defineControlModel, defineControls, defineDoseCalculatorControlProps, defineDoseDesignControlModel, defineWellPlateControlProps, defineWellPlateDoseComponentBindings, defineWellPlateDoseControlProps, detectDelimiter, downloadBlob, downloadPluginEndpoint, durationMinutes, encodePlatformPickerPath, evaluateCondition, experimentIdFromRoute, extractSampleNamesFromDesignData, extractSampleOptionsFromDesignData, extractSamplesFromDesignData, findAvailableSlots, findNearestTimeSlotIndex, formatDuration, formatExperimentDate, formatExperimentStatus, formatTime, formatTimeSlot, fromMinutes, generateDilutionSeries, generateTimeSlots, getBioTemplateComponentBindings, getBioTemplateComponentProps, getBioTemplateControlSchema, getControlDefaults, getDefaultControlView, getExperimentStatusVariant, getFieldRegistryEntry, getInjectedFrontendRevision, getPluginPageSelectorItems, getPresenceClientId, getTypeDefault, isTimeInRange, normalizeSearchQuery, parseAnalysisArtifactTarget, parseDelimitedText, parseTime, pluginFormDataFromPayload, rangesOverlap, readFileAsText, reorderList, requireBioTemplateControlSchema, resizedLeadingPanelWidth, resizedTrailingPanelWidth, resizedVerticalSplitPercent, resolveCurrentPluginId, resolveExperimentCode, resolvePluginBaseUrl, resolvePluginFrontendBase, runWellPlateValidation, snapToSlot, toBioTemplateComponentBindings, toBioTemplateComponentBindingsById, toBioTemplateComponentProps, toBioTemplateComponentPropsByComponent, toBioTemplateComponentPropsById, toMinutes, unwrapExperimentDesignData, uploadPluginEndpoint, useAnalysisArtifacts, useApi, useAppExperiment, useAsync, useAsyncBatch, useAuth, useAutoGroup, useBioTemplateComponents, useBioTemplateControls, useBioTemplatePackWorkspace, useBioTemplatePresetWorkspace, useBioTemplateWorkspace, useChemicalFormula, useCommandHistory, useConcentrationUnits, useControlSchema, useControlWorkspace, useCurrentExperiment, useDebouncedWatch, useDoseCalculator, useEventListener, useExpansionSet, useExperimentData, useExperimentSamples, useExperimentSave, useExperimentSelector, useFileBrowser, useFileImport, useFocusTrap, useForm, useFormBuilder, useGeneratedAnalysis, useGroupAssignment, useJobsStatusTray, useListReorder, useListSelection, useManualLayoutResize, useMenuKeyboard, useMobileSupportGate, useOptimisticMutation, usePasskey, usePlatformContext, usePlatformFilePickerAdapter, usePluginClient, usePluginConfig, usePluginEventStream, usePluginJobCenter, usePluginJobs, usePluginSettings, usePluginWorkspace, usePresenceHeartbeat, useProtocolTemplates, useRackEditor, useReagentSeries, useReorderAnnouncer, useRequestSyncState, useResourceCrud, useRovingFocus, useRuntimeAlignment, useSampleGroups, useScheduleDrag, useSelectionLimit, useSequenceUtils, useSortedItems, useTemplateCollection, useTextSearch, useTheme, useTimeUtils, useToast, useWellPainting, useWellPlateAdapter, useWellPlateEditor, useWellPlateValidation, validateImportFile, wellIdToCoordinate, wellIdsInRectangle };
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { PickerAdapter } from '../types/filePicker';
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
export declare function decodePlatformPickerPath(path: string): {
|
|
5
|
-
mountId: string;
|
|
6
|
-
path: string;
|
|
7
|
-
};
|
|
2
|
+
import { FilePickerAdapterOptions } from './createFilePickerAdapter';
|
|
3
|
+
export { encodePlatformPickerPath, decodePlatformPickerPath } from './createFilePickerAdapter';
|
|
8
4
|
/** Adapt the authenticated MINT mount API without exposing absolute host paths. */
|
|
9
|
-
export declare function usePlatformFilePickerAdapter(options?: {
|
|
5
|
+
export declare function usePlatformFilePickerAdapter(options?: FilePickerAdapterOptions & {
|
|
10
6
|
apiBaseUrl?: string;
|
|
11
7
|
}): PickerAdapter;
|
|
@@ -924,7 +924,7 @@ function useFileBrowser(options = {}) {
|
|
|
924
924
|
if (token === mountsToken) mountsLoading.value = false;
|
|
925
925
|
}
|
|
926
926
|
}
|
|
927
|
-
async function navigate(location) {
|
|
927
|
+
async function navigate(location, refresh = false) {
|
|
928
928
|
if (disposed || !location.mount_id) return;
|
|
929
929
|
clearTimeout(searchTimer);
|
|
930
930
|
const token = ++listToken;
|
|
@@ -936,7 +936,7 @@ function useFileBrowser(options = {}) {
|
|
|
936
936
|
resetListing();
|
|
937
937
|
sync.clearError();
|
|
938
938
|
try {
|
|
939
|
-
const query = `mount_id=${encodeURIComponent(location.mount_id)}&path=${encodeURIComponent(location.path)}&sort=${sort.value}` + (search.value ? `&search=${encodeURIComponent(search.value)}` : "") + typeRuleParams();
|
|
939
|
+
const query = `mount_id=${encodeURIComponent(location.mount_id)}&path=${encodeURIComponent(location.path)}&sort=${sort.value}` + (refresh ? "&refresh=true" : "") + (search.value ? `&search=${encodeURIComponent(search.value)}` : "") + typeRuleParams();
|
|
940
940
|
const listing = await api.get(`/filesystem/browse?${query}`, { signal: listingController.signal });
|
|
941
941
|
if (disposed || token !== listToken) return;
|
|
942
942
|
mountId.value = listing.mount_id;
|
|
@@ -981,7 +981,7 @@ function useFileBrowser(options = {}) {
|
|
|
981
981
|
if (mountId.value) await navigate({
|
|
982
982
|
mount_id: mountId.value,
|
|
983
983
|
path: path.value
|
|
984
|
-
});
|
|
984
|
+
}, true);
|
|
985
985
|
else await init();
|
|
986
986
|
}
|
|
987
987
|
function selectCurrentFolder() {
|
|
@@ -1004,14 +1004,23 @@ function useFileBrowser(options = {}) {
|
|
|
1004
1004
|
if (!mountId.value) return;
|
|
1005
1005
|
clearTimeout(searchTimer);
|
|
1006
1006
|
searchTimer = setTimeout(() => {
|
|
1007
|
-
|
|
1007
|
+
navigate({
|
|
1008
|
+
mount_id: mountId.value,
|
|
1009
|
+
path: path.value
|
|
1010
|
+
});
|
|
1008
1011
|
}, 250);
|
|
1009
1012
|
});
|
|
1010
1013
|
watch(sort, () => {
|
|
1011
|
-
if (mountId.value)
|
|
1014
|
+
if (mountId.value) navigate({
|
|
1015
|
+
mount_id: mountId.value,
|
|
1016
|
+
path: path.value
|
|
1017
|
+
});
|
|
1012
1018
|
});
|
|
1013
1019
|
watch(() => toValue(options.typeRules), () => {
|
|
1014
|
-
if (mountId.value)
|
|
1020
|
+
if (mountId.value) navigate({
|
|
1021
|
+
mount_id: mountId.value,
|
|
1022
|
+
path: path.value
|
|
1023
|
+
});
|
|
1015
1024
|
}, { deep: true });
|
|
1016
1025
|
if (getCurrentScope()) onScopeDispose(() => {
|
|
1017
1026
|
disposed = true;
|
|
@@ -2189,7 +2198,7 @@ function useCurrentExperiment(options = {}) {
|
|
|
2189
2198
|
};
|
|
2190
2199
|
}
|
|
2191
2200
|
//#endregion
|
|
2192
|
-
//#region src/composables/
|
|
2201
|
+
//#region src/composables/createFilePickerAdapter.ts
|
|
2193
2202
|
/** Opaque picker identity; decode before passing a selection to a mount-scoped API. */
|
|
2194
2203
|
function encodePlatformPickerPath(mountId, path = "") {
|
|
2195
2204
|
return JSON.stringify([mountId, path]);
|
|
@@ -2202,14 +2211,49 @@ function decodePlatformPickerPath(path) {
|
|
|
2202
2211
|
path: decoded[1]
|
|
2203
2212
|
};
|
|
2204
2213
|
}
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2214
|
+
function isRelativePath(path) {
|
|
2215
|
+
return path === "" || !/^[a-z]:/i.test(path) && !/[\\\x00-\x1f\x7f]/.test(path) && path.split("/").every((part) => part !== "" && part !== "." && part !== "..");
|
|
2216
|
+
}
|
|
2217
|
+
/** Mount browsing and search shared by platform and generated plugin clients. */
|
|
2218
|
+
function createFilePickerAdapter(transport, options = {}) {
|
|
2219
|
+
const root = options.rootLocation && { ...options.rootLocation };
|
|
2208
2220
|
const mountLabels = /* @__PURE__ */ new Map();
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2221
|
+
const listings = /* @__PURE__ */ new Map();
|
|
2222
|
+
let generation = 0;
|
|
2223
|
+
function invalidate() {
|
|
2224
|
+
generation++;
|
|
2225
|
+
listings.clear();
|
|
2226
|
+
mountLabels.clear();
|
|
2227
|
+
}
|
|
2228
|
+
function validateLocation(location) {
|
|
2229
|
+
if (!location.mount_id || !isRelativePath(location.path) || root && (location.mount_id !== root.mount_id || root.path !== "" && location.path !== root.path && !location.path.startsWith(`${root.path}/`))) throw new Error("Invalid file picker location.");
|
|
2230
|
+
}
|
|
2231
|
+
if (root) validateLocation(root);
|
|
2232
|
+
function begin(request) {
|
|
2233
|
+
request?.signal?.throwIfAborted();
|
|
2234
|
+
if (request?.refresh) invalidate();
|
|
2235
|
+
return generation;
|
|
2236
|
+
}
|
|
2237
|
+
function check(request, token) {
|
|
2238
|
+
request?.signal?.throwIfAborted();
|
|
2239
|
+
if (token !== generation) throw new DOMException("Cancelled", "AbortError");
|
|
2240
|
+
}
|
|
2241
|
+
async function read(path, request, token) {
|
|
2242
|
+
check(request, token);
|
|
2243
|
+
const decoded = path ? decodePlatformPickerPath(path) : void 0;
|
|
2244
|
+
const location = decoded ? {
|
|
2245
|
+
mount_id: decoded.mountId,
|
|
2246
|
+
path: decoded.path
|
|
2247
|
+
} : root;
|
|
2248
|
+
if (location) validateLocation(location);
|
|
2249
|
+
const key = location ? encodePlatformPickerPath(location.mount_id, location.path) : "";
|
|
2250
|
+
const cached = listings.get(key);
|
|
2251
|
+
if (cached) return cached;
|
|
2252
|
+
let nodes;
|
|
2253
|
+
if (!location) {
|
|
2254
|
+
const mounts = await transport.listMounts(request);
|
|
2255
|
+
check(request, token);
|
|
2256
|
+
nodes = mounts.map((mount) => {
|
|
2213
2257
|
mountLabels.set(mount.id, mount.label);
|
|
2214
2258
|
return {
|
|
2215
2259
|
kind: "folder",
|
|
@@ -2220,45 +2264,58 @@ function usePlatformFilePickerAdapter(options = {}) {
|
|
|
2220
2264
|
unavailableReason: mount.available === false ? "This mount is offline." : void 0
|
|
2221
2265
|
};
|
|
2222
2266
|
});
|
|
2223
|
-
}
|
|
2224
|
-
|
|
2225
|
-
|
|
2267
|
+
} else {
|
|
2268
|
+
const listing = await transport.browse(location, request);
|
|
2269
|
+
check(request, token);
|
|
2270
|
+
if (listing.truncated) throw new Error("This directory exceeds the server listing limit. Choose a smaller data directory.");
|
|
2271
|
+
const atRoot = root && location.mount_id === root.mount_id && location.path === root.path;
|
|
2272
|
+
nodes = (listing.entries ?? []).map((entry) => {
|
|
2273
|
+
if (!isRelativePath(entry.path) || !entry.name || entry.path !== `${location.path ? `${location.path}/` : ""}${entry.name}` || entry.name.includes("/")) throw new Error("Invalid file picker directory entry.");
|
|
2274
|
+
const common = {
|
|
2275
|
+
path: encodePlatformPickerPath(location.mount_id, entry.path),
|
|
2276
|
+
parentPath: atRoot ? null : key,
|
|
2277
|
+
parentName: `${mountLabels.get(location.mount_id) ?? location.mount_id}${location.path ? ` / ${location.path}` : ""}`,
|
|
2278
|
+
name: entry.name,
|
|
2279
|
+
bytes: entry.size_bytes
|
|
2280
|
+
};
|
|
2281
|
+
return entry.kind === "directory" ? {
|
|
2282
|
+
...common,
|
|
2283
|
+
kind: "folder"
|
|
2284
|
+
} : {
|
|
2285
|
+
...common,
|
|
2286
|
+
kind: "file",
|
|
2287
|
+
format: pickerFormat(entry.name)
|
|
2288
|
+
};
|
|
2289
|
+
});
|
|
2226
2290
|
}
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
const location = decodePlatformPickerPath(path);
|
|
2230
|
-
const query = new URLSearchParams({
|
|
2231
|
-
mount_id: location.mountId,
|
|
2232
|
-
path: location.path
|
|
2233
|
-
});
|
|
2234
|
-
const listing = await api.get(`/filesystem/browse?${query}`, { signal: request?.signal });
|
|
2235
|
-
if (listing.truncated) throw new Error("This directory exceeds the server listing limit. Choose a smaller data directory.");
|
|
2236
|
-
return (listing.entries ?? []).map((entry) => ({
|
|
2237
|
-
kind: entry.kind === "directory" ? "folder" : "file",
|
|
2238
|
-
path: encodePlatformPickerPath(location.mountId, entry.path),
|
|
2239
|
-
parentPath: path,
|
|
2240
|
-
parentName: `${mountLabels.get(location.mountId) ?? location.mountId}${location.path ? ` / ${location.path}` : ""}`,
|
|
2241
|
-
name: entry.name,
|
|
2242
|
-
bytes: entry.size_bytes,
|
|
2243
|
-
...entry.kind === "directory" ? { hasChildren: entry.child_count !== 0 } : { format: pickerFormat(entry.name) }
|
|
2244
|
-
}));
|
|
2291
|
+
listings.set(key, nodes);
|
|
2292
|
+
return nodes;
|
|
2245
2293
|
}
|
|
2246
2294
|
return {
|
|
2247
|
-
|
|
2248
|
-
|
|
2295
|
+
invalidate,
|
|
2296
|
+
listRoot: async (request) => read("", request, begin(request)),
|
|
2297
|
+
listChildren: async (path, request) => read(path, request, begin(request)),
|
|
2249
2298
|
async search(query, scope, request) {
|
|
2299
|
+
const token = begin(request);
|
|
2250
2300
|
const matches = [];
|
|
2251
2301
|
const queue = [scope.path];
|
|
2252
2302
|
const visited = /* @__PURE__ */ new Set();
|
|
2303
|
+
const needle = query.toLowerCase();
|
|
2304
|
+
let currentRequest = request;
|
|
2253
2305
|
while (queue.length) {
|
|
2254
|
-
request
|
|
2306
|
+
check(request, token);
|
|
2255
2307
|
const path = queue.shift();
|
|
2256
2308
|
if (visited.has(path)) continue;
|
|
2257
2309
|
visited.add(path);
|
|
2258
2310
|
if (visited.size > 500) throw new Error("Search reached its folder limit. Search a smaller location or turn off Subfolders.");
|
|
2259
|
-
const nodes =
|
|
2311
|
+
const nodes = await read(path, currentRequest, token);
|
|
2312
|
+
check(request, token);
|
|
2313
|
+
if (currentRequest?.refresh) {
|
|
2314
|
+
currentRequest = { ...currentRequest };
|
|
2315
|
+
delete currentRequest.refresh;
|
|
2316
|
+
}
|
|
2260
2317
|
for (const node of nodes) {
|
|
2261
|
-
if (node.name.toLowerCase().includes(
|
|
2318
|
+
if (node.name.toLowerCase().includes(needle)) matches.push(node);
|
|
2262
2319
|
if (scope.recursive && node.kind === "folder" && !node.unavailableReason) queue.push(node.path);
|
|
2263
2320
|
}
|
|
2264
2321
|
if (matches.length > 1e4) throw new Error("Too many search results. Use a more specific search.");
|
|
@@ -2268,6 +2325,32 @@ function usePlatformFilePickerAdapter(options = {}) {
|
|
|
2268
2325
|
};
|
|
2269
2326
|
}
|
|
2270
2327
|
//#endregion
|
|
2271
|
-
|
|
2328
|
+
//#region src/composables/usePlatformFilePickerAdapter.ts
|
|
2329
|
+
/** Adapt the authenticated MINT mount API without exposing absolute host paths. */
|
|
2330
|
+
function usePlatformFilePickerAdapter(options = {}) {
|
|
2331
|
+
const api = useApi({ baseUrl: options.apiBaseUrl ?? getInjectedPlatformContext()?.platformApiUrl });
|
|
2332
|
+
return createFilePickerAdapter({
|
|
2333
|
+
async listMounts(request) {
|
|
2334
|
+
try {
|
|
2335
|
+
const url = `/filesystem/mounts${request?.refresh ? "?refresh=true" : ""}`;
|
|
2336
|
+
const { mounts } = await api.get(url, { signal: request?.signal });
|
|
2337
|
+
return mounts;
|
|
2338
|
+
} catch (cause) {
|
|
2339
|
+
if (cause.response?.status === 404) return [];
|
|
2340
|
+
throw cause;
|
|
2341
|
+
}
|
|
2342
|
+
},
|
|
2343
|
+
browse(location, request) {
|
|
2344
|
+
const query = new URLSearchParams({
|
|
2345
|
+
mount_id: location.mount_id,
|
|
2346
|
+
path: location.path
|
|
2347
|
+
});
|
|
2348
|
+
if (request?.refresh) query.set("refresh", "true");
|
|
2349
|
+
return api.get(`/filesystem/browse?${query}`, { signal: request?.signal });
|
|
2350
|
+
}
|
|
2351
|
+
}, options);
|
|
2352
|
+
}
|
|
2353
|
+
//#endregion
|
|
2354
|
+
export { useCommandHistory as A, useAsyncBatch as B, coordinateToWellId as C, createPluginResourceClient as D, wellIdsInRectangle as E, resizedLeadingPanelWidth as F, usePasskey as H, resizedTrailingPanelWidth as I, resizedVerticalSplitPercent as L, parseAnalysisArtifactTarget as M, useFileBrowser as N, useResourceCrud as O, usePluginConfig as P, useManualLayoutResize as R, useWellPlateAdapter as S, wellIdToCoordinate as T, useAuth as U, resolvePluginFrontendBase as V, runWellPlateValidation as _, createPluginClient as a, createRowConditions as b, getPluginPageSelectorItems as c, useCurrentExperiment as d, usePluginClient as f, resolvePluginBaseUrl as g, buildPluginEndpointUrl as h, encodePlatformPickerPath as i, buildAnalysisArtifactTargetQuery as j, useOptimisticMutation as k, pluginFormDataFromPayload as l, usePluginSettings as m, createFilePickerAdapter as n, downloadBlob as o, usePluginEventStream as p, decodePlatformPickerPath as r, downloadPluginEndpoint as s, usePlatformFilePickerAdapter as t, uploadPluginEndpoint as u, useWellPlateValidation as v, useWellPainting as w, createWellPlateWells as x, createColumnConditions as y, useAsync as z };
|
|
2272
2355
|
|
|
2273
|
-
//# sourceMappingURL=composables-
|
|
2356
|
+
//# sourceMappingURL=composables-BCbYb2lA.js.map
|