@pistonite/pure 0.28.0 → 0.29.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 (60) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +23 -4
  3. package/dist/log/index.js +57 -0
  4. package/dist/log/index.js.map +1 -0
  5. package/dist/memory/index.js +92 -0
  6. package/dist/memory/index.js.map +1 -0
  7. package/dist/result/index.js +29 -0
  8. package/dist/result/index.js.map +1 -0
  9. package/dist/sync/index.js +252 -0
  10. package/dist/sync/index.js.map +1 -0
  11. package/package.json +22 -13
  12. package/src/env.d.ts +1 -0
  13. package/src/log/index.ts +36 -11
  14. package/src/log/logger.ts +93 -115
  15. package/src/memory/cell.ts +21 -11
  16. package/src/memory/emp.ts +34 -23
  17. package/src/memory/idgen.test.ts +1 -1
  18. package/src/memory/index.ts +1 -4
  19. package/src/memory/persist.ts +9 -12
  20. package/src/result/index.ts +12 -4
  21. package/src/sync/batch.test.ts +1 -1
  22. package/src/sync/batch.ts +12 -17
  23. package/src/sync/capture.ts +2 -0
  24. package/src/sync/debounce.test.ts +1 -1
  25. package/src/sync/debounce.ts +12 -15
  26. package/src/sync/index.ts +2 -3
  27. package/src/sync/latest.test.ts +1 -1
  28. package/src/sync/latest.ts +19 -16
  29. package/src/sync/once.test.ts +1 -1
  30. package/src/sync/once.ts +13 -8
  31. package/src/sync/serial.test.ts +1 -1
  32. package/src/sync/serial.ts +14 -12
  33. package/src/sync/util.ts +2 -2
  34. package/src/fs/FsError.ts +0 -55
  35. package/src/fs/FsFile.ts +0 -67
  36. package/src/fs/FsFileImpl.ts +0 -219
  37. package/src/fs/FsFileMgr.ts +0 -29
  38. package/src/fs/FsFileStandalone.ts +0 -21
  39. package/src/fs/FsFileStandaloneImplFileAPI.ts +0 -54
  40. package/src/fs/FsFileStandaloneImplHandleAPI.ts +0 -147
  41. package/src/fs/FsFileSystem.ts +0 -71
  42. package/src/fs/FsFileSystemInternal.ts +0 -30
  43. package/src/fs/FsImplEntryAPI.ts +0 -149
  44. package/src/fs/FsImplFileAPI.ts +0 -116
  45. package/src/fs/FsImplHandleAPI.ts +0 -199
  46. package/src/fs/FsOpen.ts +0 -271
  47. package/src/fs/FsOpenFile.ts +0 -256
  48. package/src/fs/FsPath.ts +0 -137
  49. package/src/fs/FsSave.ts +0 -216
  50. package/src/fs/FsSupportStatus.ts +0 -87
  51. package/src/fs/index.ts +0 -123
  52. package/src/log/internal.ts +0 -14
  53. package/src/memory/async_erc.ts +0 -186
  54. package/src/memory/erc.test.ts +0 -258
  55. package/src/memory/erc.ts +0 -320
  56. package/src/pref/dark.ts +0 -151
  57. package/src/pref/device.ts +0 -118
  58. package/src/pref/index.ts +0 -13
  59. package/src/pref/inject_style.ts +0 -22
  60. package/src/pref/locale.ts +0 -296
@@ -1,7 +1,16 @@
1
1
  import { type AnyFn, type AwaitRet, makePromise, type PromiseHandle } from "./util.ts";
2
2
 
