@effect/platform-browser 4.0.0-beta.7 → 4.0.0-beta.71

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 (91) hide show
  1. package/dist/BrowserCrypto.d.ts +81 -0
  2. package/dist/BrowserCrypto.d.ts.map +1 -0
  3. package/dist/BrowserCrypto.js +119 -0
  4. package/dist/BrowserCrypto.js.map +1 -0
  5. package/dist/BrowserHttpClient.d.ts +40 -16
  6. package/dist/BrowserHttpClient.d.ts.map +1 -1
  7. package/dist/BrowserHttpClient.js +74 -18
  8. package/dist/BrowserHttpClient.js.map +1 -1
  9. package/dist/BrowserKeyValueStore.d.ts +37 -14
  10. package/dist/BrowserKeyValueStore.d.ts.map +1 -1
  11. package/dist/BrowserKeyValueStore.js +185 -10
  12. package/dist/BrowserKeyValueStore.js.map +1 -1
  13. package/dist/BrowserPersistence.d.ts +40 -0
  14. package/dist/BrowserPersistence.d.ts.map +1 -0
  15. package/dist/BrowserPersistence.js +207 -0
  16. package/dist/BrowserPersistence.js.map +1 -0
  17. package/dist/BrowserRuntime.d.ts +79 -4
  18. package/dist/BrowserRuntime.d.ts.map +1 -1
  19. package/dist/BrowserRuntime.js +19 -1
  20. package/dist/BrowserRuntime.js.map +1 -1
  21. package/dist/BrowserSocket.d.ts +64 -6
  22. package/dist/BrowserSocket.d.ts.map +1 -1
  23. package/dist/BrowserSocket.js +64 -6
  24. package/dist/BrowserSocket.js.map +1 -1
  25. package/dist/BrowserStream.d.ts +48 -5
  26. package/dist/BrowserStream.d.ts.map +1 -1
  27. package/dist/BrowserStream.js +48 -5
  28. package/dist/BrowserStream.js.map +1 -1
  29. package/dist/BrowserWorker.d.ts +25 -4
  30. package/dist/BrowserWorker.d.ts.map +1 -1
  31. package/dist/BrowserWorker.js +62 -6
  32. package/dist/BrowserWorker.js.map +1 -1
  33. package/dist/BrowserWorkerRunner.d.ts +31 -6
  34. package/dist/BrowserWorkerRunner.d.ts.map +1 -1
  35. package/dist/BrowserWorkerRunner.js +65 -10
  36. package/dist/BrowserWorkerRunner.js.map +1 -1
  37. package/dist/Clipboard.d.ts +77 -13
  38. package/dist/Clipboard.d.ts.map +1 -1
  39. package/dist/Clipboard.js +57 -11
  40. package/dist/Clipboard.js.map +1 -1
  41. package/dist/Geolocation.d.ts +101 -24
  42. package/dist/Geolocation.d.ts.map +1 -1
  43. package/dist/Geolocation.js +69 -16
  44. package/dist/Geolocation.js.map +1 -1
  45. package/dist/IndexedDb.d.ts +89 -0
  46. package/dist/IndexedDb.d.ts.map +1 -0
  47. package/dist/IndexedDb.js +99 -0
  48. package/dist/IndexedDb.js.map +1 -0
  49. package/dist/IndexedDbDatabase.d.ts +169 -0
  50. package/dist/IndexedDbDatabase.d.ts.map +1 -0
  51. package/dist/IndexedDbDatabase.js +343 -0
  52. package/dist/IndexedDbDatabase.js.map +1 -0
  53. package/dist/IndexedDbQueryBuilder.d.ts +438 -0
  54. package/dist/IndexedDbQueryBuilder.d.ts.map +1 -0
  55. package/dist/IndexedDbQueryBuilder.js +935 -0
  56. package/dist/IndexedDbQueryBuilder.js.map +1 -0
  57. package/dist/IndexedDbTable.d.ts +191 -0
  58. package/dist/IndexedDbTable.d.ts.map +1 -0
  59. package/dist/IndexedDbTable.js +96 -0
  60. package/dist/IndexedDbTable.js.map +1 -0
  61. package/dist/IndexedDbVersion.d.ts +94 -0
  62. package/dist/IndexedDbVersion.d.ts.map +1 -0
  63. package/dist/IndexedDbVersion.js +39 -0
  64. package/dist/IndexedDbVersion.js.map +1 -0
  65. package/dist/Permissions.d.ts +76 -16
  66. package/dist/Permissions.d.ts.map +1 -1
  67. package/dist/Permissions.js +66 -11
  68. package/dist/Permissions.js.map +1 -1
  69. package/dist/index.d.ts +38 -10
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +38 -10
  72. package/dist/index.js.map +1 -1
  73. package/package.json +4 -3
  74. package/src/BrowserCrypto.ts +129 -0
  75. package/src/BrowserHttpClient.ts +84 -24
  76. package/src/BrowserKeyValueStore.ts +201 -12
  77. package/src/BrowserPersistence.ts +376 -0
  78. package/src/BrowserRuntime.ts +79 -4
  79. package/src/BrowserSocket.ts +64 -6
  80. package/src/BrowserStream.ts +48 -5
  81. package/src/BrowserWorker.ts +62 -6
  82. package/src/BrowserWorkerRunner.ts +65 -10
  83. package/src/Clipboard.ts +74 -13
  84. package/src/Geolocation.ts +97 -20
  85. package/src/IndexedDb.ts +127 -0
  86. package/src/IndexedDbDatabase.ts +664 -0
  87. package/src/IndexedDbQueryBuilder.ts +2048 -0
  88. package/src/IndexedDbTable.ts +285 -0
  89. package/src/IndexedDbVersion.ts +133 -0
  90. package/src/Permissions.ts +71 -14
  91. package/src/index.ts +45 -10
