@zenfs/core 1.3.6 → 1.4.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 (88) hide show
  1. package/dist/backends/memory.d.ts +4 -4
  2. package/dist/backends/memory.js +4 -4
  3. package/dist/backends/overlay.d.ts +5 -2
  4. package/dist/backends/overlay.js +7 -10
  5. package/dist/backends/port/fs.js +1 -4
  6. package/dist/config.js +4 -8
  7. package/dist/context.d.ts +32 -0
  8. package/dist/context.js +23 -0
  9. package/dist/credentials.d.ts +5 -5
  10. package/dist/credentials.js +10 -6
  11. package/dist/emulation/async.d.ts +90 -89
  12. package/dist/emulation/async.js +76 -75
  13. package/dist/emulation/dir.d.ts +3 -1
  14. package/dist/emulation/dir.js +6 -7
  15. package/dist/emulation/index.d.ts +1 -1
  16. package/dist/emulation/index.js +1 -1
  17. package/dist/emulation/promises.d.ts +50 -48
  18. package/dist/emulation/promises.js +78 -77
  19. package/dist/emulation/shared.d.ts +35 -8
  20. package/dist/emulation/shared.js +37 -11
  21. package/dist/emulation/sync.d.ts +63 -62
  22. package/dist/emulation/sync.js +72 -73
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.js +1 -0
  25. package/dist/stats.d.ts +2 -1
  26. package/dist/stats.js +5 -4
  27. package/package.json +3 -5
  28. package/scripts/test.js +78 -17
  29. package/tests/assignment.ts +1 -1
  30. package/tests/common/context.test.ts +19 -0
  31. package/tests/{devices.test.ts → common/devices.test.ts} +3 -3
  32. package/tests/{handle.test.ts → common/handle.test.ts} +1 -1
  33. package/tests/common/mounts.test.ts +36 -0
  34. package/tests/{mutex.test.ts → common/mutex.test.ts} +3 -3
  35. package/tests/common/path.test.ts +34 -0
  36. package/tests/common.ts +4 -3
  37. package/tests/fs/dir.test.ts +11 -11
  38. package/tests/fs/directory.test.ts +17 -17
  39. package/tests/fs/errors.test.ts +29 -39
  40. package/tests/fs/watch.test.ts +2 -2
  41. package/tests/setup/context.ts +9 -0
  42. package/tests/setup/cow+fetch.ts +1 -1
  43. package/tests/setup/memory.ts +1 -1
  44. package/tests/{setup/common.ts → setup.ts} +6 -5
  45. package/src/backends/backend.ts +0 -161
  46. package/src/backends/fetch.ts +0 -180
  47. package/src/backends/file_index.ts +0 -206
  48. package/src/backends/memory.ts +0 -45
  49. package/src/backends/overlay.ts +0 -560
  50. package/src/backends/port/fs.ts +0 -329
  51. package/src/backends/port/readme.md +0 -54
  52. package/src/backends/port/rpc.ts +0 -167
  53. package/src/backends/readme.md +0 -3
  54. package/src/backends/store/fs.ts +0 -667
  55. package/src/backends/store/readme.md +0 -9
  56. package/src/backends/store/simple.ts +0 -154
  57. package/src/backends/store/store.ts +0 -189
  58. package/src/config.ts +0 -227
  59. package/src/credentials.ts +0 -49
  60. package/src/devices.ts +0 -521
  61. package/src/emulation/async.ts +0 -834
  62. package/src/emulation/cache.ts +0 -86
  63. package/src/emulation/config.ts +0 -21
  64. package/src/emulation/constants.ts +0 -182
  65. package/src/emulation/dir.ts +0 -138
  66. package/src/emulation/index.ts +0 -8
  67. package/src/emulation/path.ts +0 -440
  68. package/src/emulation/promises.ts +0 -1140
  69. package/src/emulation/shared.ts +0 -172
  70. package/src/emulation/streams.ts +0 -34
  71. package/src/emulation/sync.ts +0 -863
  72. package/src/emulation/watchers.ts +0 -194
  73. package/src/error.ts +0 -307
  74. package/src/file.ts +0 -631
  75. package/src/filesystem.ts +0 -174
  76. package/src/index.ts +0 -35
  77. package/src/inode.ts +0 -128
  78. package/src/mixins/async.ts +0 -230
  79. package/src/mixins/index.ts +0 -5
  80. package/src/mixins/mutexed.ts +0 -257
  81. package/src/mixins/readonly.ts +0 -96
  82. package/src/mixins/shared.ts +0 -25
  83. package/src/mixins/sync.ts +0 -58
  84. package/src/polyfills.ts +0 -21
  85. package/src/stats.ts +0 -405
  86. package/src/utils.ts +0 -276
  87. package/tests/mounts.test.ts +0 -18
  88. package/tests/path.test.ts +0 -34