3
+ /** Factory for debounced function. See {@link DebounceConstructor} for usage */
4
+ export function debounce<TFn extends AnyFn>(args: DebounceConstructor<TFn>) {
5
+ const { fn, interval, disregardExecutionTime } = args;
6
+ const impl = new DebounceImpl(fn, interval, !!disregardExecutionTime);
7
+ return (...args: Parameters<TFn>) => impl.invoke(...args);
8
+ }
9
+
3
10
  /**
4
- * An async event wrapper that is guaranteed to:
11
+ * Options for `debounce` function
12
+ *
13
+ * A debounced function is an async event wrapper that is guaranteed to:
5
14
  * - Not re-fire in a minimal interval after it's initialially fired.
6
15
  * - All calls will eventually fire
7
16
  *
@@ -78,19 +87,7 @@ import { type AnyFn, type AwaitRet, makePromise, type PromiseHandle } from "./ut
78
87
  * });
79
88
  * ```
80
89
  */
81
- export function debounce<TFn extends AnyFn>({
82
- fn,
83
- interval,
84
- disregardExecutionTime,
85
- }: DebounceConstructor<TFn>) {
86
- const impl = new DebounceImpl(fn, interval, !!disregardExecutionTime);
87
- return (...args: Parameters<TFn>) => impl.invoke(...args);
88
- }
89
-
90
- /**
91
- * Options for `debounce` function
92
- */
93
- export type DebounceConstructor<TFn> = {
90
+ export interface DebounceConstructor<TFn> {
94
91
  /** Function to be debounced */
95
92
  fn: TFn;
96
93
  /**
@@ -111,7 +108,7 @@ export type DebounceConstructor<TFn> = {
111
108
  * set this to true.
112
109
  */
113
110
  disregardExecutionTime?: boolean;
114
- };
111
+ }
115
112
 