@@ -1,5 +1,40 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * Parent-side browser platform for running Effect workers.
3
+ *
4
+ * This module provides the `WorkerPlatform` used by browser code that spawns or
5
+ * connects to `Worker`, `SharedWorker`, and `MessagePort` endpoints through
6
+ * Effect's worker protocol. Pair it with `BrowserWorkerRunner` in the worker
7
+ * entrypoint when building worker-backed RPC clients, moving CPU-bound work off
8
+ * the main thread, isolating browser-only services, or adapting an existing
9
+ * `MessageChannel` in tests.
10
+ *
11
+ * **Mental model**
12
+ *
13
+ * Browser worker communication is normalized to a message port. Dedicated
14
+ * workers post messages on the worker object itself, shared workers post
15
+ * through `worker.port`, and raw `MessagePort` values can be supplied directly.
16
+ * `layerPlatform` provides only the browser platform, while `layer` combines
17
+ * the platform with a `Spawner` that creates a worker endpoint for each worker
18
+ * id.
19
+ *
20
+ * **Common tasks**
21
+ *
22
+ * Use `layer` when parent code should both provide browser worker messaging and
23
+ * define how workers are spawned. Use `layerPlatform` when a spawner is already
24
+ * provided elsewhere. Return a `MessagePort` from the spawner for tests or
25
+ * custom channels, a `Worker` for dedicated workers, or a `SharedWorker` when
26
+ * multiple browser contexts should share one worker runtime.
27
+ *
28
+ * **Gotchas**
29
+ *
30
+ * Messages use the browser structured-clone algorithm, so payloads and transfer
31
+ * lists must be accepted by the target runtime. Transferring an `ArrayBuffer` or
32
+ * `MessagePort` moves ownership away from the sender. Scope finalization sends
33
+ * the worker close signal over the port, but code that created a dedicated
34
+ * `Worker` remains responsible for broader lifecycle concerns such as
35
+ * terminating it.
36
+ *
37
+ * @since 4.0.0
3
38
  */
4
39
  import * as Deferred from "effect/Deferred"
5
40
  import * as Effect from "effect/Effect"
@@ -9,8 +44,27 @@ import * as Worker from "effect/unstable/workers/Worker"
9
44
  import { WorkerError, WorkerReceiveError } from "effect/unstable/workers/WorkerError"
10
45
 
11
46
  /**
12
- * @since 1.0.0
13
- * @category Layers
47
+ * Creates browser worker layers by combining the default `WorkerPlatform` with a spawner for `Worker`, `SharedWorker`, or `MessagePort` instances.
48
+ *
49
+ * **When to use**
50
+ *
51
+ * Use when browser parent or client code needs both the browser
52
+ * `WorkerPlatform` and a `Spawner` from one layer.
53
+ *
54
+ * **Details**
55
+ *
56
+ * The `spawn` callback receives the numeric worker id and may return a
57
+ * `Worker`, `SharedWorker`, or `MessagePort`.
58
+ *
59
+ * **Gotchas**
60
+ *
61
+ * Scope finalization sends the worker close protocol over the port. Dedicated
62
+ * workers created by `spawn` are not terminated by this layer.
63
+ *
64
+ * @see {@link layerPlatform} for providing only the browser worker platform
65
+ *
66
+ * @category layers
67
+ * @since 4.0.0
14
68
  */
