@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,54 +0,0 @@
1
- import { ilog } from "../log/internal.ts";
2
- import { errstr } from "../result";
3
-
4
- import { fsErr, FsErr, fsFail, type FsVoid, type FsResult } from "./FsError.ts";
5
- import type { FsFileStandalone } from "./FsFileStandalone.ts";
6
-
7
- export class FsFileStandaloneImplFileAPI implements FsFileStandalone {
8
- public name: string;
9
- private size: number;
10
- private lastModified: number;
11
- private file: File;
12
-
13
- constructor(file: File) {
14
- this.name = file.name;
15
- this.size = file.size;
16
- this.lastModified = file.lastModified;
17
- this.file = file;
18
- }
19
-
20
- public async isWritable(): Promise<boolean> {
21
- return false;
22
- }
23
-
24
- public async getSize(): Promise<FsResult<number>> {
25
- return { val: this.size };
26
- }
27
-
28
- public async getBytes(): Promise<FsResult<Uint8Array>> {
29
- try {
30
- const data = await this.file.arrayBuffer();
31
- return { val: new Uint8Array(data) };
32
- } catch (e) {
33
- ilog.error(e);
34
- return { err: fsFail(errstr(e)) };
35
- }
36
- }
37
- public async getLastModified(): Promise<FsResult<number>> {
38
- return { val: this.lastModified };
39
- }
40
- public async getText(): Promise<FsResult<string>> {
41
- try {
42
- const data = await this.file.text();
43
- return { val: data };
44
- } catch (e) {
45
- ilog.error(e);
46
- return { err: fsFail(errstr(e)) };
47
- }
48
- }
49
- public async write(): Promise<FsVoid> {
50
- return {
51
- err: fsErr(FsErr.NotSupported, "Write not supported in File API"),
52
- };
53
- }
54
- }
@@ -1,147 +0,0 @@
1
- import { ilog } from "../log/internal.ts";
2
- import { errstr } from "../result";
3
-
4
- import { fsErr, FsErr, fsFail, type FsVoid, type FsResult } from "./FsError.ts";
5
- import type { FsFileStandalone } from "./FsFileStandalone.ts";
6
-
7
- export class FsFileStandaloneImplHandleAPI implements FsFileStandalone {
8
- name: string;
9
- private handle: FileSystemFileHandle;
10
- constructor(handle: FileSystemFileHandle) {
11
- this.name = handle.name;
12
- this.handle = handle;
13
- }
14
-
15
- public async isWritable(): Promise<boolean> {
16
- if (
17
- !("queryPermission" in this.handle) ||
18
- !(typeof this.handle.queryPermission === "function")
19
- ) {
20
- return false;
21
- }
22
- try {
23
- const permission = await this.handle.queryPermission({
24
- mode: "readwrite",
25
- });
26
- if (permission === "granted") {
27
- return true;
28
- }
29
- if (permission === "denied") {
30
- return false;
31
- }
32
- if (
33
- !("requestPermission" in this.handle) ||
34
- !(typeof this.handle.requestPermission === "function")
35
- ) {
36
- return false;
37
- }
38
- const requestedPermission = await this.handle.requestPermission({
39
- mode: "readwrite",
40
- });
41
- return requestedPermission === "granted";
42
- } catch (e) {
43
- ilog.error(e);
44
- return false;
45
- }
46
- }
47
-
48
- private async getFile(): Promise<FsResult<File>> {
49
- try {
50
- return { val: await this.handle.getFile() };
51
- } catch (e) {
52
- if (e && typeof e === "object" && "name" in e) {
53
- if (e.name === "NotAllowedError") {
54
- return {
55
- err: fsErr(FsErr.PermissionDenied, "Permission denied"),
56
- };
57
- }
58
- if (e.name === "NotFoundError") {
59
- return { err: fsErr(FsErr.NotFound, "File not found") };
60
- }
61
- }
62
- ilog.error(e);
63
- return { err: fsFail(errstr(e)) };
64
- }
65
- }
66
-
67
- public async getSize(): Promise<FsResult<number>> {
68
- const file = await this.getFile();
69
- if (file.err) {
70
- return file;
71
- }
72
- return { val: file.val.size };
73
- }
74
- public async getBytes(): Promise<FsResult<Uint8Array>> {
75
- const file = await this.getFile();
76
- if (file.err) {
77
- return file;
78
- }
79
- try {
80
- const data = await file.val.arrayBuffer();
81
- return { val: new Uint8Array(data) };
82
- } catch (e) {
83
- ilog.error(e);
84
- return { err: fsFail(errstr(e)) };
85
- }
86
- }
87
- public async getLastModified(): Promise<FsResult<number>> {
88
- const file = await this.getFile();
89
- if (file.err) {
90
- return file;
91
- }
92
- return { val: file.val.lastModified };
93
- }
94
- public async getText(): Promise<FsResult<string>> {
95
- const file = await this.getFile();
96
- if (file.err) {
97
- return file;
98
- }
99
- try {
100
- const data = await file.val.text();
101
- return { val: data };
102
- } catch (e) {
103
- ilog.error(e);
104
- return { err: fsFail(errstr(e)) };
105
- }
106
- }
107
- public async write(content: Uint8Array<ArrayBuffer> | string): Promise<FsVoid> {
108
- const writable = await this.isWritable();
109
- if (!writable) {
110
- return {
111
- err: fsErr(FsErr.NotSupported, "Permission was not granted or API not supported"),
112
- };
113
- }
114
- try {
115
- const stream = await this.handle.createWritable();
116
- await stream.write(content);
117
- await stream.close();
118
- return {};
119
- } catch (e) {
120
- if (e && typeof e === "object" && "name" in e) {
121
- if (e.name === "NotAllowedError") {
122
- return {
123
- err: fsErr(FsErr.PermissionDenied, "Permission denied"),
124
- };
125
- }
126
- if (e.name === "NotFoundError") {
127
- return { err: fsErr(FsErr.NotFound, "File not found") };
128
- }
129
- if (e.name === "NoMidificationAllowedError") {
130
- return {
131
- err: fsErr(FsErr.PermissionDenied, "Failed to acquire write lock"),
132
- };
133
- }
134
- if (e.name === "AbortError") {
135
- return { err: fsErr(FsErr.UserAbort, "User abort") };
136
- }
137
- if (e.name === "QuotaExceededError") {
138
- return {
139
- err: fsErr(FsErr.PermissionDenied, "Quota exceeded"),
140
- };
141
- }
142
- }
143
- ilog.error(e);
144
- return { err: fsFail(errstr(e)) };
145
- }
146
- }
147
- }
@@ -1,71 +0,0 @@
1
- import type { FsFile } from "./FsFile.ts";
2
- import type { FsResult } from "./FsError.ts";
3
-
4
- /**
5
- * File system before it is initialized
6
- *
7
- * This is an internal type used inside fsOpen functions
8
- */
9
- export interface FsFileSystemUninit {
10
- /// Initialize the file system
11
- init(): Promise<FsResult<FsFileSystem>>;
12
- }
13
-
14
- /** Initialized file system */
15
- export interface FsFileSystem {
16
- /**
17
- * Get the root path of the file system for display
18
- *
19
- * The returned string has no significance in the file system itself.
20
- * It should only be used as an indicator to the user.
21
- */
22
- readonly root: string;
23
-
24
- /**
25
- * Capabilities of this file system implementation
26
- * See README.md for more information
27
- */
28
- readonly capabilities: FsCapabilities;
29
-
30
- /**
31
- * List files in a directory
32
- *
33
- * The input path should be relative to the root (of the uploaded directory).
34
- *
35
- * Returns a list of file names in the directory (not full paths).
36
- * Directory names end with a slash.
37
- *
38
- * Returns Fail if the underlying file system operation fails.
39
- */
40
- listDir: (path: string) => Promise<FsResult<string[]>>;
41
-
42
- /**
43
- * Get a file object for operations
44
- *
45
- * The returned object can store temporary state for the file, such
46
- * as newer content. Calling openFile with the same path will
47
- * return the same object.
48
- *
49
- * Note that opening a file doesn't actually block the file
50
- * from being modified by programs other than the browser.
51
- *
52
- * You can make the FsFileSystem forget about the file by
53
- * calling `close` on the file object.
54
- */
55
- getFile: (path: string) => FsFile;
56
-
57
- /** Get all paths that `getFile` has been called with but not `close`d */
58
- getOpenedPaths: () => string[];
59
- }
60
-
61
- /** Capabilities of the file system implementation */
62
- export type FsCapabilities = {
63
- /** Can the browser directly write to the file system */
64
- write: boolean;
65
- /**
66
- * Can the browser detect live updates:
67
- * - Change of modified time
68
- * - Change of directory structure (new, renamed, deleted files)
69
- */
70
- live: boolean;
71
- };
@@ -1,30 +0,0 @@
1
- import type { FsResult, FsVoid } from "./FsError.ts";
2
-
3
- /** Internal APIs for FsFileSystem */
4
- export interface FsFileSystemInternal {
5
- /**
6
- * Read the file as a File object
7
- *
8
- * Returns Fail if the underlying file system operation fails.
9
- */
10
- read: (path: string) => Promise<FsResult<File>>;
11
-
12
- /**
13
- * Write content to a file on disk
14
- *
15
- * Writes the content to the path specified.
16
- * If the content is a string, UTF-8 encoding is used.
17
- *
18
- * Will overwrite existing file.
19
- *
20
- * Returns Fail if the underlying file system operation fails.
21
- * Returns NotSupported if the browser does not support this
22
- * Returns PermissionDenied if the operation is supported, but permission is not given
23
- */
24
- write: (path: string, content: Uint8Array<ArrayBuffer>) => Promise<FsVoid>;
25
-
26
- /**
27
- * Forget about a file
28
- */
29
- closeFile: (path: string) => void;
30
- }
@@ -1,149 +0,0 @@
1
- import { type Ok, tryAsync, errstr } from "../result/index.ts";
2
-
3
- import { FsErr, type FsResult, type FsVoid, fsErr, fsFail } from "./FsError.ts";
4
- import type { FsFileSystem, FsFileSystemUninit, FsCapabilities } from "./FsFileSystem.ts";
5
- import type { FsFile } from "./FsFile.ts";
6
- import { fsIsRoot, fsNormalize } from "./FsPath.ts";
7
- import { FsFileMgr } from "./FsFileMgr.ts";
8
- import type { FsFileSystemInternal } from "./FsFileSystemInternal.ts";
9
-
10
- /** FsFileSystem implementation that uses FileEntry API */
11
- export class FsImplEntryAPI implements FsFileSystemUninit, FsFileSystem, FsFileSystemInternal {
12
- public root: string;
13
- public capabilities: FsCapabilities;
14
-
15
- private rootEntry: FileSystemDirectoryEntry;
16
-
17
- private mgr: FsFileMgr;
18
-
19
- constructor(root: string, rootEntry: FileSystemDirectoryEntry) {
20
- this.root = root;
21
- this.rootEntry = rootEntry;
22
- this.capabilities = { write: false, live: true };
23
- this.mgr = new FsFileMgr();
24
- }
25
-
26
- public init(): Promise<FsResult<FsFileSystem>> {
27
- // no init needed
28
- return Promise.resolve({ val: this });
29
- }
30
-
31
- public async listDir(path: string): Promise<FsResult<string[]>> {
32
- const normalized = fsNormalize(path);
33
- if (normalized.err) {
34
- return normalized;
35
- }
36
- path = normalized.val;
37
-
38
- const entry = await this.resolveDir(path);
39
- if (entry.err) {
40
- return entry;
41
- }
42
-
43
- const entries = await tryAsync(
44
- () =>
45
- new Promise<FileSystemEntry[]>((resolve, reject) => {
46
- entry.val.createReader().readEntries(resolve, reject);
47
- }),
48
- );
49
- if ("err" in entries) {
50
- const err = fsFail("Failed to list directory `" + path + "`: " + errstr(entries.err));
51
- return { err };
52
- }
53
-
54
- const names = entries.val.map(({ isDirectory, name }) => {
55
- if (isDirectory) {
56
- return name + "/";
57
- }
58
- return name;
59
- });
60
-
61
- return { val: names };
62
- }
63
-
64
- public async read(path: string): Promise<FsResult<File>> {
65
- const normalized = fsNormalize(path);
66
- if (normalized.err) {
67
- return normalized;
68
- }
69
- path = normalized.val;
70
-
71
- const entry = await this.resolveFile(path);
72
- if (entry.err) {
73
- return entry;
74
- }
75
-
76
- const file = await tryAsync(
77
- () =>
78
- new Promise<File>((resolve, reject) => {
79
- entry.val.file(resolve, reject);
80
- }),
81
- );
82
- if ("err" in file) {
83
- const err = fsFail("Failed to read file `" + path + "`: " + errstr(file.err));
84
- return { err };
85
- }
86
-
87
- return file;
88
- }
89
-
90
- public write(): Promise<FsVoid> {
91
- const err = fsErr(FsErr.NotSupported, "Write not supported in FileEntry API");
92
- return Promise.resolve({ err });
93
- }
94
-
95
- public getFile(path: string): FsFile {
96
- return this.mgr.get(this, path);
97
- }
98
- public getOpenedPaths(): string[] {
99
- return this.mgr.getOpenedPaths();
100
- }
101
- public closeFile(path: string): void {
102
- this.mgr.close(path);
103
- }
104
-
105
- /** Resolve a directory entry. Path must be normalized */
106
- private async resolveDir(path: string): Promise<FsResult<FileSystemDirectoryEntry>> {
107
- if (fsIsRoot(path)) {
108
- return { val: this.rootEntry };
109
- }
110
- const entry = await tryAsync(
111
- () =>
112
- new Promise<FileSystemEntry>((resolve, reject) => {
113
- this.rootEntry.getDirectory(path, {}, resolve, reject);
114
- }),
115
- );
116
- if ("err" in entry) {
117
- const err = fsFail("Failed to resolve directory `" + path + "`: " + errstr(entry.err));
118
- return { err };
119
- }
120
- if (!entry.val.isDirectory) {
121
- const err = fsErr(FsErr.IsFile, "Path `" + path + "` is not a directory");
122
- return { err };
123
- }
124
- return entry as Ok<FileSystemDirectoryEntry>;
125
- }
126
-
127
- /** Resolve a file entry. Path must be normalized */
128
- private async resolveFile(path: string): Promise<FsResult<FileSystemFileEntry>> {
129
- if (fsIsRoot(path)) {
130
- const err = fsErr(FsErr.IsDirectory, "Path `" + path + "` is not a file");
131
- return { err };
132
- }
133
- const entry = await tryAsync(
134
- () =>
135
- new Promise<FileSystemEntry>((resolve, reject) => {
136
- this.rootEntry.getFile(path, {}, resolve, reject);
137
- }),
138
- );
139
- if ("err" in entry) {
140
- const err = fsFail("Failed to resolve file `" + path + "`: " + errstr(entry.err));
141
- return { err };
142
- }
143
- if (!entry.val.isFile) {
144
- const err = fsErr(FsErr.IsDirectory, "Path `" + path + "` is not a file");
145
- return { err };
146
- }
147
- return entry as Ok<FileSystemFileEntry>;
148
- }
149
- }
@@ -1,116 +0,0 @@
1
- import { ilog } from "../log/internal.ts";
2
-
3
- import type { FsFile } from "./FsFile.ts";
4
- import type { FsFileSystem, FsFileSystemUninit, FsCapabilities } from "./FsFileSystem.ts";
5
- import { FsErr, type FsResult, type FsVoid, fsErr } from "./FsError.ts";
6
- import { fsIsRoot, fsNormalize } from "./FsPath.ts";
7
- import { FsFileMgr } from "./FsFileMgr.ts";
8
- import type { FsFileSystemInternal } from "./FsFileSystemInternal.ts";
9
-
10
- /**
11
- * FileSystem implementation that uses a list of Files
12
- * This is supported in all browsers, but it is stale.
13
- * It's used for Firefox when the File Entries API is not available
14
- * i.e. opened from <input type="file">
15
- */
16
- export class FsImplFileAPI implements FsFileSystemUninit, FsFileSystem, FsFileSystemInternal {
17
- public root: string;
18
- public capabilities: FsCapabilities;
19
-
20
- private files: Record<string, File>;
21
- private directories: Record<string, string[]>;
22
- private mgr: FsFileMgr;
23
-
24
- constructor(files: FileList) {
25
- // this seems to also work for windows
26
- this.root = files[0].webkitRelativePath.split("/", 1)[0];
27
- this.capabilities = { write: false, live: false };
28
- this.files = {};
29
- this.directories = {};
30
- this.mgr = new FsFileMgr();
31
-
32
- for (let i = 0; i < files.length; i++) {
33
- const file = files[i];
34
- // remove "<root>/"
35
- const path = file.webkitRelativePath.slice(this.root.length + 1);
36
- const normalized = fsNormalize(path);
37
- if (normalized.err) {
38
- // shouldn't happen since the path is from the File API
39
- ilog.error("invalid path: " + path);
40
- continue;
41
- }
42
- this.files[normalized.val] = file;
43
- }
44
- }
45
-
46
- public init(): Promise<FsResult<FsFileSystem>> {
47
- // no init needed
48
- return Promise.resolve({ val: this });
49
- }
50
-
51
- public listDir(path: string): Promise<FsResult<string[]>> {
52
- const normalized = fsNormalize(path);
53
- if (normalized.err) {
54
- return Promise.resolve(normalized);
55
- }
56
- path = normalized.val;
57
-
58
- if (path in this.directories) {
59
- return Promise.resolve({ val: this.directories[path] });
60
- }
61
-
62
- const set = new Set<string>();
63
- const prefix = fsIsRoot(path) ? "" : path + "/";
64
-
65
- Object.keys(this.files).forEach((path) => {
66
- if (!path.startsWith(prefix)) {
67
- return;
68
- }
69
- const relPath = path.slice(prefix.length);
70
- const slashIndex = relPath.indexOf("/");
71
- if (slashIndex < 0) {
72
- // file
73
- set.add(relPath);
74
- } else {
75
- // directory
76
- const dir = relPath.slice(0, slashIndex + 1);
77
- set.add(dir);
78
- }
79
- });
80
-
81
- const paths = Array.from(set);
82
- this.directories[path] = paths;
83
-
84
- return Promise.resolve({ val: paths });
85
- }
86
-
87
- public read(path: string): Promise<FsResult<File>> {
88
- const normalized = fsNormalize(path);
89
- if (normalized.err) {
90
- return Promise.resolve(normalized);
91
- }
92
-
93
- const file = this.files[normalized.val];
94
- if (!file) {
95
- const err = fsErr(FsErr.NotFound, "File not found: " + path);
96
- return Promise.resolve({ err });
97
- }
98
-
99
- return Promise.resolve({ val: file });
100
- }
101
-
102
- public write(): Promise<FsVoid> {
103
- const err = fsErr(FsErr.NotSupported, "Write not supported in File API");
104
- return Promise.resolve({ err });
105
- }
106
-
107
- public getFile(path: string): FsFile {
108
- return this.mgr.get(this, path);
109
- }
110
- public getOpenedPaths(): string[] {
111
- return this.mgr.getOpenedPaths();
112
- }
113
- public closeFile(path: string): void {
114
- this.mgr.close(path);
115
- }
116
- }