@@ -1,161 +0,0 @@
1
- import type { Entries, RequiredKeys } from 'utilium';
2
- import { ErrnoError, Errno } from '../error.js';
3
- import type { FileSystem } from '../filesystem.js';
4
- import { levenshtein } from '../utils.js';
5
-
6
- type OptionType = 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function';
7
-
8
- /**
9
- * Resolves the type of Backend.options from the options interface
10
- */
11
- export type OptionsConfig<T> = {
12
- [K in keyof T]: {
13
- /**
14
- * The basic JavaScript type(s) for this option.
15
- */
16
- type: OptionType | readonly OptionType[];
17
-
18
- /**
19
- * Description of the option. Used in error messages and documentation.
20
- * @deprecated
21
- */
22
- description?: string;
23
-
24
- /**
25
- * Whether or not the option is required (optional can be set to null or undefined). Defaults to false.
26
- */
27
- required: K extends RequiredKeys<T> ? true : false;
28
-
29
- /**
30
- * A custom validation function to check if the option is valid.
31
- * When async, resolves if valid and rejects if not.
32
- * When sync, it will throw an error if not valid.
33
- */
34
- validator?(opt: T[K]): void | Promise<void>;
35
- };
36
- };
37
-
38
- /**
39
- * Configuration options shared by backends and `Configuration`
40
- */
41
- export interface SharedConfig {
42
- /**
43
- * If set, disables the sync cache and sync operations on async file systems.
44
- */
45
- disableAsyncCache?: boolean;
46
- }
47
-
48
- /**
49
- * A backend
50
- */
51
- export interface Backend<FS extends FileSystem = FileSystem, TOptions extends object = object> {
52
- /**
53
- * Create a new instance of the backend
54
- */
55
- create(options: TOptions & Partial<SharedConfig>): FS | Promise<FS>;
56
-
57
- /**
58
- * A name to identify the backend.
59
- */
60
- name: string;
61
-
62
- /**
63
- * Describes all of the options available for this backend.
64
- */
65
- options: OptionsConfig<TOptions>;
66
-
67
- /**
68
- * Whether the backend is available in the current environment.
69
- * It supports checking synchronously and asynchronously
70
- *
71
- * Returns 'true' if this backend is available in the current
72
- * environment. For example, a backend using a browser API will return
73
- * 'false' if the API is unavailable
74
- *
75
- */
76
- isAvailable(): boolean | Promise<boolean>;
77
- }
78
-
79
- /**
80
- * Gets the options type of a backend
81
- * @internal
82
- */
83
- export type OptionsOf<T extends Backend> = T extends Backend<FileSystem, infer TOptions> ? TOptions : never;
84
-
85
- /**
86
- * Gets the FileSystem type for a backend
87
- * @internal
88
- */
89
- export type FilesystemOf<T extends Backend> = T extends Backend<infer FS> ? FS : never;
90
-
91
- /** @internal */
92
- export function isBackend(arg: unknown): arg is Backend {
93
- return arg != null && typeof arg == 'object' && 'isAvailable' in arg && typeof arg.isAvailable == 'function' && 'create' in arg && typeof arg.create == 'function';
94
- }
95
-
96
- /**
97
- * Checks that `options` object is valid for the file system options.
98
- * @internal
99
- */
100
- export async function checkOptions<T extends Backend>(backend: T, options: Record<string, unknown>): Promise<void> {
101
- if (typeof options != 'object' || options === null) {
102
- throw new ErrnoError(Errno.EINVAL, 'Invalid options');
103
- }
104
-
105
- // Check for required options.
106
- for (const [optName, opt] of Object.entries(backend.options) as Entries<OptionsConfig<Record<string, any>>>) {
107
- const providedValue = options?.[optName];
108
-
109
- if (providedValue === undefined || providedValue === null) {
110
- if (!opt.required) {
111
- continue;
112
- }
113
- /* Required option not provided.
114
- if any incorrect options provided, which ones are close to the provided one?
115
- (edit distance 5 === close)*/
116
- const incorrectOptions = Object.keys(options)
117
- .filter(o => !(o in backend.options))
118
- .map((a: string) => {
119
- return { str: a, distance: levenshtein(optName, a) };
120
- })
121
- .filter(o => o.distance < 5)
122
- .sort((a, b) => a.distance - b.distance);
123
-
124
- throw new ErrnoError(
125
- Errno.EINVAL,
126
- `${backend.name}: Required option '${optName}' not provided.${
127
- incorrectOptions.length > 0 ? ` You provided '${incorrectOptions[0].str}', did you mean '${optName}'.` : ''
128
- }`
129
- );
130
- }
131
- // Option provided, check type.
132
- const typeMatches = Array.isArray(opt.type) ? opt.type.indexOf(typeof providedValue) != -1 : typeof providedValue == opt.type;
133
- if (!typeMatches) {
134
- throw new ErrnoError(
135
- Errno.EINVAL,
136
- `${backend.name}: Value provided for option ${optName} is not the proper type. Expected ${
137
- Array.isArray(opt.type) ? `one of {${opt.type.join(', ')}}` : (opt.type as string)
138
- }, but received ${typeof providedValue}`
139
- );
140
- }
141
-
142
- if (opt.validator) {
143
- await opt.validator(providedValue);
144
- }
145
- // Otherwise: All good!
146
- }
147
- }
148
-
149
- /**
150
- * Specifies a file system backend type and its options.
151
- *
152
- * Individual options can recursively contain BackendConfiguration objects for values that require file systems.
153
- *
154
- * The configuration for each file system corresponds to that file system's option object passed to its `create()` method.
155
- */
156
- export type BackendConfiguration<T extends Backend> = OptionsOf<T> & Partial<SharedConfig> & { backend: T };
157
-
158
- /** @internal */
159
- export function isBackendConfig<T extends Backend>(arg: unknown): arg is BackendConfiguration<T> {
160
- return arg != null && typeof arg == 'object' && 'backend' in arg && isBackend(arg.backend);
161
- }
@@ -1,180 +0,0 @@
1
- import { Errno, ErrnoError } from '../error.js';
2
- import type { FileSystemMetadata } from '../filesystem.js';
3
- import type { Stats } from '../stats.js';
4
- import type { Backend } from './backend.js';
5
- import { IndexFS } from './file_index.js';
6
- import type { IndexData } from './file_index.js';
7
-
8
- /**
9
- * Asynchronously download a file as a buffer or a JSON object.
10
- * Note that the third function signature with a non-specialized type is
11
- * invalid, but TypeScript requires it when you specialize string arguments to
12
- * constants.
13
- * @hidden
14
- */
15
- async function fetchFile(path: string, type: 'buffer', init?: RequestInit): Promise<Uint8Array>;
16
- async function fetchFile<T extends object>(path: string, type: 'json', init?: RequestInit): Promise<T>;
17
- async function fetchFile<T extends object>(path: string, type: 'buffer' | 'json', init?: RequestInit): Promise<T | Uint8Array>;
18
- async function fetchFile<T extends object>(path: string, type: string, init?: RequestInit): Promise<T | Uint8Array> {
19
- const response = await fetch(path, init).catch((e: Error) => {
20
- throw new ErrnoError(Errno.EIO, e.message, path);
21
- });
22
- if (!response.ok) {
23
- throw new ErrnoError(Errno.EIO, 'fetch failed: response returned code ' + response.status, path);
24
- }
25
- switch (type) {
26
- case 'buffer': {
27
- const arrayBuffer = await response.arrayBuffer().catch((e: Error) => {
28
- throw new ErrnoError(Errno.EIO, e.message, path);
29
- });
30
- return new Uint8Array(arrayBuffer);
31
- }
32
- case 'json':
33
- return response.json().catch((e: Error) => {
34
- throw new ErrnoError(Errno.EIO, e.message, path);
35
- }) as Promise<T>;
36
- default:
37
- throw new ErrnoError(Errno.EINVAL, 'Invalid download type: ' + type);
38
- }
39
- }
40
-
41
- /**
42
- * Configuration options for FetchFS.
43
- */
44
- export interface FetchOptions {
45
- /**
46
- * Options to pass through to fetch calls
47
- */
48
- requestInit?: RequestInit;
49
-
50
- /**
51
- * URL to a file index as a JSON file or the file index object itself.
52
- * Defaults to `index.json`.
53
- */
54
- index?: string | IndexData;
55
-
56
- /** Used as the URL prefix for fetched files.
57
- * Default: Fetch files relative to the index.
58
- */
59
- baseUrl?: string;
60
- }
61
-
62
- /**
63
- * A simple filesystem backed by HTTP using the `fetch` API.
64
- *
65
- *
66
- * Index objects look like the following:
67
- *
68
- * ```json
69
- * {
70
- * "version": 1,
71
- * "entries": {
72
- * "/home": { ... },
73
- * "/home/jvilk": { ... },
74
- * "/home/james": { ... }
75
- * }
76
- * }
77
- * ```
78
- *
79
- * Each entry contains the stats associated with the file.
80
- */
81
- export class FetchFS extends IndexFS {
82
- public readonly baseUrl: string;
83
- public readonly requestInit?: RequestInit;
84
-
85
- public async ready(): Promise<void> {
86
- if (this._isInitialized) {
87
- return;
88
- }
89
- await super.ready();
90
-
91
- if (this._disableSync) {
92
- return;
93
- }
94
-
95
- /**
96
- * Iterate over all of the files and cache their contents
97
- */
98
- for (const [path, stats] of this.index.files()) {
99
- await this.getData(path, stats);
100
- }
101
- }
102
-
103
- public constructor({ index = 'index.json', baseUrl = '', requestInit }: FetchOptions) {
104
- // prefix url must end in a directory separator.
105
- if (baseUrl.at(-1) != '/') {
106
- baseUrl += '/';
107
- }
108
-
109
- super(typeof index != 'string' ? index : fetchFile<IndexData>(index, 'json', requestInit));
110
-
111
- this.baseUrl = baseUrl;
112
- this.requestInit = requestInit;
113
- }
114
-
115
- public metadata(): FileSystemMetadata {
116
- return {
117
- ...super.metadata(),
118
- name: FetchFS.name,
119
- readonly: true,
120
- };
121
- }
122
-
123
- /**
124
- * Preload the `path` into the index.
125
- */
126
- public preload(path: string, buffer: Uint8Array): void {
127
- const stats = this.index.get(path);
128
- if (!stats) {
129
- throw ErrnoError.With('ENOENT', path, 'preload');
130
- }
131
- if (!stats.isFile()) {
132
- throw ErrnoError.With('EISDIR', path, 'preload');
133
- }
134
- stats.size = buffer.length;
135
- stats.fileData = buffer;
136
- }
137
-
138
- /**
139
- * @todo Be lazier about actually requesting the data?
140
- */
141
- protected async getData(path: string, stats: Stats): Promise<Uint8Array> {
142
- if (stats.fileData) {
143
- return stats.fileData;
144
- }
145
-
146
- const data = await fetchFile(this.baseUrl + (path.startsWith('/') ? path.slice(1) : path), 'buffer', this.requestInit);
147
- stats.fileData = data;
148
- return data;
149
- }
150
-
151
- protected getDataSync(path: string, stats: Stats): Uint8Array {
152
- if (stats.fileData) {
153
- return stats.fileData;
154
- }
155
-
156
- throw new ErrnoError(Errno.ENODATA, '', path, 'getData');
157
- }
158
- }
159
-
160
- const _Fetch = {
161
- name: 'Fetch',
162
-
163
- options: {
164
- index: { type: ['string', 'object'], required: false },
165
- baseUrl: { type: 'string', required: false },
166
- requestInit: { type: 'object', required: false },
167
- },
168
-
169
- isAvailable(): boolean {
170
- return typeof globalThis.fetch == 'function';
171
- },
172
-
173
- create(options: FetchOptions) {
174
- return new FetchFS(options);
175
- },
176
- } as const satisfies Backend<FetchFS, FetchOptions>;
177
- type _Fetch = typeof _Fetch;
178
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
179
- export interface Fetch extends _Fetch {}
180
- export const Fetch: Fetch = _Fetch;
@@ -1,206 +0,0 @@
1
- /* Note: this file is named file_index.ts because Typescript has special behavior regarding index.ts which can't be disabled. */
2
-
3
- import { isJSON } from 'utilium';
4
- import { basename, dirname } from '../emulation/path.js';
5
- import { Errno, ErrnoError } from '../error.js';
6
- import { NoSyncFile, isWriteable } from '../file.js';
7
- import { FileSystem } from '../filesystem.js';
8
- import { Readonly } from '../mixins/readonly.js';
9
- import type { StatsLike } from '../stats.js';
10
- import { Stats } from '../stats.js';
11
- import { decodeUTF8, encodeUTF8 } from '../utils.js';
12
-
13
- /**
14
- * An Index in JSON form
15
- * @internal
16
- */
17
- export interface IndexData {
18
- version: 1;
19
- entries: Record<string, StatsLike<number>>;
20
- }
21
-
22
- export const version = 1;
23
-
24
- /**
25
- * An index of files
26
- * @internal
27
- */
28
- export class Index extends Map<string, Stats> {
29
- /**
30
- * Convenience method
31
- */
32
- public files(): Map<string, Stats> {
33
- const files = new Map<string, Stats>();
34
- for (const [path, stats] of this) {
35
- if (stats.isFile()) {
36
- files.set(path, stats);
37
- }
38
- }
39
- return files;
40
- }
41
-
42
- /**
43
- * Converts the index to JSON
44
- */
45
- public toJSON(): IndexData {
46
- return {
47
- version,
48
- entries: Object.fromEntries(this),
49
- };
50
- }
51
-
52
- /**
53
- * Converts the index to a string
54
- */
55
- public toString(): string {
56
- return JSON.stringify(this.toJSON());
57
- }
58
-
59
- /**
60
- * Returns the files in the directory `dir`.
61
- * This is expensive so it is only called once per directory.
62
- */
63
- protected dirEntries(dir: string): string[] {
64
- const entries = [];
65
- for (const entry of this.keys()) {
66
- if (dirname(entry) == dir) {
67
- entries.push(basename(entry));
68
- }
69
- }
70
- return entries;
71
- }
72
-
73
- /**
74
- * Loads the index from JSON data
75
- */
76
- public fromJSON(json: IndexData): void {
77
- if (json.version != version) {
78
- throw new ErrnoError(Errno.EINVAL, 'Index version mismatch');
79
- }
80
-
81
- this.clear();
82
-
83
- for (const [path, data] of Object.entries(json.entries)) {
84
- const stats = new Stats(data);
85
- if (stats.isDirectory()) {
86
- stats.fileData = encodeUTF8(JSON.stringify(this.dirEntries(path)));
87
- }
88
- this.set(path, stats);
89
- }
90
- }
91
-
92
- /**
93
- * Parses an index from a string
94
- */
95
- public static parse(data: string): Index {
96
- if (!isJSON(data)) {
97
- throw new ErrnoError(Errno.EINVAL, 'Invalid JSON');
98
- }
99
-
100
- const json = JSON.parse(data) as IndexData;
101
- const index = new Index();
102
- index.fromJSON(json);
103
- return index;
104
- }
105
- }
106
-
107
- export abstract class IndexFS extends Readonly(FileSystem) {
108
- protected index: Index = new Index();
109
-
110
- protected _isInitialized: boolean = false;
111
-
112
- public async ready(): Promise<void> {
113
- await super.ready();
114
- if (this._isInitialized) {
115
- return;
116
- }
117
- this.index.fromJSON(await this.indexData);
118
- this._isInitialized = true;
119
- }
120
-
121
- public constructor(private indexData: IndexData | Promise<IndexData>) {
122
- super();
123
- }
124
-
125
- public async reloadFiles(): Promise<void> {
126
- for (const [path, stats] of this.index.files()) {
127
- delete stats.fileData;
128
- stats.fileData = await this.getData(path, stats);
129
- }
130
- }
131
-
132
- public reloadFilesSync(): void {
133
- for (const [path, stats] of this.index.files()) {
134
- delete stats.fileData;
135
- stats.fileData = this.getDataSync(path, stats);
136
- }
137
- }
138
-
139
- public stat(path: string): Promise<Stats> {
140
- return Promise.resolve(this.statSync(path));
141
- }
142
-
143
- public statSync(path: string): Stats {
144
- if (!this.index.has(path)) {
145
- throw ErrnoError.With('ENOENT', path, 'stat');
146
- }
147
-
148
- return this.index.get(path)!;
149
- }
150
-
151
- public async openFile(path: string, flag: string): Promise<NoSyncFile<this>> {
152
- if (isWriteable(flag)) {
153
- // You can't write to files on this file system.
154
- throw new ErrnoError(Errno.EPERM, path);
155
- }
156
-
157
- // Check if the path exists, and is a file.
158
- const stats = this.index.get(path);
159
-
160
- if (!stats) {
161
- throw ErrnoError.With('ENOENT', path, 'openFile');
162
- }
163
-
164
- return new NoSyncFile(this, path, flag, stats, stats.isDirectory() ? stats.fileData : await this.getData(path, stats));
165
- }
166
-
167
- public openFileSync(path: string, flag: string): NoSyncFile<this> {
168
- if (isWriteable(flag)) {
169
- // You can't write to files on this file system.
170
- throw new ErrnoError(Errno.EPERM, path);
171
- }
172
-
173
- // Check if the path exists, and is a file.
174
- const stats = this.index.get(path);
175
-
176
- if (!stats) {
177
- throw ErrnoError.With('ENOENT', path, 'openFile');
178
- }
179
-
180
- return new NoSyncFile(this, path, flag, stats, stats.isDirectory() ? stats.fileData : this.getDataSync(path, stats));
181
- }
182
-
183
- public readdir(path: string): Promise<string[]> {
184
- return Promise.resolve(this.readdirSync(path));
185
- }
186
-
187
- public readdirSync(path: string): string[] {
188
- // Check if it exists.
189
- const stats = this.index.get(path);
190
- if (!stats) {
191
- throw ErrnoError.With('ENOENT', path, 'readdir');
192
- }
193
-
194
- const content: unknown = JSON.parse(decodeUTF8(stats.fileData));
195
- if (!Array.isArray(content)) {
196
- throw ErrnoError.With('ENODATA', path, 'readdir');
197
- }
198
- if (!content.every(item => typeof item == 'string')) {
199
- throw ErrnoError.With('ENODATA', path, 'readdir');
200
- }
201
- return content;
202
- }
203
-
204
- protected abstract getData(path: string, stats: Stats): Promise<Uint8Array>;
205
- protected abstract getDataSync(path: string, stats: Stats): Uint8Array;
206
- }
@@ -1,45 +0,0 @@
1
- import type { Backend } from './backend.js';
2
- import { StoreFS } from './store/fs.js';
3
- import { SimpleTransaction, type SimpleSyncStore } from './store/simple.js';
4
-
5
- /**
6
- * A simple in-memory store
7
- */
8
- export class InMemoryStore extends Map<bigint, Uint8Array> implements SimpleSyncStore {
9
- public constructor(public name: string = 'tmp') {
10
- super();
11
- }
12
-
13
- public async sync(): Promise<void> {}
14
-
15
- public clearSync(): void {
16
- this.clear();
17
- }
18
-
19
- public transaction(): SimpleTransaction {
20
- return new SimpleTransaction(this);
21
- }
22
- }
23
-
24
- /**
25
- * A simple in-memory file system backed by an InMemoryStore.
26
- * Files are not persisted across page loads.
27
- */
28
- const _InMemory = {
29
- name: 'InMemory',
30
- isAvailable(): boolean {
31
- return true;
32
- },
33
- options: {
34
- name: { type: 'string', required: false },
35
- },
36
- create({ name }: { name?: string }) {
37
- const fs = new StoreFS(new InMemoryStore(name));
38
- fs.checkRootSync();
39
- return fs;
40
- },
41
- } as const satisfies Backend<StoreFS<InMemoryStore>, { name?: string }>;
42
- type _InMemory = typeof _InMemory;
43
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
44
- export interface InMemory extends _InMemory {}
45
- export const InMemory: InMemory = _InMemory;