15
69
  export const layer = (
16
70
  spawn: (id: number) => Worker | SharedWorker | MessagePort
@@ -21,8 +75,10 @@ export const layer = (
21
75
  )
22
76
 
23
77
  /**
24
- * @since 1.0.0
25
- * @category Layers
78
+ * Layer that provides the browser `WorkerPlatform` for `Worker`, `SharedWorker`, and `MessagePort` communication.
79
+ *
80
+ * @category layers
81
+ * @since 4.0.0
26
82
  */
27
83
  export const layerPlatform: Layer.Layer<Worker.WorkerPlatform> = Layer.succeed(Worker.WorkerPlatform)(
28
84
  Worker.makePlatform<globalThis.SharedWorker | globalThis.Worker | MessagePort>()({
@@ -50,7 +106,7 @@ export const layerPlatform: Layer.Layer<Worker.WorkerPlatform> = Layer.succeed(W
50
106
  message: "An error event was emitter",
51
107
  cause: event.error ?? event.message
52
108
  })
53
- }).asEffect()
109
+ })
54
110
  )
55
111
  }
56
112
  port.addEventListener("message", onMessage as any)
@@ -1,5 +1,35 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * Runner-side browser platform for Effect worker handlers.
3
+ *
4
+ * This module is for code already executing inside a browser worker, or for
5
+ * tests and adapters that pass a `MessagePort` or `Window` endpoint directly.
6
+ * It provides the `WorkerRunnerPlatform` used by `WorkerRunner` and protocols
7
+ * such as `RpcServer.layerProtocolWorkerRunner` to receive parent or client
8
+ * requests, run Effect handlers, and post responses back through the browser
9
+ * messaging channel.
10
+ *
11
+ * **Mental model**
12
+ *
13
+ * Dedicated workers use the ambient `self` endpoint. Shared workers receive one
14
+ * `MessagePort` per `onconnect` event, and this module caches ports that arrive
15
+ * before the runner layer starts. `layer` reads from the global worker `self`;
16
+ * `make` and `layerMessagePort` are for explicit endpoints supplied by tests,
17
+ * custom channels, or adapter code.
18
+ *
19
+ * **Common tasks**
20
+ *
21
+ * Pair this module with `BrowserWorker` in the parent page when moving RPC
22
+ * handlers, CPU-bound computations, or browser-only services into a dedicated
23
+ * worker or shared worker. Use `layer` in normal worker entry points and
24
+ * `layerMessagePort` when a test or integration already owns the transport.
25
+ *
26
+ * **Gotchas**
27
+ *
28
+ * Payloads and transfer lists must satisfy the browser structured-clone
29
+ * algorithm. `messageerror` and `error` events fail the runner, and each
30
+ * connected `MessagePort` is closed when its scope finalizes.
31
+ *
32
+ * @since 4.0.0
3
33
  */
4
34
  import * as Cause from "effect/Cause"
5
35
  import * as Deferred from "effect/Deferred"
@@ -22,8 +52,10 @@ if (typeof self !== "undefined" && "onconnect" in self) {
22
52
  }
23
53
 
24
54
  /**
25
- * @since 1.0.0
26
- * @category Constructors
55
+ * Creates a `WorkerRunnerPlatform` service that runs worker handlers over a `MessagePort` or `Window`.
56
+ *
57
+ * @category constructors
58
+ * @since 4.0.0
27
59
  */
