@jbrowse/core 4.0.4 → 4.1.0

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.
Files changed (45) hide show
  1. package/esm/PluginLoader.js +11 -9
  2. package/esm/pluggableElementTypes/RpcMethodType.d.ts +1 -0
  3. package/esm/pluggableElementTypes/RpcMethodType.js +49 -5
  4. package/esm/pluggableElementTypes/RpcMethodTypeWithFiltersAndRenameRegions.js +1 -0
  5. package/esm/pluggableElementTypes/models/saveTrackFileTypes/bed.js +5 -2
  6. package/esm/pluggableElementTypes/models/saveTrackFileTypes/genbank.js +57 -26
  7. package/esm/pluggableElementTypes/models/saveTrackFileTypes/gff3.js +35 -16
  8. package/esm/pluggableElementTypes/renderers/LayoutSession.js +6 -3
  9. package/esm/pluggableElementTypes/renderers/ServerSideRendererType.js +4 -1
  10. package/esm/pluggableElementTypes/renderers/util/serializableFilterChain.d.ts +2 -1
  11. package/esm/pluggableElementTypes/renderers/util/serializableFilterChain.js +2 -2
  12. package/esm/rpc/methods/CoreRender.js +7 -2
  13. package/esm/ui/FileSelector/FileSelector.d.ts +0 -1
  14. package/esm/ui/FileSelector/FileSelector.js +19 -31
  15. package/esm/ui/FileSelector/LocalFileChooser.js +90 -26
  16. package/esm/ui/FileSelector/SourceTypeSelector.js +18 -33
  17. package/esm/ui/FileSelector/util.d.ts +8 -0
  18. package/esm/ui/FileSelector/util.js +34 -0
  19. package/esm/ui/SnackbarContents.js +4 -4
  20. package/esm/ui/SnackbarModel.d.ts +4 -4
  21. package/esm/ui/SnackbarModel.js +18 -7
  22. package/esm/ui/index.d.ts +1 -1
  23. package/esm/ui/index.js +1 -1
  24. package/esm/util/IntervalTree.d.ts +42 -0
  25. package/esm/util/IntervalTree.js +257 -0
  26. package/esm/util/colord.d.ts +22 -8
  27. package/esm/util/colord.js +227 -10
  28. package/esm/util/crypto.d.ts +7 -0
  29. package/esm/util/crypto.js +536 -0
  30. package/esm/util/fileHandleStore.d.ts +6 -0
  31. package/esm/util/fileHandleStore.js +68 -0
  32. package/esm/util/idMaker.js +9 -1
  33. package/esm/util/index.d.ts +3 -0
  34. package/esm/util/index.js +3 -0
  35. package/esm/util/io/index.js +11 -1
  36. package/esm/util/jexl.js +1 -0
  37. package/esm/util/tracks.d.ts +41 -7
  38. package/esm/util/tracks.js +141 -9
  39. package/esm/util/types/index.d.ts +10 -4
  40. package/esm/util/types/index.js +6 -0
  41. package/esm/util/types/mst.d.ts +17 -0
  42. package/esm/util/types/mst.js +10 -2
  43. package/package.json +350 -15
  44. package/esm/ui/FileSelector/index.d.ts +0 -1
  45. package/esm/ui/FileSelector/index.js +0 -1
