@livestore/utils 0.4.0-dev.2 → 0.4.0-dev.20

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 (184) hide show
  1. package/dist/.tsbuildinfo.json +1 -1
  2. package/dist/NoopTracer.d.ts.map +1 -1
  3. package/dist/NoopTracer.js +1 -0
  4. package/dist/NoopTracer.js.map +1 -1
  5. package/dist/browser/Opfs/Opfs.d.ts +51 -0
  6. package/dist/browser/Opfs/Opfs.d.ts.map +1 -0
  7. package/dist/browser/Opfs/Opfs.js +345 -0
  8. package/dist/browser/Opfs/Opfs.js.map +1 -0
  9. package/dist/browser/Opfs/debug-utils.d.ts +20 -0
  10. package/dist/browser/Opfs/debug-utils.d.ts.map +1 -0
  11. package/dist/browser/Opfs/debug-utils.js +94 -0
  12. package/dist/browser/Opfs/debug-utils.js.map +1 -0
  13. package/dist/browser/Opfs/mod.d.ts +4 -0
  14. package/dist/browser/Opfs/mod.d.ts.map +1 -0
  15. package/dist/browser/Opfs/mod.js +4 -0
  16. package/dist/browser/Opfs/mod.js.map +1 -0
  17. package/dist/browser/Opfs/utils.d.ts +68 -0
  18. package/dist/browser/Opfs/utils.d.ts.map +1 -0
  19. package/dist/browser/Opfs/utils.js +206 -0
  20. package/dist/browser/Opfs/utils.js.map +1 -0
  21. package/dist/browser/QuotaExceededError.d.ts +59 -0
  22. package/dist/browser/QuotaExceededError.d.ts.map +1 -0
  23. package/dist/browser/QuotaExceededError.js +2 -0
  24. package/dist/browser/QuotaExceededError.js.map +1 -0
  25. package/dist/browser/WebChannelBrowser.d.ts +22 -0
  26. package/dist/browser/WebChannelBrowser.d.ts.map +1 -0
  27. package/dist/browser/WebChannelBrowser.js +76 -0
  28. package/dist/browser/WebChannelBrowser.js.map +1 -0
  29. package/dist/browser/WebError.d.ts +425 -0
  30. package/dist/browser/WebError.d.ts.map +1 -0
  31. package/dist/browser/WebError.js +414 -0
  32. package/dist/browser/WebError.js.map +1 -0
  33. package/dist/browser/WebError.test.d.ts +2 -0
  34. package/dist/browser/WebError.test.d.ts.map +1 -0
  35. package/dist/browser/WebError.test.js +46 -0
  36. package/dist/browser/WebError.test.js.map +1 -0
  37. package/dist/browser/WebLock.d.ts.map +1 -0
  38. package/dist/browser/WebLock.js.map +1 -0
  39. package/dist/{browser.d.ts → browser/detect.d.ts} +1 -1
  40. package/dist/browser/detect.d.ts.map +1 -0
  41. package/dist/{browser.js → browser/detect.js} +1 -1
  42. package/dist/browser/detect.js.map +1 -0
  43. package/dist/browser/mod.d.ts +8 -0
  44. package/dist/browser/mod.d.ts.map +1 -0
  45. package/dist/browser/mod.js +8 -0
  46. package/dist/browser/mod.js.map +1 -0
  47. package/dist/effect/Debug.d.ts +38 -0
  48. package/dist/effect/Debug.d.ts.map +1 -0
  49. package/dist/effect/Debug.js +287 -0
  50. package/dist/effect/Debug.js.map +1 -0
  51. package/dist/effect/Effect.d.ts +9 -3
  52. package/dist/effect/Effect.d.ts.map +1 -1
  53. package/dist/effect/Effect.js +4 -2
  54. package/dist/effect/Effect.js.map +1 -1
  55. package/dist/effect/Error.d.ts +1 -1
  56. package/dist/effect/Error.js.map +1 -1
  57. package/dist/effect/Logger.d.ts +4 -1
  58. package/dist/effect/Logger.d.ts.map +1 -1
  59. package/dist/effect/Logger.js +12 -3
  60. package/dist/effect/Logger.js.map +1 -1
  61. package/dist/effect/OtelTracer.d.ts +5 -0
  62. package/dist/effect/OtelTracer.d.ts.map +1 -0
  63. package/dist/effect/OtelTracer.js +8 -0
  64. package/dist/effect/OtelTracer.js.map +1 -0
  65. package/dist/effect/RpcClient.d.ts +32 -0
  66. package/dist/effect/RpcClient.d.ts.map +1 -0
  67. package/dist/effect/RpcClient.js +149 -0
  68. package/dist/effect/RpcClient.js.map +1 -0
  69. package/dist/effect/Schema/index.d.ts +2 -2
  70. package/dist/effect/Schema/index.d.ts.map +1 -1
  71. package/dist/effect/Schema/index.js +12 -2
  72. package/dist/effect/Schema/index.js.map +1 -1
  73. package/dist/effect/Stream.d.ts +73 -2
  74. package/dist/effect/Stream.d.ts.map +1 -1
  75. package/dist/effect/Stream.js +68 -1
  76. package/dist/effect/Stream.js.map +1 -1
  77. package/dist/effect/Stream.test.d.ts +2 -0
  78. package/dist/effect/Stream.test.d.ts.map +1 -0
  79. package/dist/effect/Stream.test.js +84 -0
  80. package/dist/effect/Stream.test.js.map +1 -0
  81. package/dist/effect/SubscriptionRef.d.ts +2 -2
  82. package/dist/effect/SubscriptionRef.d.ts.map +1 -1
  83. package/dist/effect/SubscriptionRef.js +6 -1
  84. package/dist/effect/SubscriptionRef.js.map +1 -1
  85. package/dist/effect/WebChannel/WebChannel.d.ts +2 -21
  86. package/dist/effect/WebChannel/WebChannel.d.ts.map +1 -1
  87. package/dist/effect/WebChannel/WebChannel.js +5 -81
  88. package/dist/effect/WebChannel/WebChannel.js.map +1 -1
  89. package/dist/effect/WebChannel/WebChannel.test.js +1 -1
  90. package/dist/effect/WebChannel/WebChannel.test.js.map +1 -1
  91. package/dist/effect/WebChannel/common.d.ts +1 -1
  92. package/dist/effect/WebChannel/common.d.ts.map +1 -1
  93. package/dist/effect/WebSocket.d.ts.map +1 -1
  94. package/dist/effect/WebSocket.js +12 -12
  95. package/dist/effect/WebSocket.js.map +1 -1
  96. package/dist/effect/mod.d.ts +32 -0
  97. package/dist/effect/mod.d.ts.map +1 -0
  98. package/dist/effect/mod.js +35 -0
  99. package/dist/effect/mod.js.map +1 -0
  100. package/dist/global.d.ts +1 -0
  101. package/dist/global.d.ts.map +1 -1
  102. package/dist/global.js.map +1 -1
  103. package/dist/misc.js +1 -1
  104. package/dist/misc.js.map +1 -1
  105. package/dist/mod.d.ts +3 -1
  106. package/dist/mod.d.ts.map +1 -1
  107. package/dist/mod.js +5 -1
  108. package/dist/mod.js.map +1 -1
  109. package/dist/node/ChildProcessRunner/ChildProcessRunner.d.ts.map +1 -1
  110. package/dist/node/ChildProcessRunner/ChildProcessRunner.js +66 -10
  111. package/dist/node/ChildProcessRunner/ChildProcessRunner.js.map +1 -1
  112. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js +177 -3
  113. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js.map +1 -1
  114. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.d.ts +14 -5
  115. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.d.ts.map +1 -1
  116. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.js +7 -1
  117. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.js.map +1 -1
  118. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.js +13 -3
  119. package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.js.map +1 -1
  120. package/dist/node/ChildProcessRunner/ChildProcessWorker.d.ts +16 -0
  121. package/dist/node/ChildProcessRunner/ChildProcessWorker.d.ts.map +1 -1
  122. package/dist/node/ChildProcessRunner/ChildProcessWorker.js +98 -2
  123. package/dist/node/ChildProcessRunner/ChildProcessWorker.js.map +1 -1
  124. package/dist/node/mod.d.ts +8 -2
  125. package/dist/node/mod.d.ts.map +1 -1
  126. package/dist/node/mod.js +11 -3
  127. package/dist/node/mod.js.map +1 -1
  128. package/dist/qr.d.ts +38 -0
  129. package/dist/qr.d.ts.map +1 -0
  130. package/dist/qr.js +109 -0
  131. package/dist/qr.js.map +1 -0
  132. package/package.json +54 -44
  133. package/src/NoopTracer.ts +1 -0
  134. package/src/browser/Opfs/Opfs.ts +428 -0
  135. package/src/browser/Opfs/debug-utils.ts +151 -0
  136. package/src/browser/Opfs/mod.ts +3 -0
  137. package/src/browser/Opfs/utils.ts +270 -0
  138. package/src/browser/QuotaExceededError.ts +59 -0
  139. package/src/browser/WebChannelBrowser.ts +131 -0
  140. package/src/browser/WebError.test.ts +66 -0
  141. package/src/browser/WebError.ts +599 -0
  142. package/src/browser/mod.ts +8 -0
  143. package/src/effect/Debug.ts +375 -0
  144. package/src/effect/Effect.ts +31 -4
  145. package/src/effect/Error.ts +1 -1
  146. package/src/effect/Logger.ts +14 -4
  147. package/src/effect/OtelTracer.ts +11 -0
  148. package/src/effect/RpcClient.ts +212 -0
  149. package/src/effect/Schema/index.ts +17 -3
  150. package/src/effect/Stream.test.ts +127 -0
  151. package/src/effect/Stream.ts +111 -2
  152. package/src/effect/SubscriptionRef.ts +14 -2
  153. package/src/effect/WebChannel/WebChannel.test.ts +1 -1
  154. package/src/effect/WebChannel/WebChannel.ts +13 -135
  155. package/src/effect/WebChannel/common.ts +1 -1
  156. package/src/effect/WebSocket.ts +11 -10
  157. package/src/effect/{index.ts → mod.ts} +42 -15
  158. package/src/global.ts +1 -0
  159. package/src/misc.ts +1 -1
  160. package/src/mod.ts +10 -1
  161. package/src/node/ChildProcessRunner/ChildProcessRunner.ts +71 -10
  162. package/src/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.ts +258 -3
  163. package/src/node/ChildProcessRunner/ChildProcessRunnerTest/schema.ts +14 -1
  164. package/src/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.ts +16 -3
  165. package/src/node/ChildProcessRunner/ChildProcessWorker.ts +111 -3
  166. package/src/node/mod.ts +13 -6
  167. package/src/qr.ts +125 -0
  168. package/dist/browser.d.ts.map +0 -1
  169. package/dist/browser.js.map +0 -1
  170. package/dist/effect/Schema/msgpack.d.ts +0 -3
  171. package/dist/effect/Schema/msgpack.d.ts.map +0 -1
  172. package/dist/effect/Schema/msgpack.js +0 -7
  173. package/dist/effect/Schema/msgpack.js.map +0 -1
  174. package/dist/effect/WebLock.d.ts.map +0 -1
  175. package/dist/effect/WebLock.js.map +0 -1
  176. package/dist/effect/index.d.ts +0 -27
  177. package/dist/effect/index.d.ts.map +0 -1
  178. package/dist/effect/index.js +0 -31
  179. package/dist/effect/index.js.map +0 -1
  180. package/src/effect/Schema/msgpack.ts +0 -8
  181. /package/dist/{effect → browser}/WebLock.d.ts +0 -0
  182. /package/dist/{effect → browser}/WebLock.js +0 -0
  183. /package/src/{effect → browser}/WebLock.ts +0 -0
  184. /package/src/{browser.ts → browser/detect.ts} +0 -0