28
60
  export const make = (self: MessagePort | Window): WorkerRunner.WorkerRunnerPlatform["Service"] => ({
29
61
  start: Effect.fnUntraced(function*<O = unknown, I = unknown>() {
@@ -44,7 +76,7 @@ export const make = (self: MessagePort | Window): WorkerRunner.WorkerRunnerPlatf
44
76
  Effect.scopedWith(Effect.fnUntraced(function*(scope) {
45
77
  const closeLatch = Deferred.makeUnsafe<void, WorkerError>()
46
78
  const trackFiber = Fiber.runIn(scope)
47
- const services = yield* Effect.services<R>()
79
+ const services = yield* Effect.context<R>()
48
80
  const runFork = Effect.runForkWith(services)
49
81
  const onExit = (exit: Exit.Exit<any, E>) => {
50
82
  if (exit._tag === "Failure" && !Cause.hasInterruptsOnly(exit.cause)) {
@@ -83,7 +115,7 @@ export const make = (self: MessagePort | Window): WorkerRunner.WorkerRunnerPlatf
83
115
  message: "An messageerror event was emitted",
84
116
  cause: error.data
85
117
  })
86
- }).asEffect()
118
+ })
87
119
  )
88
120
  }
89
121
  function onError(error: any) {
@@ -94,7 +126,7 @@ export const make = (self: MessagePort | Window): WorkerRunner.WorkerRunnerPlatf
94
126
  message: "An error event was emitted",
95
127
  cause: error.data
96
128
  })
97
- }).asEffect()
129
+ })
98
130
  )
99
131
  }
100
132
  function handlePort(port: MessagePort) {
@@ -151,16 +183,39 @@ export const make = (self: MessagePort | Window): WorkerRunner.WorkerRunnerPlatf
151
183
  })
152
184
 
153
185
  /**
154
- * @since 1.0.0
155
- * @category Layers
186
+ * Layer that provides a browser `WorkerRunnerPlatform` using the global `self` worker context.
187
+ *
188
+ * **When to use**
189
+ *
190
+ * Use when a browser worker entry point uses the ambient `self` object as the
191
+ * worker transport.
192
+ *
193
+ * **Details**
194
+ *
195
+ * Delegates to `make(self)` and provides the runner-side platform used by
196
+ * protocols such as `RpcServer.layerProtocolWorkerRunner`.
197
+ *
198
+ * **Gotchas**
199
+ *
200
+ * This layer depends on the browser worker global `self`. Use
201
+ * `layerMessagePort` when the transport is an explicit `MessagePort` or
202
+ * `Window`.
203
+ *
204
+ * @see {@link make} for constructing a runner platform from an explicit endpoint
205
+ * @see {@link layerMessagePort} for providing a platform from an explicit endpoint
206
+ *
207
+ * @category layers
208
+ * @since 4.0.0
156
209
  */
157
210
  export const layer: Layer.Layer<WorkerRunner.WorkerRunnerPlatform> = Layer.sync(WorkerRunner.WorkerRunnerPlatform)(() =>
158
211
  make(self)
159
212
  )
160
213
 
161
214
  /**
162
- * @since 1.0.0
163
- * @category Layers
215
+ * Layer that provides a `WorkerRunnerPlatform` using the supplied `MessagePort` or `Window`.
216
+ *
217
+ * @category layers
218
+ * @since 4.0.0
164
219
  */
165
220
  export const layerMessagePort = (port: MessagePort | Window): Layer.Layer<WorkerRunner.WorkerRunnerPlatform> =>
166
221
  Layer.succeed(WorkerRunner.WorkerRunnerPlatform)(make(port))
package/src/Clipboard.ts CHANGED
@@ -1,17 +1,64 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * Browser clipboard integration for Effect programs.
3
+ *
4
+ * This module provides a `Clipboard` service backed by `navigator.clipboard`.
5
+ * It keeps copy, paste, clear, and rich clipboard operations inside the Effect
6
+ * environment so browser UI code can require clipboard capability without
7
+ * calling the global API directly. Text helpers cover portable copy and paste
8
+ * flows, while `read`, `write`, and `writeBlob` expose `ClipboardItem` payloads
9
+ * for browsers that support richer MIME types.
10
+ *
11
+ * **Mental model**
12
+ *
13
+ * `Clipboard` is a capability service. Application code depends on the service
14
+ * tag, {@link layer} supplies the live browser implementation, and {@link make}
15
+ * builds custom implementations for tests, unsupported browsers, or constrained
16
+ * capabilities. Browser failures are converted to {@link ClipboardError}.
17
+ *
18
+ * **Common tasks**
19
+ *
20
+ * - Provide {@link layer} near the browser application edge.
21
+ * - Use `writeString` for copy buttons and generated text.
22
+ * - Use `readString` for paste or import workflows.
23
+ * - Use `write` or `writeBlob` for rich clipboard payloads when
24
+ * `ClipboardItem` is available.
25
+ * - Use `clear` to replace the clipboard with an empty string.
26
+ *
27
+ * **Gotchas**
28
+ *
29
+ * Clipboard access requires a secure context in modern browsers and may also
30
+ * require user activation, permissions, and a focused document. Support differs
31
+ * between reads, writes, text, and custom MIME payloads, so feature detection or
32
+ * graceful fallback is often needed around `ClipboardItem` usage.
33
+ *
34
+ * @since 4.0.0
3
35
  */