package/esm/util/jexl.js CHANGED
@@ -24,6 +24,7 @@ export default function JexlF() {
24
24
  j.addFunction('charAt', (s, index) => s.charAt(index));
25
25
  j.addFunction('charCodeAt', (s, index) => s.charCodeAt(index));
26
26
  j.addFunction('codePointAt', (s, pos) => s.codePointAt(pos));
27
+ j.addFunction('includes', (s, search) => s.includes(search));
27
28
  j.addFunction('startsWith', (s, search, len) => s.startsWith(search, len));
28
29
  j.addFunction('endsWith', (s, search, len) => s.endsWith(search, len));
29
30
  j.addFunction('padEnd', (s, len, pad) => s.padEnd(len, pad));
@@ -1,4 +1,4 @@
1
- import type { FileLocation, PreFileLocation } from './types/index.ts';
1
+ import type { BlobLocation, FileHandleLocation, FileLocation, PreFileLocation } from './types/index.ts';
2
2
  import type { AnyConfigurationModel } from '../configuration/index.ts';
3
3
  import type { IAnyStateTreeNode, IAnyType, Instance, types } from '@jbrowse/mobx-state-tree';
4
4
  export declare function getTrackAssemblyNames(track: IAnyStateTreeNode & {
@@ -12,12 +12,46 @@ export declare const UNSUPPORTED = "UNSUPPORTED";
12
12
  export declare function getBlob(id: string): File | undefined;
13
13
  export declare function getBlobMap(): Record<string, File>;
14
14
  export declare function setBlobMap(map: Record<string, File>): void;
15
- export declare function storeBlobLocation(location: PreFileLocation): import("./index.ts").PreUriLocation | import("./index.ts").PreLocalPathLocation | {
16
- name: string;
17
- blobId: string;
18
- locationType: string;
19
- };
20
- export declare function makeIndex(location: FileLocation, suffix: string): import("./index.ts").BlobLocation | {
15
+ export declare function storeBlobLocation(location: PreFileLocation): BlobLocation | PreFileLocation;
16
+ export declare function getFileFromCache(handleId: string): File | undefined;
17
+ export declare function setFileInCache(handleId: string, file: File): void;
18
+ export declare function clearFileFromCache(handleId: string): void;
19
+ export declare function getFileHandleCache(): Record<string, File>;
20
+ export declare function setFileHandleCache(cache: Record<string, File>): void;
21
+ export declare function ensureFileHandleReady(handleId: string, requestPermission?: boolean): Promise<File>;
22
+ export declare function storeFileHandleLocation(handle: FileSystemFileHandle): Promise<FileHandleLocation>;
23
+ export declare function restoreFileHandles(handleIds: string[], requestPermission?: boolean): Promise<({
24
+ handleId: string;
25
+ success: boolean;
26
+ error?: undefined;
27
+ } | {
28
+ handleId: string;
29
+ success: boolean;
30
+ error: unknown;
31
+ })[]>;
32
+ export declare function findFileHandleIds(obj: unknown, handleIds?: Set<string>, seen?: WeakSet<object>): Set<string>;
33
+ export declare function restoreFileHandlesFromSnapshot(sessionSnapshot: unknown, requestPermission?: boolean): Promise<({
34
+ handleId: string;
35
+ success: boolean;
36
+ error?: undefined;
37
+ } | {
38
+ handleId: string;
39
+ success: boolean;
40
+ error: unknown;
41
+ })[]>;
42
+ export declare function getPendingFileHandleIds(): string[];
43
+ export declare function setPendingFileHandleIds(ids: string[]): void;
44
+ export declare function clearPendingFileHandleIds(): void;
45
+ export declare function restorePendingFileHandles(): Promise<({
46
+ handleId: string;
47
+ success: boolean;
48
+ error?: undefined;
49
+ } | {
50
+ handleId: string;
51
+ success: boolean;
52
+ error: unknown;
53
+ })[]>;
54
+ export declare function makeIndex(location: FileLocation, suffix: string): BlobLocation | FileHandleLocation | {
21
55
  uri: string;
22
56
  locationType: string;
23
57
  localPath?: undefined;
@@ -1,4 +1,5 @@
1
- import { getParent, isRoot, isStateTreeNode } from '@jbrowse/mobx-state-tree';
1
+ import { getParent, getSnapshot, isRoot, isStateTreeNode, } from '@jbrowse/mobx-state-tree';
2
+ import { getFileHandle, storeFileHandle, verifyPermission, } from "./fileHandleStore.js";
2
3
  import { getEnv, getSession, objectHash } from "./index.js";
3
4
  import { readConfObject } from "../configuration/index.js";
4
5
  const trackAssemblyNamesCache = new WeakMap();
@@ -60,10 +61,121 @@ export function storeBlobLocation(location) {
60
61
  if ('blob' in location) {
61
62
  const blobId = `b${Date.now()}-${counter++}`;
62
63
  blobMap[blobId] = location.blob;
63
- return { name: location.blob.name, blobId, locationType: 'BlobLocation' };
64
+ return {
65
+ name: location.blob.name,
66
+ blobId,
67
+ locationType: 'BlobLocation',
68
+ };
64
69
  }
65
70
  return location;
66
71
  }
72
+ let fileHandleCache = {};
73
+ export function getFileFromCache(handleId) {
74
+ return fileHandleCache[handleId];
75
+ }
76
+ export function setFileInCache(handleId, file) {
77
+ fileHandleCache[handleId] = file;
78
+ }
79
+ export function clearFileFromCache(handleId) {
80
+ delete fileHandleCache[handleId];
81
+ }
82
+ export function getFileHandleCache() {
83
+ return fileHandleCache;
84
+ }
85
+ export function setFileHandleCache(cache) {
86
+ fileHandleCache = cache;
87
+ }
88
+ export async function ensureFileHandleReady(handleId, requestPermission = true) {
89
+ const cached = fileHandleCache[handleId];
90
+ if (cached) {
91
+ return cached;
92
+ }
93
+ const handle = await getFileHandle(handleId);
94
+ if (!handle) {
95
+ throw new Error(`File handle not found for handleId: ${handleId}. The file may have been opened in a different browser or the IndexedDB was cleared.`);
96
+ }
97
+ const hasPermission = await verifyPermission(handle, requestPermission);
98
+ if (!hasPermission) {
99
+ throw new Error(`Permission denied for file "${handle.name}". Click "Restore access" to grant permission.`);
100
+ }
101
+ const file = await handle.getFile();
102
+ fileHandleCache[handleId] = file;
103
+ return file;
104
+ }
105
+ export async function storeFileHandleLocation(handle) {
106
+ const handleId = await storeFileHandle(handle);
107
+ const file = await handle.getFile();
108
+ fileHandleCache[handleId] = file;
109
+ return {
110
+ locationType: 'FileHandleLocation',
111
+ name: handle.name,
112
+ handleId,
113
+ };
114
+ }
115
+ export async function restoreFileHandles(handleIds, requestPermission = false) {
116
+ const results = [];
117
+ for (const handleId of handleIds) {
118
+ try {
119
+ await ensureFileHandleReady(handleId, requestPermission);
120
+ results.push({ handleId, success: true });
121
+ }
122
+ catch (e) {
123
+ results.push({ handleId, success: false, error: e });
124
+ }
125
+ }
126
+ return results;
127
+ }
128
+ export function findFileHandleIds(obj, handleIds = new Set(), seen = new WeakSet()) {
129
+ if (!obj || typeof obj !== 'object') {
130
+ return handleIds;
131
+ }
132
+ if (seen.has(obj)) {
133
+ return handleIds;
134
+ }
135
+ seen.add(obj);
136
+ if (Array.isArray(obj)) {
137
+ for (const item of obj) {
138
+ findFileHandleIds(item, handleIds, seen);
139
+ }
140
+ }
141
+ else {
142
+ const record = obj;
143
+ if (record.locationType === 'FileHandleLocation' &&
144
+ typeof record.handleId === 'string') {
145
+ handleIds.add(record.handleId);
146
+ }
147
+ for (const value of Object.values(record)) {
148
+ findFileHandleIds(value, handleIds, seen);
149
+ }
150
+ }
151
+ return handleIds;
152
+ }
153
+ export async function restoreFileHandlesFromSnapshot(sessionSnapshot, requestPermission = false) {
154
+ const handleIds = findFileHandleIds(sessionSnapshot);
155
+ if (handleIds.size > 0) {
156
+ return restoreFileHandles([...handleIds], requestPermission);
157
+ }
158
+ return [];
159
+ }
160
+ let pendingFileHandleIds = [];
161
+ export function getPendingFileHandleIds() {
162
+ return pendingFileHandleIds;
163
+ }
164
+ export function setPendingFileHandleIds(ids) {
165
+ pendingFileHandleIds = ids;
166
+ }
167
+ export function clearPendingFileHandleIds() {
168
+ pendingFileHandleIds = [];
169
+ }
170
+ export async function restorePendingFileHandles() {
171
+ if (pendingFileHandleIds.length === 0) {
172
+ return [];
173
+ }
174
+ const results = await restoreFileHandles(pendingFileHandleIds, true);
175
+ const stillFailed = results.filter(r => !r.success).map(r => r.handleId);
176
+ pendingFileHandleIds = stillFailed;
177
+ return results;
178
+ }
67
179
  export function makeIndex(location, suffix) {
68
180
  if ('uri' in location) {
69
181
  return {
@@ -88,10 +200,22 @@ export function getFileName(track) {
88
200
  const uri = 'uri' in track ? track.uri : undefined;
89
201
  const localPath = 'localPath' in track ? track.localPath : undefined;
90
202
  const blob = 'blobId' in track ? track : undefined;
91
- return (blob?.name ||
92
- uri?.slice(uri.lastIndexOf('/') + 1) ||
93
- localPath?.slice(localPath.replace(/\\/g, '/').lastIndexOf('/') + 1) ||
94
- '');
203
+ const fileHandle = 'handleId' in track ? track : undefined;
204
+ if (blob?.name) {
205
+ return blob.name;
206
+ }
207
+ if (fileHandle?.name) {
208
+ return fileHandle.name;
209
+ }
210
+ if (uri) {
211
+ const normalized = uri.replace(/\\/g, '/');
212
+ return normalized.slice(normalized.lastIndexOf('/') + 1);
213
+ }
214
+ if (localPath) {
215
+ const normalized = localPath.replace(/\\/g, '/');
216
+ return normalized.slice(normalized.lastIndexOf('/') + 1);
217
+ }
218
+ return '';
95
219
  }
96
220
  export function guessAdapter(file, index, adapterHint, model) {
97
221
  if (model) {
@@ -165,10 +289,14 @@ export function showTrackGeneric(self, trackId, initialSnapshot = {}, displayIni
165
289
  if (found) {
166
290
  return found;
167
291
  }
168
- const conf = session.getTracksById()[trackId];
169
- if (!conf) {
292
+ const rawConf = session.getTracksById()[trackId];
293
+ if (!rawConf) {
170
294
  throw new Error(`Could not resolve identifier "${trackId}"`);
171
295
  }
296
+ const confSnapshot = isStateTreeNode(rawConf)
297
+ ? getSnapshot(rawConf)
298
+ : structuredClone(rawConf);
299
+ const conf = pluginManager.evaluateExtensionPoint('Core-preProcessTrackConfig', confSnapshot);
172
300
  const trackType = pluginManager.getTrackType(conf.type);
173
301
  if (!trackType) {
174
302
  throw new Error(`Unknown track type ${conf.type}`);
@@ -177,12 +305,15 @@ export function showTrackGeneric(self, trackId, initialSnapshot = {}, displayIni
177
305
  const supportedDisplays = new Set(viewType.displayTypes.map(d => d.name));
178
306
  const displays = conf.displays ?? [];
179
307
  const displayConf = displays.find((d) => supportedDisplays.has(d.type));
180
- const displayType = displayConf?.type ??
308
+ const snapshotType = displayInitialSnapshot.type;
309
+ const defaultDisplayType = displayConf?.type ??
181
310
  trackType.displayTypes.find(d => supportedDisplays.has(d.name))?.name;
311
+ const displayType = snapshotType ?? defaultDisplayType;
182
312
  if (!displayType) {
183
313
  throw new Error(`Could not find a compatible display for view type ${self.type}`);
184
314
  }
185
315
  const displayId = displayConf?.displayId ?? `${trackId}-${displayType}`;
316
+ const { type: _type, displayId: _displayId, ...displayConfState } = displayConf ?? {};
186
317
  const track = trackType.stateModel.create({
187
318
  ...initialSnapshot,
188
319
  type: conf.type,
@@ -191,6 +322,7 @@ export function showTrackGeneric(self, trackId, initialSnapshot = {}, displayIni
191
322
  {
192
323
  type: displayType,
193
324
  configuration: displayId,
325
+ ...displayConfState,
194
326
  ...displayInitialSnapshot,
195
327
  },
196
328
  ],
@@ -1,5 +1,5 @@
1
1
  import type React from 'react';
2
- import type { BlobLocation as MUBlobLocation, LocalPathLocation as MULocalPathLocation, NoAssemblyRegion as MUNoAssemblyRegion, Region as MUIRegion, UriLocation as MUUriLocation } from './mst.ts';
2
+ import type { BlobLocation as MUBlobLocation, FileHandleLocation as MUFileHandleLocation, LocalPathLocation as MULocalPathLocation, NoAssemblyRegion as MUNoAssemblyRegion, Region as MUIRegion, UriLocation as MUUriLocation } from './mst.ts';
3
3
  import type TextSearchManager from '../../TextSearch/TextSearchManager.ts';
4
4
  import type assemblyManager from '../../assemblyManager/index.ts';
5
5
  import type { AnyConfigurationModel } from '../../configuration/index.ts';
@@ -64,7 +64,7 @@ export interface AbstractSessionModel extends AbstractViewContainer {
64
64
  clearSelection: () => void;
65
65
  duplicateCurrentSession?: () => void;
66
66
  notify: (message: string, level?: NotificationLevel, action?: SnackAction) => void;
67
- notifyError: (message: string, error?: unknown, extra?: unknown) => void;
67
+ notifyError: (message: string, error?: unknown, extra?: unknown, action?: SnackAction) => void;
68
68
  assemblyManager: AssemblyManager;
69
69
  version: string;
70
70
  getTrackActionMenuItems?: (config: AnyConfigurationModel, extraTrackActions?: MenuItem[]) => MenuItem[];
@@ -246,6 +246,9 @@ export interface UriLocation extends SnapshotIn<typeof MUUriLocation> {
246
246
  export declare function isUriLocation(location: unknown): location is UriLocation;
247
247
  export declare function isLocalPathLocation(location: unknown): location is LocalPathLocation;
248
248
  export declare function isBlobLocation(location: unknown): location is BlobLocation;
249
+ export interface FileHandleLocation extends SnapshotIn<typeof MUFileHandleLocation> {
250
+ }
251
+ export declare function isFileHandleLocation(location: unknown): location is FileHandleLocation;
249
252
  export declare class AuthNeededError extends Error {
250
253
  message: string;
251
254
  url: string;
@@ -260,7 +263,7 @@ export declare function isAuthNeededException(exception: unknown): exception is
260
263
  export declare function isRetryException(exception: Error): boolean;
261
264
  export interface BlobLocation extends SnapshotIn<typeof MUBlobLocation> {
262
265
  }
263
- export type FileLocation = LocalPathLocation | UriLocation | BlobLocation;
266
+ export type FileLocation = LocalPathLocation | UriLocation | BlobLocation | FileHandleLocation;
264
267
  export interface PreUriLocation {
265
268
  uri: string;
266
269
  }
@@ -270,5 +273,8 @@ export interface PreLocalPathLocation {
270
273
  export interface PreBlobLocation {
271
274
  blob: File;
272
275
  }
273
- export type PreFileLocation = PreUriLocation | PreLocalPathLocation | PreBlobLocation;
276
+ export interface PreFileHandleLocation {
277
+ handle: FileSystemFileHandle;
278
+ }
279
+ export type PreFileLocation = PreUriLocation | PreLocalPathLocation | PreBlobLocation | PreFileHandleLocation;
274
280
  export { default as TextSearchManager } from '../../TextSearch/TextSearchManager.ts';
@@ -98,6 +98,12 @@ export function isBlobLocation(location) {
98
98
  'blobId' in location &&
99
99
  !!location.blobId);
100
100
  }
101
+ export function isFileHandleLocation(location) {
102
+ return (typeof location === 'object' &&
103
+ location !== null &&
104
+ 'handleId' in location &&
105
+ !!location.handleId);
106
+ }
101
107
  export class AuthNeededError extends Error {
102
108
  message;
103
109
  url;
@@ -25,6 +25,11 @@ export declare const BlobLocation: import("@jbrowse/mobx-state-tree").IModelType
25
25
  name: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
26
26
  blobId: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
27
27
  }, {}, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>;
28
+ export declare const FileHandleLocation: import("@jbrowse/mobx-state-tree").IModelType<{
29
+ locationType: import("@jbrowse/mobx-state-tree").ISimpleType<"FileHandleLocation">;
30
+ name: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
31
+ handleId: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
32
+ }, {}, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>;
28
33
  export declare const UriLocationRaw: import("@jbrowse/mobx-state-tree").IModelType<{
29
34
  locationType: import("@jbrowse/mobx-state-tree").ISimpleType<"UriLocation">;
30
35
  uri: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
@@ -66,6 +71,10 @@ export declare const FileLocation: import("@jbrowse/mobx-state-tree").ISnapshotP
66
71
  locationType: import("@jbrowse/mobx-state-tree").ISimpleType<"BlobLocation">;
67
72
  name: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
68
73
  blobId: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
74
+ }>> | import("@jbrowse/mobx-state-tree").ModelCreationType<import("@jbrowse/mobx-state-tree/dist/internal").ExtractCFromProps<{
75
+ locationType: import("@jbrowse/mobx-state-tree").ISimpleType<"FileHandleLocation">;
76
+ name: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
77
+ handleId: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
69
78
  }>> | import("@jbrowse/mobx-state-tree").ModelCreationType<import("@jbrowse/mobx-state-tree/dist/internal").ExtractCFromProps<{
70
79
  locationType: import("@jbrowse/mobx-state-tree").ISimpleType<"LocalPathLocation">;
71
80
  localPath: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
@@ -81,6 +90,10 @@ export declare const FileLocation: import("@jbrowse/mobx-state-tree").ISnapshotP
81
90
  locationType: import("@jbrowse/mobx-state-tree").ISimpleType<"BlobLocation">;
82
91
  name: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
83
92
  blobId: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
93
+ }> | import("@jbrowse/mobx-state-tree").ModelSnapshotType<{
94
+ locationType: import("@jbrowse/mobx-state-tree").ISimpleType<"FileHandleLocation">;
95
+ name: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
96
+ handleId: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
84
97
  }> | import("@jbrowse/mobx-state-tree").ModelSnapshotType<{
85
98
  locationType: import("@jbrowse/mobx-state-tree").ISimpleType<"LocalPathLocation">;
86
99
  localPath: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
@@ -88,6 +101,10 @@ export declare const FileLocation: import("@jbrowse/mobx-state-tree").ISnapshotP
88
101
  locationType: import("@jbrowse/mobx-state-tree").ISimpleType<"BlobLocation">;
89
102
  name: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
90
103
  blobId: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
104
+ }, {}> | import("@jbrowse/mobx-state-tree").ModelInstanceType<{
105
+ locationType: import("@jbrowse/mobx-state-tree").ISimpleType<"FileHandleLocation">;
106
+ name: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
107
+ handleId: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
91
108
  }, {}> | import("@jbrowse/mobx-state-tree").ModelInstanceType<{
92
109
  locationType: import("@jbrowse/mobx-state-tree").ISimpleType<"LocalPathLocation">;
93
110
  localPath: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
@@ -23,6 +23,11 @@ export const BlobLocation = types.model('BlobLocation', {
23
23
  name: types.string,
24
24
  blobId: types.string,
25
25
  });
26
+ export const FileHandleLocation = types.model('FileHandleLocation', {
27
+ locationType: types.literal('FileHandleLocation'),
28
+ name: types.string,
29
+ handleId: types.string,
30
+ });
26
31
  export const UriLocationRaw = types.model('UriLocation', {
27
32
  locationType: types.literal('UriLocation'),
28
33
  uri: types.string,
@@ -42,14 +47,14 @@ export const UriLocation = types.snapshotProcessor(UriLocationRaw, {
42
47
  return snap;
43
48
  },
44
49
  });
45
- export const FileLocation = types.snapshotProcessor(types.union(LocalPathLocation, UriLocation, BlobLocation), {
50
+ export const FileLocation = types.snapshotProcessor(types.union(LocalPathLocation, UriLocation, BlobLocation, FileHandleLocation), {
46
51
  preProcessor(snap) {
47
52
  if (!snap) {
48
53
  return undefined;
49
54
  }
50
55
  const { locationType, ...rest } = snap;
51
56
  if (!locationType) {
52
- const { uri, localPath, blob } = rest;
57
+ const { uri, localPath, blob, handleId } = rest;
53
58
  let locationType = '';
54
59
  if (uri !== undefined) {
55
60
  locationType = 'UriLocation';
@@ -60,6 +65,9 @@ export const FileLocation = types.snapshotProcessor(types.union(LocalPathLocatio
60
65
  else if (blob !== undefined) {
61
66
  locationType = 'BlobLocation';
62
67
  }
68
+ else if (handleId !== undefined) {
69
+ locationType = 'FileHandleLocation';
70
+ }
63
71
  return { ...rest, locationType };
64
72
  }
65
73
  return snap;