116
113
  class DebounceImpl<TFn extends AnyFn> {
117
114
  private idle: boolean;
package/src/sync/index.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  /**
2
- * # pure/sync
3
- * JS synchronization utilities
2
+ * Synchronization utilities
4
3
  *
5
4
  * @module
6
5
  */
@@ -10,7 +9,7 @@ export {
10
9
  type SerialEventCancelCallback,
11
10
  type SerialCancelToken,
12
11
  } from "./serial.ts";
13
- export { latest, type LatestConstructor, type UpdateArgsFn } from "./latest.ts";
12
+ export { latest, type LatestConstructor, type LatestUpdateArgsFn } from "./latest.ts";
14
13
  export { debounce, type DebounceConstructor } from "./debounce.ts";
15
14
  export { batch, type BatchConstructor } from "./batch.ts";
16
15
  export { once, type OnceConstructor } from "./once.ts";
@@ -1,4 +1,4 @@
1
- import { expect, test, describe } from "vitest";
1
+ import { expect, test, describe } from "mono-dev/vitest";
2
2
 
3
3
  import { latest } from "./latest.ts";
4
4
 
@@ -1,7 +1,18 @@
1
1
  import { type AnyFn, type AwaitRet, makePromise, type PromiseHandle } from "./util.ts";
2
2
 
3
3
  /**
4
- * An async event wrapper that always resolve to the result of the latest
4
+ * Factory for `latest`. See {@link LatestConstructor} for usage.
5
+ */
6
+ export function latest<TFn extends AnyFn>(args: LatestConstructor<TFn>) {
7
+ const { fn, areArgsEqual, updateArgs } = args;
8
+ const impl = new LatestImpl(fn, areArgsEqual, updateArgs);
9
+ return (...args: Parameters<TFn>) => impl.invoke(...args);
10
+ }
11
+
12
+ /**
13
+ * Args for constructing `latest`
14
+ *
15
+ * `latest` is an async event wrapper that always resolve to the result of the latest
5
16
  * call
6
17
  *
7
18
  * ## Example
@@ -31,16 +42,7 @@ import { type AnyFn, type AwaitRet, makePromise, type PromiseHandle } from "./ut
31
42
  * See the constructor options for more advanced usage, for example,
32
43
  * control how arguments are updated when new calls are made.
33
44
  */
34
- export function latest<TFn extends AnyFn>({
35
- fn,
36
- areArgsEqual,
37
- updateArgs,
38
- }: LatestConstructor<TFn>) {
39
- const impl = new LatestImpl(fn, areArgsEqual, updateArgs);
40
- return (...args: Parameters<TFn>) => impl.invoke(...args);
41
- }
42
-
43
- export type LatestConstructor<TFn extends AnyFn> = {
45
+ export interface LatestConstructor<TFn extends AnyFn> {
44
46
  /** Function to be wrapped */
45
47
  fn: TFn;
46
48
 
@@ -72,9 +74,10 @@ export type LatestConstructor<TFn extends AnyFn> = {
72
74
  * to be executed next.
73
75
  *
74
76
  */
75
- updateArgs?: UpdateArgsFn<TFn>;
76
- };
77
- export type UpdateArgsFn<TFn extends AnyFn> = (
77
+ updateArgs?: LatestUpdateArgsFn<TFn>;
78
+ }
79
+ /** See {@link LatestConstructor} */
80
+ export type LatestUpdateArgsFn<TFn extends AnyFn> = (
78
81
  current: Parameters<TFn>,
79
82
  middle: Parameters<TFn>[],
80
83
  latest: Parameters<TFn>,
@@ -91,12 +94,12 @@ export class LatestImpl<TFn extends AnyFn> {
91
94
  private middleArgs: Parameters<TFn>[];
92
95
 
93
96
  private areArgsEqual: (a: Parameters<TFn>, b: Parameters<TFn>) => boolean;
94
- private updateArgs: UpdateArgsFn<TFn>;
97
+ private updateArgs: LatestUpdateArgsFn<TFn>;
95
98
 
96
99
  constructor(
97
100
  private fn: TFn,
98
101
  areArgsEqual?: (a: Parameters<TFn>, b: Parameters<TFn>) => boolean,
99
- updateArgs?: UpdateArgsFn<TFn>,
102
+ updateArgs?: LatestUpdateArgsFn<TFn>,
100
103
  ) {
101
104
  this.middleArgs = [];
102
105
  this.areArgsEqual = areArgsEqual || (() => false);
@@ -1,4 +1,4 @@
1
- import { expect, test } from "vitest";
1
+ import { expect, test } from "mono-dev/vitest";
2
2
 
3
3
  import { once } from "./once.ts";
4
4
 
package/src/sync/once.ts CHANGED
@@ -1,7 +1,17 @@
1
1
  import { type AnyFn, type AwaitRet, makePromise } from "./util.ts";
2
2
 
3
3
  /**
4
- * An async event wrapper that ensures an async initialization is only ran once.
4
+ * Factory function for `once`. See {@link OnceConstructor} for usage
5
+ */
6
+ export function once<TFn extends AnyFn>(args: OnceConstructor<TFn>) {
7
+ const impl = new OnceImpl(args.fn);
8
+ return (...args: Parameters<TFn>) => impl.invoke(...args);
9
+ }
10
+
11
+ /**
12
+ * Args for constructing a `once`
13
+ *
14
+ * `once` is an async event wrapper that ensures an async initialization is only ran once.
5
15
  * Any subsequent calls after the first call will return a promise that resolves/rejects
6
16
  * with the result of the first call.
7
17
  *
@@ -66,15 +76,10 @@ import { type AnyFn, type AwaitRet, makePromise } from "./util.ts";
66
76
  * This is not an issue if the resource doesn't leak other resources,
67
77
  * since it will eventually be GC'd.
68
78
  */
69
- export function once<TFn extends AnyFn>({ fn }: OnceConstructor<TFn>) {
70
- const impl = new OnceImpl(fn);
71
- return (...args: Parameters<TFn>) => impl.invoke(...args);
72
- }
73
-
74
- export type OnceConstructor<TFn> = {
79
+ export interface OnceConstructor<TFn> {
75
80
  /** Function to be called only once */
76
81
  fn: TFn;
77
- };
82
+ }
78
83
 
79
84
  export class OnceImpl<TFn extends AnyFn> {
80
85
  private promise: Promise<AwaitRet<TFn>> | undefined;
@@ -1,4 +1,4 @@
1
- import { test, expect, expectTypeOf, vi } from "vitest";
1
+ import { test, expect, expectTypeOf, vi } from "mono-dev/vitest";
2
2
 
3
3
  import { serial, type SerialCancelToken } from "./serial.ts";
4
4
  import type { Result } from "../result/index.ts";
@@ -2,7 +2,18 @@ import type { Result } from "../result/index.ts";
2
2
  import type { AnyFn } from "./util.ts";
3
3
 
4
4
  /**
5
- * An async event wrapper that is cancelled when a new one starts.
5
+ * Factory function for `serial`. See {@link SerialConstructor} for usage
6
+ */
7
+ export const serial = <TFn extends AnyFn>(args: SerialConstructor<TFn>) => {
8
+ const { fn, onCancel } = args;
9
+ const impl = new SerialImpl(fn, onCancel);
10
+ return (...args: Parameters<TFn>) => impl.invoke(...args);
11
+ };
12
+
13
+ /**
14
+ * Options for `serial` function
15
+ *
16
+ * `serial` is an async event wrapper that is cancelled when a new one starts.
6
17
  * When a new event is started, the previous caller will receive a
7
18
  * cancellation error, instead of being hung up indefinitely.
8
19
  *
@@ -132,16 +143,7 @@ import type { AnyFn } from "./util.ts";
132
143
  *
133
144
  * If the underlying function throws, the exception will be re-thrown to the caller.
134
145
  */
135
-
136
- export function serial<TFn extends AnyFn>({ fn, onCancel }: SerialConstructor<TFn>) {
137
- const impl = new SerialImpl(fn, onCancel);
138
- return (...args: Parameters<TFn>) => impl.invoke(...args);
139
- }
140
-
141
- /**
142
- * Options for `serial` function
143
- */
144
- export type SerialConstructor<TFn> = {
146
+ export interface SerialConstructor<TFn> {
145
147
  /**
146
148
  * Function creator that returns the async function to be wrapped
147
149
  */
@@ -152,7 +154,7 @@ export type SerialConstructor<TFn> = {
152
154
  * This is guaranteed to be only called at most once per execution
153
155
  */
154
156
  onCancel?: SerialEventCancelCallback;
155
- };
157
+ }
156
158
 
157
159
  class SerialImpl<TFn extends AnyFn> {
158
160
  private serial: SerialId;
package/src/sync/util.ts CHANGED
@@ -18,11 +18,11 @@ export const makePromise = <T>(): PromiseHandle<T> => {
18
18
  * A handle of the promise that breaks down the promise object
19
19
  * and its resolve and reject functions
20
20
  */
21
- export type PromiseHandle<T> = {
21
+ export interface PromiseHandle<T> {
22
22
  promise: Promise<T>;
23
23
  resolve: (value: T | PromiseLike<T>) => void;
24
24
  reject: (reason?: unknown) => void;
25
- };
25
+ }
26
26
 
27
27
  /** Shorthand for Awaited<ReturnType<T>> */
28
28
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
package/src/fs/FsError.ts DELETED
@@ -1,55 +0,0 @@
1
- import type { Result, Void } from "../result/index.ts";
2
-
3
- /** Result type for file system operations */
4
- export const FsErr = {
5
- /** Generic error */
6
- Fail: 1,
7
- /** The operation does not apply to the root directory */
8
- IsRoot: 2,
9
- /** Invalid encoding */
10
- InvalidEncoding: 3,
11
- /** Not supported */
12
- NotSupported: 4,
13
- /** The operation does not apply to a file */
14
- IsFile: 5,
15
- /** The file was not modified since the last check */
16
- NotModified: 6,
17
- /** Permission error */
18
- PermissionDenied: 7,
19
- /** User abort */
20
- UserAbort: 8,
21
- /** Not found */
22
- NotFound: 9,
23
- /** Trying to do stuff to a closed file */
24
- IsClosed: 10,
25
- /** If the path is invalid, for example trying to get the parent of root */
26
- InvalidPath: 11,
27
- /** Trying to operate on a file that has been closed */
28
- Closed: 12,
29
- /** The operation does not apply to a directory */
30
- IsDirectory: 5,
31
- } as const;
32
-
33
- /** Result type for file system operations */
34
- export type FsErr = (typeof FsErr)[keyof typeof FsErr];
35
-
36
- /** Fs error type with a code and message */
37
- export type FsError = {
38
- readonly code: FsErr;
39
- readonly message: string;
40
- };
41
-
42
- /** Helper to create a FsError */
43
- export function fsErr(code: FsErr, message: string): FsError {
44
- return { code, message };
45
- }
46
-
47
- /** Helper to create a FsError with the code Fail */
48
- export function fsFail(message: string): FsError {
49
- return fsErr(FsErr.Fail, message);
50
- }
51
-
52
- /** Helper result type for FsError */
53
- export type FsResult<T> = Result<T, FsError>;
54
- /** Helper result type for FsError with no value */
55
- export type FsVoid = Void<FsError>;
package/src/fs/FsFile.ts DELETED
@@ -1,67 +0,0 @@
1
- import type { FsResult, FsVoid } from "./FsError.ts";
2
-
3
- /** Interface for operating on a file in the loaded file system */
4
- export interface FsFile {
5
- /** Path of the file relative to the root of the file system (the uploaded directory) */
6
- readonly path: string;
7
-
8
- /** Returns if the content of the file in memory is newer than the file on disk */
9
- isDirty(): boolean;
10
-
11
- /** Get the last modified time. May load it from file system if needed */
12
- getLastModified(): Promise<FsResult<number>>;
13
-
14
- /**
15
- * Get the text content of the file
16
- *
17
- * If the file is not loaded, it will load it.
18
- *
19
- * If the file is not a text file, it will return InvalidEncoding
20
- */
21
- getText(): Promise<FsResult<string>>;
22
-
23
- /** Get the content of the file */
24
- getBytes(): Promise<FsResult<Uint8Array>>;
25
-
26
- /**
27
- * Set the content in memory. Does not save to disk.
28
- * Does nothing if file is closed
29
- */
30
- setText(content: string): void;
31
-
32
- /**
33
- * Set the content in memory. Does not save to disk.
34
- * Does nothing if file is closed
35
- */
36
- setBytes(content: Uint8Array<ArrayBuffer>): void;
37
-
38
- /**
39
- * Load the file's content if it's not newer than fs
40
- *
41
- * Returns Ok if the file is newer than fs
42
- */
43
- loadIfNotDirty(): Promise<FsVoid>;
44
-
45
- /**
46
- * Load the file's content from FS.
47
- *
48
- * Overwrites any unsaved changes in memory only if the file was modified
49
- * at a later time than the last in memory modification.
50
- *
51
- * If it fails, the file's content in memory will not be changed
52
- */
53
- load(): Promise<FsVoid>;
54
-
55
- /**
56
- * Save the file's content to FS if it is dirty.
57
- *
58
- * If not dirty, returns Ok
59
- */
60
- writeIfNewer(): Promise<FsVoid>;
61
-
62
- /**
63
- * Close the file. In memory content will be lost.
64
- * Further operations on the file will fail
65
- */
66
- close(): void;
67
- }
@@ -1,219 +0,0 @@
1
- import { tryAsync, errstr } from "../result/index.ts";
2
-
3
- import type { FsFile } from "./FsFile.ts";
4
- import type { FsFileSystemInternal } from "./FsFileSystemInternal.ts";
5
- import { FsErr, type FsResult, type FsVoid, fsErr, fsFail } from "./FsError.ts";
6
-
7
- /** Allocate a new file object */
8
- export function fsFile(fs: FsFileSystemInternal, path: string): FsFile {
9
- return new FsFileImpl(fs, path);
10
- }
11
-
12
- function errclosed() {
13
- return { err: fsErr(FsErr.Closed, "File is closed") } as const;
14
- }
15
-
16
- class FsFileImpl implements FsFile {
17
- /** The path of the file */
18
- public path: string;
19
-
20
- private closed: boolean;
21
-
22
- /** Reference to the file system so we can read/write */
23
- private fs: FsFileSystemInternal;
24
- /** If the file is text */
25
- private isText: boolean;
26
- /** Bytes of the file */
27
- private buffer: Uint8Array<ArrayBuffer> | undefined;
28
- /** If the content in the buffer is different from the content on FS */
29
- private isBufferDirty: boolean;
30
- /** The content string of the file */
31
- private content: string | undefined;
32
- /** If the content string is newer than the bytes */
33
- private isContentNewer: boolean;
34
- /** The last modified time of the file */
35
- private lastModified: number | undefined;
36
-
37
- constructor(fs: FsFileSystemInternal, path: string) {
38
- this.closed = false;
39
- this.fs = fs;
40
- this.path = path;
41
- this.isText = false;
42
- this.buffer = undefined;
43
- this.isBufferDirty = false;
44
- this.content = undefined;
45
- this.isContentNewer = false;
46
- this.lastModified = undefined;
47
- }
48
-
49
- public close(): void {
50
- this.closed = true;
51
- this.fs.closeFile(this.path);
52
- }
53
-
54
- public isDirty(): boolean {
55
- return this.isBufferDirty || this.isContentNewer;
56
- }
57
-
58
- public async getLastModified(): Promise<FsResult<number>> {
59
- if (this.closed) {
60
- return errclosed();
61
- }
62
- if (this.lastModified === undefined) {
63
- const r = await this.loadIfNotDirty();
64
- if (r.err) {
65
- return r;
66
- }
67
- }
68
- return { val: this.lastModified ?? 0 };
69
- }
70
-
71
- public async getText(): Promise<FsResult<string>> {
72
- if (this.closed) {
73
- return errclosed();
74
- }
75
- if (this.buffer === undefined) {
76
- const r = await this.load();
77
- if (r.err) {
78
- return r;
79
- }
80
- }
81
- if (!this.isText) {
82
- const err = fsFail("File is not valid UTF-8");
83
- return { err };
84
- }
85
- return { val: this.content ?? "" };
86
- }
87
-
88
- public async getBytes(): Promise<FsResult<Uint8Array>> {
89
- if (this.closed) {
90
- return errclosed();
91
- }
92
- this.updateBuffer();
93
- if (this.buffer === undefined) {
94
- const r = await this.load();
95
- if (r.err) {
96
- return r;
97
- }
98
- }
99
- if (this.buffer === undefined) {
100
- const err = fsFail("Read was successful, but content was undefined");
101
- return { err };
102
- }
103
- return { val: this.buffer };
104
- }
105
-
106
- public setText(content: string): void {
107
- if (this.closed) {
108
- return;
109
- }
110
- if (this.content === content) {
111
- return;
112
- }
113
- this.content = content;
114
- this.isContentNewer = true;
115
- this.lastModified = new Date().getTime();
116
- }
117
-
118
- public setBytes(content: Uint8Array<ArrayBuffer>): void {
119
- if (this.closed) {
120
- return;
121
- }
122
- this.buffer = content;
123
- this.isBufferDirty = true;
124
- this.decodeBuffer();
125
- this.isContentNewer = true;
126
- this.lastModified = new Date().getTime();
127
- }
128
-
129
- public async loadIfNotDirty(): Promise<FsVoid> {
130
- if (this.closed) {
131
- return errclosed();
132
- }
133
- if (this.isDirty()) {
134
- return {};
135
- }
136
- return await this.load();
137
- }
138
-
139
- public async load(): Promise<FsVoid> {
140
- if (this.closed) {
141
- return errclosed();
142
- }
143
- const { val: file, err } = await this.fs.read(this.path);
144
- if (err) {
145
- return { err };
146
- }
147
-
148
- // check if the file has been modified since last loaded
149
- if (this.lastModified !== undefined) {
150
- if (file.lastModified <= this.lastModified) {
151
- return {};
152
- }
153
- }
154
- this.lastModified = file.lastModified;
155
- // load the buffer
156
- const buffer = await tryAsync(async () => new Uint8Array(await file.arrayBuffer()));
157
- if ("err" in buffer) {
158
- const err = fsFail(errstr(buffer.err));
159
- return { err };
160
- }
161
- this.buffer = buffer.val;
162
- this.isBufferDirty = false;
163
- // Try decoding the buffer as text
164
- this.decodeBuffer();
165
- this.isContentNewer = false;
166
- return {};
167
- }
168
-
169
- public async writeIfNewer(): Promise<FsVoid> {
170
- if (this.closed) {
171
- return errclosed();
172
- }
173
- if (!this.isDirty()) {
174
- return {};
175
- }
176
- return await this.write();
177
- }
178
-
179
- /**
180
- * Write the content without checking if it's dirty. Overwrites the file currently on FS
181
- *
182
- * This is private - outside code should only use writeIfDirty
183
- */
184
- private async write(): Promise<FsVoid> {
185
- this.updateBuffer();
186
- const buffer = this.buffer;
187
- if (this.content === undefined || buffer === undefined) {
188
- // file was never read or modified
189
- return {};
190
- }
191
- const result = await this.fs.write(this.path, buffer);
192
- if (result.err) {
193
- return result;
194
- }
195
- this.isBufferDirty = false;
196
- return {};
197
- }
198
-
199
- private decodeBuffer() {
200
- try {
201
- this.content = new TextDecoder("utf-8", { fatal: true }).decode(this.buffer);
202
- this.isText = true;
203
- } catch {
204
- this.content = undefined;
205
- this.isText = false;
206
- }
207
- }
208
-
209
- /** Encode the content to buffer if it is newer */
210
- private updateBuffer() {
211
- if (!this.isContentNewer || this.content === undefined) {
212
- return;
213
- }
214
- const encoder = new TextEncoder();
215
- this.buffer = encoder.encode(this.content);
216
- this.isBufferDirty = true;
217
- this.isContentNewer = false;
218
- }
219
- }
@@ -1,29 +0,0 @@
1
- import type { FsFile } from "./FsFile.ts";
2
- import type { FsFileSystemInternal } from "./FsFileSystemInternal.ts";
3
- import { fsFile } from "./FsFileImpl.ts";
4
-
5
- /** Internal class to track opened files */
6
- export class FsFileMgr {
7
- private opened: Map<string, FsFile>;
8
-
9
- public constructor() {
10
- this.opened = new Map();
11
- }
12
-
13
- public get(fs: FsFileSystemInternal, path: string): FsFile {
14
- let file = this.opened.get(path);
15
- if (!file) {
16
- file = fsFile(fs, path);
17
- this.opened.set(path, file);
18
- }
19
- return file;
20
- }
21
-
22
- public close(path: string): void {
23
- this.opened.delete(path);
24
- }
25
-
26
- public getOpenedPaths(): string[] {
27
- return Array.from(this.opened.keys());
28
- }
29
- }
@@ -1,21 +0,0 @@
1
- import type { FsResult, FsVoid } from "./FsError.ts";
2
-
3
- /**
4
- * Interface for operating on a file opened standalone (without opening a file system
5
- */
6
- export interface FsFileStandalone {
7
- /** The name of the file */
8
- readonly name: string;
9
- /** If the file is writable. May prompt user for permission */
10
- isWritable(): Promise<boolean>;
11
- /** Get the size of the file */
12
- getSize(): Promise<FsResult<number>>;
13
- /** Get the content of the file as a byte array */
14
- getBytes(): Promise<FsResult<Uint8Array>>;
15
- /** Get the last modified time of the file */
16
- getLastModified(): Promise<FsResult<number>>;
17
- /** Get the text content of the file*/
18
- getText(): Promise<FsResult<string>>;
19
- /** Write content to the file if the implementation supports writing, and permission is granted*/
20
- write(content: Uint8Array | string): Promise<FsVoid>;
21
- }