36
+ import * as Context from "effect/Context"
4
37
  import * as Data from "effect/Data"
5
38
  import * as Effect from "effect/Effect"
6
39
  import * as Layer from "effect/Layer"
7
- import * as ServiceMap from "effect/ServiceMap"
8
40
 
9
41
  const TypeId = "~@effect/platform-browser/Clipboard"
10
42
  const ErrorTypeId = "~@effect/platform-browser/Clipboard/ClipboardError"
11
43
 
12
44
  /**
13
- * @since 1.0.0
14
- * @category Models
45
+ * Service interface for reading from, writing to, and clearing the browser clipboard.
46
+ *
47
+ * **Details**
48
+ *
49
+ * `read` and `write` work with `ClipboardItem` arrays. `readString` and
50
+ * `writeString` use text, `writeBlob` writes one `Blob`, and `clear` writes an
51
+ * empty string.
52
+ *
53
+ * **Gotchas**
54
+ *
55
+ * Clipboard access generally requires a secure context and may require user
56
+ * activation, permissions, or a focused document. `ClipboardItem` and non-text
57
+ * MIME type support varies by browser. Failed browser operations are surfaced
58
+ * as `ClipboardError`.
59
+ *
60
+ * @category models
61
+ * @since 4.0.0
15
62
  */