@@ -0,0 +1,68 @@
1
+ import { Effect } from 'effect';
2
+ import { Opfs, OpfsError } from './Opfs.ts';
3
+ /**
4
+ * Resolve a directory handle using a slash-delimited OPFS path.
5
+ *
6
+ * @param path - Directory path relative to the OPFS root.
7
+ * @param options - Options forwarded to `getDirectoryHandle` when traversing segments.
8
+ * @returns Directory handle for the final segment.
9
+ */
10
+ export declare const getDirectoryHandleByPath: (path: string, options?: FileSystemGetDirectoryOptions | undefined) => Effect.Effect<FileSystemDirectoryHandle, import("../WebError.ts").TypeError | import("../WebError.ts").NotFoundError | import("../WebError.ts").NotAllowedError | import("../WebError.ts").TypeMismatchError | import("../WebError.ts").SecurityError | import("../WebError.ts").UnknownError | OpfsError, Opfs>;
11
+ /**
12
+ * Remove a file or directory identified by an OPFS path.
13
+ *
14
+ * @param path - Slash-delimited path to delete.
15
+ * @param options.recursive - When `true`, recursively delete directory contents; defaults to `false`.
16
+ */
17
+ export declare const remove: (path: string, options?: {
18
+ readonly recursive?: boolean;
19
+ } | undefined) => Effect.Effect<void, import("../WebError.ts").TypeError | import("../WebError.ts").NoModificationAllowedError | import("../WebError.ts").NotFoundError | import("../WebError.ts").NotAllowedError | import("../WebError.ts").TypeMismatchError | import("../WebError.ts").InvalidModificationError | import("../WebError.ts").SecurityError | import("../WebError.ts").UnknownError | OpfsError, Opfs>;
20
+ /**
21
+ * Determine whether a file or directory exists at the given OPFS path.
22
+ *
23
+ * @param path - Slash-delimited path to inspect.
24
+ * @returns `true` if the path resolves to a file or directory, otherwise `false`.
25
+ */
26
+ export declare const exists: (path: string) => Effect.Effect<boolean, import("../WebError.ts").TypeError | import("../WebError.ts").NotAllowedError | import("../WebError.ts").TypeMismatchError | import("../WebError.ts").SecurityError | import("../WebError.ts").UnknownError | OpfsError, Opfs>;
27
+ /**
28
+ * Create a directory at the provided path, optionally creating parents recursively.
29
+ *
30
+ * @param path - Slash-delimited directory path.
31
+ * @param options.recursive - When `true`, create all missing parent segments; defaults to `false`.
32
+ */
33
+ export declare const makeDirectory: (path: string, options?: {
34
+ readonly recursive?: boolean;
35
+ } | undefined) => Effect.Effect<void, import("../WebError.ts").TypeError | import("../WebError.ts").NotFoundError | import("../WebError.ts").NotAllowedError | import("../WebError.ts").TypeMismatchError | import("../WebError.ts").SecurityError | import("../WebError.ts").UnknownError | OpfsError, Opfs>;
36
+ /**
37
+ * Extract basic metadata for a given file handle.
38
+ *
39
+ * @param handle - File handle whose metadata should be read.
40
+ * @returns Object containing name, size, MIME type, and last modification timestamp.
41
+ */
42
+ export declare const getMetadata: (handle: FileSystemFileHandle) => Effect.Effect<{
43
+ name: string;
44
+ size: number;
45
+ type: string;
46
+ lastModified: number;
47
+ }, import("../WebError.ts").NotFoundError | import("../WebError.ts").NotAllowedError | import("../WebError.ts").UnknownError, Opfs>;
48
+ /**
49
+ * Write bytes to an OPFS path, creating or replacing the target file.
50
+ *
51
+ * @param path - Slash-delimited file path.
52
+ * @param data - Bytes to persist.
53
+ */
54
+ export declare const writeFile: (path: string, data: Uint8Array<ArrayBufferLike>) => Effect.Effect<void, import("../WebError.ts").TypeError | import("../WebError.ts").NoModificationAllowedError | import("../WebError.ts").NotFoundError | import("../WebError.ts").NotAllowedError | import("../WebError.ts").TypeMismatchError | import("../WebError.ts").AbortError | import("../WebError.ts").SecurityError | import("../WebError.ts").QuotaExceededError | import("../WebError.ts").UnknownError | OpfsError, Opfs>;
55
+ /**
56
+ * Synchronously write bytes to the target file handle, truncating any existing content.
57
+ *
58
+ * @param handle - Sync access handle to overwrite.
59
+ * @param buffer - Raw data to persist.
60
+ * @returns Effect that resolves once every byte is flushed to durable storage.
61
+ *
62
+ * @remarks
63
+ * - Only available in Dedicated Web Workers.
64
+ * - Crash safety: not atomic. A crash mid-write can leave the file truncated or partially written.
65
+ * For atomic replacement, prefer `writeFile` or a temp-file pattern with two prepared handles.
66
+ */
67
+ export declare const syncWriteFile: (handle: FileSystemSyncAccessHandle, buffer: AllowSharedBufferSource) => Effect.Effect<undefined, import("../WebError.ts").WebError | OpfsError, Opfs>;
68
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/browser/Opfs/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAA;AACvC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAoG3C;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,yXAQnC,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,MAAM;yBAEgB,OAAO;uZAkBxC,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,MAAM,yQAiBjB,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa;yBAES,OAAO;6SASxC,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,WAAW;;;;;mIAStB,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,SAAS,4dAoBpB,CAAA;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,wJAsBxB,CAAA"}
@@ -0,0 +1,206 @@
1
+ import { Effect, Stream } from 'effect';
2
+ import { Opfs, OpfsError } from "./Opfs.js";
3
+ /**
4
+ * Set of path segments that are forbidden by the File System specification.
5
+ *
6
+ * A valid segment is non-empty, not equal to `.` or `..`, and must not have path separator characters.
7
+ *
8
+ * @see {@link https://fs.spec.whatwg.org/#valid-file-name | File System Spec}
9
+ */
10
+ const DISALLOWED_SEGMENTS = new Set(['.', '..']);
11
+ /**
12
+ * Parse a slash-separated OPFS path into validated segments.
13
+ *
14
+ * Rejects empty paths and disallows `.` / `..` so callers cannot rely on implicit current/parent
15
+ * directory semantics that the File System Access API does not support.
16
+ *
17
+ * @param path - Slash-delimited path relative to the OPFS root.
18
+ * @returns Effect that yields the sanitized path segments.
19
+ */
20
+ const parsePathSegments = (path) => Effect.gen(function* () {
21
+ const segments = path.split('/').filter((segment) => segment.length > 0);
22
+ if (segments.length === 0) {
23
+ return yield* new OpfsError({
24
+ message: `Invalid OPFS path '${path}': path must contain at least one non-empty segment`,
25
+ });
26
+ }
27
+ for (const segment of segments) {
28
+ if (DISALLOWED_SEGMENTS.has(segment)) {
29
+ return yield* new OpfsError({
30
+ message: `Invalid OPFS path '${path}': segment '${segment}' is not supported`,
31
+ });
32
+ }
33
+ }
34
+ return segments;
35
+ });
36
+ /**
37
+ * Determine whether the provided OPFS path refers to the origin root.
38
+ */
39
+ const isRootPath = (path) => path === '' || path === '/';
40
+ /**
41
+ * Split a set of path segments into parent and leaf portions.
42
+ *
43
+ * @param segments - Non-empty sequence of path segments pointing to a concrete entry.
44
+ * @returns Parent directory segments and the final segment representing the target entry.
45
+ */
46
+ const splitPathSegments = (segments) => ({
47
+ parentSegments: segments.slice(0, -1),
48
+ leafSegment: segments[segments.length - 1],
49
+ });
50
+ /**
51
+ * Resolve a directory path from the OPFS root and return the final directory handle.
52
+ *
53
+ * @param segments - Ordered list of directory names to follow.
54
+ * @param options - Options forwarded to each `getDirectoryHandle` call.
55
+ */
56
+ const traverseDirectoryPath = (segments, options) => Effect.gen(function* () {
57
+ let currentDirHandle = yield* Opfs.getRootDirectoryHandle;
58
+ for (let index = 0; index < segments.length; index++) {
59
+ const segment = segments[index];
60
+ currentDirHandle = yield* Opfs.getDirectoryHandle(currentDirHandle, segment, options);
61
+ }
62
+ return currentDirHandle;
63
+ });
64
+ /**
65
+ * Ensure that a directory path exists, creating intermediate segments when permitted.
66
+ *
67
+ * @param segments - Ordered list of directory names to ensure.
68
+ * @param options.recursive - When `true`, create every missing segment. Otherwise only the leaf is created.
69
+ */
70
+ const ensureDirectoryPath = (segments, options) => Effect.gen(function* () {
71
+ let currentDirHandle = yield* Opfs.getRootDirectoryHandle;
72
+ for (let index = 0; index < segments.length; index++) {
73
+ const segment = segments[index];
74
+ const isLast = index === segments.length - 1;
75
+ const shouldCreate = options.recursive || isLast;
76
+ currentDirHandle = yield* Opfs.getDirectoryHandle(currentDirHandle, segment, shouldCreate ? { create: true } : undefined);
77
+ }
78
+ return currentDirHandle;
79
+ });
80
+ /**
81
+ * Resolve a directory handle using a slash-delimited OPFS path.
82
+ *
83
+ * @param path - Directory path relative to the OPFS root.
84
+ * @param options - Options forwarded to `getDirectoryHandle` when traversing segments.
85
+ * @returns Directory handle for the final segment.
86
+ */
87
+ export const getDirectoryHandleByPath = Effect.fn('@livestore/utils:Opfs.getDirectoryHandleByPath')(function* (path, options) {
88
+ if (isRootPath(path))
89
+ return yield* Opfs.getRootDirectoryHandle;
90
+ const pathSegments = yield* parsePathSegments(path);
91
+ return yield* traverseDirectoryPath(pathSegments, options);
92
+ });
93
+ /**
94
+ * Remove a file or directory identified by an OPFS path.
95
+ *
96
+ * @param path - Slash-delimited path to delete.
97
+ * @param options.recursive - When `true`, recursively delete directory contents; defaults to `false`.
98
+ */
99
+ export const remove = Effect.fn('@livestore/utils:Opfs.remove')(function* (path, options) {
100
+ const recursive = options?.recursive ?? false;
101
+ if (isRootPath(path)) {
102
+ const rootHandle = yield* Opfs.getRootDirectoryHandle;
103
+ const handlesStream = yield* Opfs.values(rootHandle);
104
+ yield* handlesStream.pipe(Stream.runForEach((handle) => Opfs.removeEntry(rootHandle, handle.name, { recursive: true })));
105
+ return;
106
+ }
107
+ const pathSegments = yield* parsePathSegments(path);
108
+ const { parentSegments, leafSegment: targetName } = splitPathSegments(pathSegments);
109
+ const parentDirHandle = yield* traverseDirectoryPath(parentSegments);
110
+ yield* Opfs.removeEntry(parentDirHandle, targetName, { recursive });
111
+ });
112
+ /**
113
+ * Determine whether a file or directory exists at the given OPFS path.
114
+ *
115
+ * @param path - Slash-delimited path to inspect.
116
+ * @returns `true` if the path resolves to a file or directory, otherwise `false`.
117
+ */
118
+ export const exists = Effect.fn('@livestore/utils:Opfs.exists')(function* (path) {
119
+ if (isRootPath(path))
120
+ return true;
121
+ const pathSegments = yield* parsePathSegments(path);
122
+ const { parentSegments, leafSegment: targetName } = splitPathSegments(pathSegments);
123
+ const parentDirHandle = yield* traverseDirectoryPath(parentSegments, { create: false }).pipe(Effect.catchTag('@livestore/utils/Web/NotFoundError', () => Effect.succeed(undefined)));
124
+ if (parentDirHandle === undefined)
125
+ return false;
126
+ return yield* Opfs.getFileHandle(parentDirHandle, targetName).pipe(Effect.orElse(() => Opfs.getDirectoryHandle(parentDirHandle, targetName, { create: false })), Effect.as(true), Effect.catchTag('@livestore/utils/Web/NotFoundError', () => Effect.succeed(false)));
127
+ });
128
+ /**
129
+ * Create a directory at the provided path, optionally creating parents recursively.
130
+ *
131
+ * @param path - Slash-delimited directory path.
132
+ * @param options.recursive - When `true`, create all missing parent segments; defaults to `false`.
133
+ */
134
+ export const makeDirectory = Effect.fn('@livestore/utils:Opfs.makeDirectory')(function* (path, options) {
135
+ const recursive = options?.recursive ?? false;
136
+ if (isRootPath(path))
137
+ return;
138
+ const pathSegments = yield* parsePathSegments(path);
139
+ yield* ensureDirectoryPath(pathSegments, { recursive });
140
+ });
141
+ /**
142
+ * Extract basic metadata for a given file handle.
143
+ *
144
+ * @param handle - File handle whose metadata should be read.
145
+ * @returns Object containing name, size, MIME type, and last modification timestamp.
146
+ */
147
+ export const getMetadata = Effect.fn('@livestore/utils:Opfs.getMetadata')(function* (handle) {
148
+ return yield* Opfs.getFile(handle).pipe(Effect.map((file) => ({
149
+ name: file.name,
150
+ size: file.size,
151
+ type: file.type,
152
+ lastModified: file.lastModified,
153
+ })));
154
+ });
155
+ /**
156
+ * Write bytes to an OPFS path, creating or replacing the target file.
157
+ *
158
+ * @param path - Slash-delimited file path.
159
+ * @param data - Bytes to persist.
160
+ */
161
+ export const writeFile = Effect.fn('@livestore/utils:Opfs.writeFile')(function* (path, data) {
162
+ if (isRootPath(path)) {
163
+ return yield* new OpfsError({
164
+ message: `Invalid OPFS path '${path}': cannot write file directly to the OPFS root`,
165
+ });
166
+ }
167
+ const pathSegments = yield* parsePathSegments(path);
168
+ const { parentSegments, leafSegment: fileName } = splitPathSegments(pathSegments);
169
+ return yield* Effect.scoped(Effect.gen(function* () {
170
+ const parentDirHandle = yield* traverseDirectoryPath(parentSegments);
171
+ const fileHandle = yield* Opfs.getFileHandle(parentDirHandle, fileName, { create: true });
172
+ yield* Opfs.writeFile(fileHandle, new Uint8Array(data), {
173
+ keepExistingData: false,
174
+ });
175
+ }));
176
+ });
177
+ /**
178
+ * Synchronously write bytes to the target file handle, truncating any existing content.
179
+ *
180
+ * @param handle - Sync access handle to overwrite.
181
+ * @param buffer - Raw data to persist.
182
+ * @returns Effect that resolves once every byte is flushed to durable storage.
183
+ *
184
+ * @remarks
185
+ * - Only available in Dedicated Web Workers.
186
+ * - Crash safety: not atomic. A crash mid-write can leave the file truncated or partially written.
187
+ * For atomic replacement, prefer `writeFile` or a temp-file pattern with two prepared handles.
188
+ */
189
+ export const syncWriteFile = Effect.fn('@livestore/utils:Opfs.syncWriteFile')(function* (handle, buffer) {
190
+ const bytes = ArrayBuffer.isView(buffer)
191
+ ? new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength)
192
+ : new Uint8Array(buffer);
193
+ yield* Opfs.syncTruncate(handle, 0);
194
+ let offset = 0;
195
+ while (offset < bytes.byteLength) {
196
+ const wrote = yield* Opfs.syncWrite(handle, bytes.subarray(offset), { at: offset });
197
+ if (wrote === 0) {
198
+ return yield* new OpfsError({
199
+ message: `Short write: wrote ${offset} of ${bytes.byteLength} bytes.`,
200
+ });
201
+ }
202
+ offset += Number(wrote);
203
+ }
204
+ yield* Opfs.syncFlush(handle);
205
+ });
206
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/browser/Opfs/utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Type augmentation for the `QuotaExceededError` interface.
3
+ *
4
+ * In previous versions of the Web platform standard, quota exceeded errors were to be thrown
5
+ * as regular `DOMException` objects with `name: "QuotaExceededError"`. In the latest versions,
6
+ * the `QuotaExceededError` exists as a dedicated interface extending `DOMException`, providing
7
+ * additional properties like `quota` and `requested`.
8
+ *
9
+ * As of TypeScript 5.9, the standard DOM type definitions (`lib.dom.d.ts`) do **not** include
10
+ * the `QuotaExceededError` interface, even though it is already supported by a few browsers.
11
+ *
12
+ * This file provides the missing type definitions so that code can safely reference
13
+ * `globalThis.QuotaExceededError` with proper type checking, supporting both:
14
+ * - Browsers with the new dedicated interface
15
+ * - Browsers still using a regular `DOMException`
16
+ *
17
+ * @see {@link https://webidl.spec.whatwg.org/#quotaexceedederror | Web IDL Specification}
18
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/QuotaExceededError | MDN Reference}
19
+ */
20
+ declare global {
21
+ interface QuotaExceededError extends DOMException {
22
+ /**
23
+ * The **`message`** read-only property of a message or description associated with the given error name.
24
+ *
25
+ * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/QuotaExceededError/QuotaExceededError#message)
26
+ */
27
+ readonly message: string;
28
+ /**
29
+ * A number representing the quota limit in bytes, or undefined.
30
+ *
31
+ * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/QuotaExceededError/quota)
32
+ */
33
+ readonly quota?: number;
34
+ /**
35
+ * A number representing the requested amount of storage in bytes, or undefined.
36
+ *
37
+ * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/QuotaExceededError/requested)
38
+ */
39
+ readonly requested?: number;
40
+ }
41
+ /**
42
+ * The **`QuotaExceededError`** represents an error when a requested operation would exceed a system-imposed storage quota.
43
+ *
44
+ * @remarks
45
+ *
46
+ * In browser versions before this interface was implemented, it was a regular DOMException. The subclassing allows for extra information like quota and requested to be included.
47
+ *
48
+ * [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/QuotaExceededError)
49
+ */
50
+ var QuotaExceededError: {
51
+ prototype: QuotaExceededError;
52
+ new (message?: string, options?: {
53
+ quota: number;
54
+ requested: number;
55
+ }): QuotaExceededError;
56
+ } | undefined;
57
+ }
58
+ export {};
59
+ //# sourceMappingURL=QuotaExceededError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QuotaExceededError.d.ts","sourceRoot":"","sources":["../../src/browser/QuotaExceededError.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,kBAAmB,SAAQ,YAAY;QAC/C;;;;WAIG;QACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;QACxB;;;;WAIG;QACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;QACvB;;;;WAIG;QACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAC5B;IAED;;;;;;;;OAQG;IACH,IAAI,kBAAkB,EAClB;QACE,SAAS,EAAE,kBAAkB,CAAA;QAC7B,KAAK,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,GAAG,kBAAkB,CAAA;KAC3F,GACD,SAAS,CAAA;CACd;AAED,OAAO,EAAE,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=QuotaExceededError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QuotaExceededError.js","sourceRoot":"","sources":["../../src/browser/QuotaExceededError.ts"],"names":[],"mappings":"AA0DA,OAAO,EAAE,CAAA"}
@@ -0,0 +1,22 @@
1
+ import { Scope } from 'effect';
2
+ import * as Effect from '../effect/Effect.ts';
3
+ import { type InputSchema, type WebChannel } from '../effect/WebChannel/common.ts';
4
+ /** Browser BroadcastChannel-backed WebChannel */
5
+ export declare const broadcastChannel: <MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded>({ channelName, schema: inputSchema, }: {
6
+ channelName: string;
7
+ schema: InputSchema<MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded>;
8
+ }) => Effect.Effect<WebChannel<MsgListen, MsgSend>, never, Scope.Scope>;
9
+ /**
10
+ * Window.postMessage-based WebChannel
11
+ */
12
+ export declare const windowChannel: <MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded>({ listenWindow, sendWindow, targetOrigin, ids, schema: inputSchema, }: {
13
+ listenWindow: Window;
14
+ sendWindow: Window;
15
+ targetOrigin?: string;
16
+ ids: {
17
+ own: string;
18
+ other: string;
19
+ };
20
+ schema: InputSchema<MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded>;
21
+ }) => Effect.Effect<WebChannel<MsgListen, MsgSend>, never, Scope.Scope>;
22
+ //# sourceMappingURL=WebChannelBrowser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebChannelBrowser.d.ts","sourceRoot":"","sources":["../../src/browser/WebChannelBrowser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,EAAE,MAAM,QAAQ,CAAA;AAE9C,OAAO,KAAK,MAAM,MAAM,qBAAqB,CAAA;AAG7C,OAAO,EACL,KAAK,WAAW,EAGhB,KAAK,UAAU,EAEhB,MAAM,gCAAgC,CAAA;AAEvC,iDAAiD;AACjD,eAAO,MAAM,gBAAgB,GAAI,SAAS,EAAE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,uCAGpF;IACD,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,WAAW,CAAC,SAAS,EAAE,OAAO,EAAE,gBAAgB,EAAE,cAAc,CAAC,CAAA;CAC1E,KAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAkCjE,CAAA;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,SAAS,EAAE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,uEAMjF;IACD,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,GAAG,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACnC,MAAM,EAAE,WAAW,CAAC,SAAS,EAAE,OAAO,EAAE,gBAAgB,EAAE,cAAc,CAAC,CAAA;CAC1E,KAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CA2DjE,CAAA"}
@@ -0,0 +1,76 @@
1
+ import { Deferred, Exit, Scope } from 'effect';
2
+ import * as Effect from "../effect/Effect.js";
3
+ import * as Schema from "../effect/Schema/index.js";
4
+ import * as Stream from "../effect/Stream.js";
5
+ import { listenToDebugPing, mapSchema, WebChannelSymbol, } from "../effect/WebChannel/common.js";
6
+ /** Browser BroadcastChannel-backed WebChannel */
7
+ export const broadcastChannel = ({ channelName, schema: inputSchema, }) => Effect.scopeWithCloseable((scope) => Effect.gen(function* () {
8
+ const schema = mapSchema(inputSchema);
9
+ const channel = new BroadcastChannel(channelName);
10
+ yield* Effect.addFinalizer(() => Effect.try(() => channel.close()).pipe(Effect.ignoreLogged));
11
+ const send = (message) => Effect.gen(function* () {
12
+ const messageEncoded = yield* Schema.encode(schema.send)(message);
13
+ channel.postMessage(messageEncoded);
14
+ });
15
+ // TODO also listen to `messageerror` in parallel
16
+ const listen = Stream.fromEventListener(channel, 'message').pipe(Stream.map((_) => Schema.decodeEither(schema.listen)(_.data)), listenToDebugPing(channelName));
17
+ const closedDeferred = yield* Deferred.make().pipe(Effect.acquireRelease(Deferred.done(Exit.void)));
18
+ const supportsTransferables = false;
19
+ return {
20
+ [WebChannelSymbol]: WebChannelSymbol,
21
+ send,
22
+ listen,
23
+ closedDeferred,
24
+ shutdown: Scope.close(scope, Exit.succeed('shutdown')),
25
+ schema,
26
+ supportsTransferables,
27
+ };
28
+ }).pipe(Effect.withSpan(`WebChannel:broadcastChannel(${channelName})`)));
29
+ /**
30
+ * Window.postMessage-based WebChannel
31
+ */
32
+ export const windowChannel = ({ listenWindow, sendWindow, targetOrigin = '*', ids, schema: inputSchema, }) => Effect.scopeWithCloseable((scope) => Effect.gen(function* () {
33
+ const schema = mapSchema(inputSchema);
34
+ const debugInfo = {
35
+ sendTotal: 0,
36
+ listenTotal: 0,
37
+ targetOrigin,
38
+ ids,
39
+ };
40
+ const WindowMessageListen = Schema.Struct({
41
+ message: schema.listen,
42
+ from: Schema.Literal(ids.other),
43
+ to: Schema.Literal(ids.own),
44
+ }).annotations({ title: 'webmesh.WindowMessageListen' });
45
+ const WindowMessageSend = Schema.Struct({
46
+ message: schema.send,
47
+ from: Schema.Literal(ids.own),
48
+ to: Schema.Literal(ids.other),
49
+ }).annotations({ title: 'webmesh.WindowMessageSend' });
50
+ const send = (message) => Effect.gen(function* () {
51
+ debugInfo.sendTotal++;
52
+ const [messageEncoded, transferables] = yield* Schema.encodeWithTransferables(WindowMessageSend)({
53
+ message,
54
+ from: ids.own,
55
+ to: ids.other,
56
+ });
57
+ sendWindow.postMessage(messageEncoded, targetOrigin, transferables);
58
+ });
59
+ const listen = Stream.fromEventListener(listenWindow, 'message').pipe(Stream.filter((_) => Schema.is(Schema.encodedSchema(WindowMessageListen))(_.data)), Stream.map((_) => {
60
+ debugInfo.listenTotal++;
61
+ return Schema.decodeEither(schema.listen)(_.data.message);
62
+ }), listenToDebugPing('window'));
63
+ const closedDeferred = yield* Deferred.make().pipe(Effect.acquireRelease(Deferred.done(Exit.void)));
64
+ const supportsTransferables = true;
65
+ return {
66
+ [WebChannelSymbol]: WebChannelSymbol,
67
+ send,
68
+ listen,
69
+ closedDeferred,
70
+ shutdown: Scope.close(scope, Exit.succeed('shutdown')),
71
+ schema,
72
+ supportsTransferables,
73
+ debugInfo,
74
+ };
75
+ }).pipe(Effect.withSpan(`WebChannel:windowChannel`)));
76
+ //# sourceMappingURL=WebChannelBrowser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebChannelBrowser.js","sourceRoot":"","sources":["../../src/browser/WebChannelBrowser.ts"],"names":[],"mappings":"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"}