16
63
  export interface Clipboard {
17
64
  readonly [TypeId]: typeof TypeId
@@ -24,8 +71,10 @@ export interface Clipboard {
24
71
  }
25
72
 
26
73
  /**
27
- * @since 1.0.0
28
- * @category Errors
74
+ * Tagged error raised when a browser clipboard operation fails.
75
+ *
76
+ * @category errors
77
+ * @since 4.0.0
29
78
  */
30
79
  export class ClipboardError extends Data.TaggedError("ClipboardError")<{
31
80
  readonly message: string
@@ -35,14 +84,26 @@ export class ClipboardError extends Data.TaggedError("ClipboardError")<{
35
84
  }
36
85
 
37
86
  /**
38
- * @since 1.0.0
39
- * @category Service
87
+ * Service tag for the browser `Clipboard` service.
88
+ *
89
+ * **When to use**
90
+ *
91
+ * Use when an Effect needs to require or provide clipboard capabilities through
92
+ * the context.
93
+ *
94
+ * @see {@link make} for building a custom clipboard service
95
+ * @see {@link layer} for providing the browser-backed clipboard service
96
+ *
97
+ * @category services
98
+ * @since 4.0.0
40
99
  */
41
- export const Clipboard: ServiceMap.Service<Clipboard, Clipboard> = ServiceMap.Service<Clipboard>(TypeId)
100
+ export const Clipboard: Context.Service<Clipboard, Clipboard> = Context.Service<Clipboard>(TypeId)
42
101
 
43
102
  /**
44
- * @since 1.0.0
45
- * @category Constructors
103
+ * Builds a `Clipboard` service from primitive read and write operations, deriving `clear` and `writeBlob` helpers.
104
+ *
105
+ * @category constructors
106
+ * @since 4.0.0
46
107
  */
47
108
  export const make = (
48
109
  impl: Omit<Clipboard, "clear" | "writeBlob" | typeof TypeId>
@@ -57,8 +118,8 @@ export const make = (
57
118
  /**
58
119
  * A layer that directly interfaces with the navigator.clipboard api
59
120
  *
60
- * @since 1.0.0
61
- * @category Layers
121
+ * @category layers
122
+ * @since 4.0.0
62
123
  */
63
124
  export const layer: Layer.Layer<Clipboard> = Layer.succeed(
64
125
  Clipboard,
@@ -1,20 +1,74 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * Browser geolocation integration for Effect programs.
3
+ *
4
+ * This module exposes a `Geolocation` service backed by
5
+ * `navigator.geolocation`. Use it for browser features that need a single
6
+ * position fix, such as nearby search or delivery estimates, or a stream of
7
+ * position updates for navigation, tracking, and location-aware interfaces.
8
+ * Browser failures are represented as typed `GeolocationError` values instead
9
+ * of raw callback errors.
10
+ *
11
+ * **Mental model**
12
+ *
13
+ * - The service delegates to the browser Geolocation API and follows the
14
+ * browser's permission, privacy, origin, and secure-context rules.
15
+ * - `getCurrentPosition` reads one position fix from the service.
16
+ * - {@link watchPosition} turns browser position callbacks into a `Stream` and
17
+ * clears the underlying browser watch when the stream is finalized.
18
+ *
19
+ * **Common tasks**
20
+ *
21
+ * - Provide the live browser implementation with {@link layer}.
22
+ * - Read a one-shot position from the `Geolocation` service.
23
+ * - Stream position updates with {@link watchPosition}.
24
+ * - Handle denied permissions, timeouts, and unavailable position data with
25
+ * {@link GeolocationError}.
26
+ *
27
+ * **Gotchas**
28
+ *
29
+ * - Browsers may prompt the user, reject access outside secure contexts, block
30
+ * access by permissions policy, or report that position data is unavailable.
31
+ * - {@link watchPosition} uses a sliding buffer; increase `bufferSize` if slow
32
+ * consumers must not skip older positions.
33
+ *
34
+ * @since 4.0.0
3
35
  */
4
36
  import * as Cause from "effect/Cause"
37
+ import * as Context from "effect/Context"
5
38
  import * as Data from "effect/Data"
6
39
  import * as Effect from "effect/Effect"
7
40
  import * as Layer from "effect/Layer"
8
41
  import * as Queue from "effect/Queue"
9
- import * as ServiceMap from "effect/ServiceMap"
10
42
  import * as Stream from "effect/Stream"
11
43
 
12
44
  const TypeId = "~@effect/platform-browser/Geolocation"
13
45
  const ErrorTypeId = "~@effect/platform-browser/Geolocation/GeolocationError"
14
46
 
15
47
  /**
16
- * @since 1.0.0
17
- * @category Models
48
+ * Service interface for browser geolocation, providing effects for the current position and streams of watched positions.
49
+ *
50
+ * **When to use**
51
+ *
52
+ * Use when browser code needs a typed Effect service for one-shot location
53
+ * reads or streamed location updates.
54
+ *
55
+ * **Details**
56
+ *
57
+ * `getCurrentPosition` returns one position effect. `watchPosition` returns a
58
+ * stream and accepts the browser `PositionOptions` plus an optional sliding
59
+ * `bufferSize`.
60
+ *
61
+ * **Gotchas**
62
+ *
63
+ * Browser permission prompts, denied permissions, timeouts, unavailable
64
+ * position data, secure-context restrictions, and policy restrictions are
65
+ * surfaced as `GeolocationError`.
66
+ *
67
+ * @see {@link GeolocationError} for represented browser geolocation failures
68
+ * @see {@link layer} for the browser-backed service implementation
69
+ *
70
+ * @category models
71
+ * @since 4.0.0
18
72
  */
19
73
  export interface Geolocation {
20
74
  readonly [TypeId]: typeof TypeId
@@ -31,14 +85,25 @@ export interface Geolocation {
31
85
  }
32
86
 
33
87
  /**
34
- * @since 1.0.0
35
- * @category Service
88
+ * Service tag for the browser `Geolocation` service.
89
+ *
90
+ * **When to use**
91
+ *
92
+ * Use when an Effect needs to access or provide geolocation capabilities
93
+ * through the context.
94
+ *
95
+ * @see {@link layer} for providing the browser-backed geolocation service
96
+ *
97
+ * @category services
98
+ * @since 4.0.0
36
99
  */
37
- export const Geolocation: ServiceMap.Service<Geolocation, Geolocation> = ServiceMap.Service<Geolocation>(TypeId)
100
+ export const Geolocation: Context.Service<Geolocation, Geolocation> = Context.Service<Geolocation>(TypeId)
38
101
 
39
102
  /**
40
- * @since 1.0.0
41
- * @category Errors
103
+ * Tagged error wrapping a browser geolocation failure reason.
104
+ *
105
+ * @category errors
106
+ * @since 4.0.0
42
107
  */
43
108
  export class GeolocationError extends Data.TaggedError("GeolocationError")<{
44
109
  readonly reason: GeolocationErrorReason
@@ -60,8 +125,10 @@ export class GeolocationError extends Data.TaggedError("GeolocationError")<{
60
125
  }
61
126
 
62
127
  /**
63
- * @since 1.0.0
64
- * @category Errors
128
+ * Error reason for the browser geolocation `POSITION_UNAVAILABLE` failure.
129
+ *
130
+ * @category errors
131
+ * @since 4.0.0
65
132
  */
66
133
  export class PositionUnavailable extends Data.TaggedError("PositionUnavailable")<{
67
134
  readonly cause: unknown
@@ -72,8 +139,10 @@ export class PositionUnavailable extends Data.TaggedError("PositionUnavailable")
72
139
  }
73
140
 
74
141
  /**
75
- * @since 1.0.0
76
- * @category Errors
142
+ * Error reason for the browser geolocation `PERMISSION_DENIED` failure.
143
+ *
144
+ * @category errors
145
+ * @since 4.0.0
77
146
  */
78
147
  export class PermissionDenied extends Data.TaggedError("PermissionDenied")<{
79
148
  readonly cause: unknown
@@ -84,8 +153,10 @@ export class PermissionDenied extends Data.TaggedError("PermissionDenied")<{
84
153
  }
85
154
 
86
155
  /**
87
- * @since 1.0.0
88
- * @category Errors
156
+ * Error reason for the browser geolocation `TIMEOUT` failure.
157
+ *
158
+ * @category errors
159
+ * @since 4.0.0
89
160
  */
90
161
  export class Timeout extends Data.TaggedError("Timeout")<{
91
162
  readonly cause: unknown
@@ -96,8 +167,10 @@ export class Timeout extends Data.TaggedError("Timeout")<{
96
167
  }
97
168
 
98
169
  /**
99
- * @since 1.0.0
100
- * @category Errors
170
+ * Union of browser geolocation error reasons represented by the service.
171
+ *
172
+ * @category errors
173
+ * @since 4.0.0
101
174
  */
102
175
  export type GeolocationErrorReason = PositionUnavailable | PermissionDenied | Timeout
103
176
 
@@ -141,8 +214,10 @@ const makeQueue = (
141
214
  )
142
215
 
143
216
  /**
144
- * @since 1.0.0
145
- * @category Layers
217
+ * Layer that provides `Geolocation` using `navigator.geolocation`, with watched positions buffered in a sliding queue.
218
+ *
219
+ * @category layers
220
+ * @since 4.0.0
146
221
  */
147
222
  export const layer: Layer.Layer<Geolocation> = Layer.succeed(
148
223
  Geolocation,
@@ -162,8 +237,10 @@ export const layer: Layer.Layer<Geolocation> = Layer.succeed(
162
237
  )
163
238
 
164
239
  /**
165
- * @since 1.0.0
240
+ * Streams positions from the `Geolocation` service using `watchPosition`, with an optional sliding buffer size.
241
+ *
166
242
  * @category Accessors
243
+ * @since 4.0.0
167
244
  */
168
245
  export const watchPosition = (
169
246
  options?:
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Browser IndexedDB primitives and key schemas for Effect applications.
3
+ *
4
+ * This module is the low-level bridge used by the platform-browser IndexedDB
5
+ * integration. It provides an `IndexedDb` service around the browser
6
+ * `indexedDB` factory and `IDBKeyRange` constructor, a `layerWindow` layer for
7
+ * wiring those primitives from `window`, and schemas for the key shapes accepted
8
+ * by IndexedDB object stores and indexes.
9
+ *
10
+ * Use it when building typed local persistence for browser caches,
11
+ * offline-first state, background queues, drafts, or other client-side data
12
+ * that should be validated before it reaches IndexedDB. Higher-level database,
13
+ * version, table, and query modules build on these primitives for migrations
14
+ * and typed transactions.
15
+ *
16
+ * IndexedDB still follows the browser rules: schema changes happen only during
17
+ * version upgrades, upgrades may be blocked by other open tabs or connections,
18
+ * and reads or writes must run in transactions scoped to the object stores they
19
+ * touch. The `layerWindow` constructor should be used only where browser
20
+ * globals are available, and code that also runs during SSR or in restricted
21
+ * browser contexts should account for `indexedDB` or `IDBKeyRange` being
22
+ * missing.
23
+ *
24
+ * @since 4.0.0
25
+ */
26
+ import * as Context from "effect/Context"
27
+ import * as Effect from "effect/Effect"
28
+ import * as Layer from "effect/Layer"
29
+ import * as Schema from "effect/Schema"
30
+
31
+ const TypeId = "~@effect/platform-browser/IndexedDb"
32
+
33
+ /**
34
+ * Service interface that provides the browser `indexedDB` factory and `IDBKeyRange` constructor.
35
+ *
36
+ * @category models
37
+ * @since 4.0.0
38
+ */
39
+ export interface IndexedDb {
40
+ readonly [TypeId]: typeof TypeId
41
+ readonly indexedDB: globalThis.IDBFactory
42
+ readonly IDBKeyRange: typeof globalThis.IDBKeyRange
43
+ }
44
+
45
+ /**
46
+ * Service tag for browser IndexedDB primitives.
47
+ *
48
+ * @category tag
49
+ * @since 4.0.0
50
+ */
51
+ export const IndexedDb: Context.Service<IndexedDb, IndexedDb> = Context.Service<IndexedDb, IndexedDb>(TypeId)
52
+
53
+ /** @internal */
54
+ const IDBFlatKey = Schema.Union([
55
+ Schema.String,
56
+ Schema.Number.check(Schema.makeFilter((input) => !Number.isNaN(input))),
57
+ Schema.DateValid,
58
+ Schema.declare(
59
+ (input): input is BufferSource =>
60
+ input instanceof ArrayBuffer ||
61
+ (ArrayBuffer.isView(input) && input.buffer instanceof ArrayBuffer)
62
+ )
63
+ ])
64
+
65
+ /**
66
+ * Schema for IndexedDB keys: strings, non-NaN numbers, valid dates, buffer sources, or arrays of those flat key values.
67
+ *
68
+ * @category schemas
69
+ * @since 4.0.0
70
+ */
71
+ export const IDBValidKey = Schema.Union([IDBFlatKey, Schema.Array(IDBFlatKey)])
72
+
73
+ /**
74
+ * Schema for auto-incremented IndexedDB keys, accepting integers from 1 through `2 ** 53`.
75
+ *
76
+ * **When to use**
77
+ *
78
+ * Use when defining numeric key-path fields for `IndexedDbTable` definitions
79
+ * that use IndexedDB auto-increment keys.
80
+ *
81
+ * **Details**
82
+ *
83
+ * The schema accepts integer values from `1` through `2 ** 53`, matching the
84
+ * range used for generated IndexedDB auto-increment keys.
85
+ *
86
+ * @see {@link IDBValidKey} for the broader IndexedDB key schema
87
+ *
88
+ * @category schemas
89
+ * @since 4.0.0
90
+ */
91
+ export const AutoIncrement = Schema.Int.check(
92
+ Schema.isBetween({ minimum: 1, maximum: 2 ** 53 })
93
+ ).annotate({
94
+ identifier: "AutoIncrement",
95
+ title: "autoIncrement",
96
+ description: "Defines a valid autoIncrement key path for the IndexedDb table"
97
+ })
98
+
99
+ /**
100
+ * Creates an `IndexedDb` service from an `IDBFactory` and `IDBKeyRange` constructor.
101
+ *
102
+ * @category constructors
103
+ * @since 4.0.0
104
+ */
105
+ export const make = (impl: Omit<IndexedDb, typeof TypeId>): IndexedDb => IndexedDb.of({ [TypeId]: TypeId, ...impl })
106
+
107
+ /**
108
+ * Layer that provides `IndexedDb` from `window.indexedDB` and `window.IDBKeyRange`, failing with a config error when they are unavailable.
109
+ *
110
+ * @category constructors
111
+ * @since 4.0.0
112
+ */
113
+ export const layerWindow: Layer.Layer<IndexedDb> = Layer.effect(
114
+ IndexedDb,
115
+ Effect.suspend(() => {
116
+ if (window.indexedDB && window.IDBKeyRange) {
117
+ return Effect.succeed(
118
+ make({
119
+ indexedDB: window.indexedDB,
120
+ IDBKeyRange: window.IDBKeyRange
121
+ })
122
+ )
123
+ } else {
124
+ return Effect.die(new Error("window.indexedDB is not available"))
125
+ }
126
+ })
127
+ )