@effect/platform-browser 4.0.0-beta.99 → 4.0.0-rc.108
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.
- package/AGENTS.md +381 -0
- package/CLAUDE.md +381 -0
- package/README.md +14 -1
- package/ai-docs/README.md +44 -0
- package/ai-docs/package.json +36 -0
- package/ai-docs/src/01_effect/01_basics/01_effect-gen.ts +30 -0
- package/ai-docs/src/01_effect/01_basics/02_effect-fn.ts +39 -0
- package/ai-docs/src/01_effect/01_basics/10_creating-effects.ts +74 -0
- package/ai-docs/src/01_effect/01_basics/index.md +5 -0
- package/ai-docs/src/01_effect/02_schema/10_schema-basics.ts +43 -0
- package/ai-docs/src/01_effect/02_schema/index.md +7 -0
- package/ai-docs/src/01_effect/03_services/01_service.ts +45 -0
- package/ai-docs/src/01_effect/03_services/10_reference.ts +10 -0
- package/ai-docs/src/01_effect/03_services/20_layer-composition.ts +70 -0
- package/ai-docs/src/01_effect/03_services/20_layer-unwrap.ts +66 -0
- package/ai-docs/src/01_effect/03_services/index.md +5 -0
- package/ai-docs/src/01_effect/04_errors/01_error-handling.ts +30 -0
- package/ai-docs/src/01_effect/04_errors/10_catch-tags.ts +24 -0
- package/ai-docs/src/01_effect/04_errors/20_reason-errors.ts +64 -0
- package/ai-docs/src/01_effect/04_errors/index.md +1 -0
- package/ai-docs/src/01_effect/05_resources/10_acquire-release.ts +105 -0
- package/ai-docs/src/01_effect/05_resources/20_layer-side-effects.ts +31 -0
- package/ai-docs/src/01_effect/05_resources/30_layer-map.ts +86 -0
- package/ai-docs/src/01_effect/05_resources/index.md +3 -0
- package/ai-docs/src/01_effect/06_running/10_run-main.ts +30 -0
- package/ai-docs/src/01_effect/06_running/20_layer-launch.ts +27 -0
- package/ai-docs/src/01_effect/06_running/index.md +1 -0
- package/ai-docs/src/01_effect/07_pubsub/10_pubsub.ts +56 -0
- package/ai-docs/src/01_effect/07_pubsub/index.md +3 -0
- package/ai-docs/src/03_stream/10_creating-streams.ts +103 -0
- package/ai-docs/src/03_stream/20_consuming-streams.ts +137 -0
- package/ai-docs/src/03_stream/30_encoding.ts +165 -0
- package/ai-docs/src/03_stream/index.md +4 -0
- package/ai-docs/src/04_integration/10_managed-runtime.ts +129 -0
- package/ai-docs/src/04_integration/index.md +5 -0
- package/ai-docs/src/05_batching/10_request-resolver.ts +89 -0
- package/ai-docs/src/05_batching/index.md +3 -0
- package/ai-docs/src/06_schedule/10_schedules.ts +110 -0
- package/ai-docs/src/06_schedule/index.md +3 -0
- package/ai-docs/src/07_datetime/10_creating-and-formatting.ts +30 -0
- package/ai-docs/src/07_datetime/20_time-zones.ts +44 -0
- package/ai-docs/src/07_datetime/index.md +5 -0
- package/ai-docs/src/08_observability/10_logging.ts +66 -0
- package/ai-docs/src/08_observability/20_otlp-tracing.ts +95 -0
- package/ai-docs/src/08_observability/index.md +7 -0
- package/ai-docs/src/09_testing/10_effect-tests.ts +55 -0
- package/ai-docs/src/09_testing/20_layer-tests.ts +138 -0
- package/ai-docs/src/09_testing/index.md +1 -0
- package/ai-docs/src/10_predicate/01_basics.ts +14 -0
- package/ai-docs/src/10_predicate/index.md +9 -0
- package/ai-docs/src/50_http-client/10_basics.ts +102 -0
- package/ai-docs/src/50_http-client/index.md +3 -0
- package/ai-docs/src/51_http-server/10_basics.ts +116 -0
- package/ai-docs/src/51_http-server/fixtures/api/Api.ts +14 -0
- package/ai-docs/src/51_http-server/fixtures/api/Authorization.ts +36 -0
- package/ai-docs/src/51_http-server/fixtures/api/System.ts +10 -0
- package/ai-docs/src/51_http-server/fixtures/api/Users.ts +91 -0
- package/ai-docs/src/51_http-server/fixtures/domain/User.ts +12 -0
- package/ai-docs/src/51_http-server/fixtures/domain/UserErrors.ts +22 -0
- package/ai-docs/src/51_http-server/fixtures/server/Authorization.ts +36 -0
- package/ai-docs/src/51_http-server/fixtures/server/Users/http.ts +71 -0
- package/ai-docs/src/51_http-server/fixtures/server/Users.ts +62 -0
- package/ai-docs/src/51_http-server/index.md +3 -0
- package/ai-docs/src/60_child-process/10_working-with-child-processes.ts +117 -0
- package/ai-docs/src/60_child-process/index.md +3 -0
- package/ai-docs/src/70_cli/10_basics.ts +136 -0
- package/ai-docs/src/70_cli/index.md +5 -0
- package/ai-docs/src/71_ai/10_language-model.ts +156 -0
- package/ai-docs/src/71_ai/20_tools.ts +226 -0
- package/ai-docs/src/71_ai/30_chat.ts +158 -0
- package/ai-docs/src/71_ai/fixtures/domain/LaunchPlan.ts +9 -0
- package/ai-docs/src/71_ai/index.md +5 -0
- package/ai-docs/src/80_cluster/10_entities.ts +97 -0
- package/ai-docs/src/80_cluster/index.md +4 -0
- package/ai-docs/src/index.md +10 -0
- package/ai-docs/tsconfig.json +24 -0
- package/dist/BrowserCrypto.d.ts +1 -1
- package/dist/BrowserCrypto.d.ts.map +1 -1
- package/dist/BrowserCrypto.js +4 -2
- package/dist/BrowserCrypto.js.map +1 -1
- package/dist/BrowserHttpClient.d.ts +5 -5
- package/dist/BrowserHttpClient.d.ts.map +1 -1
- package/dist/BrowserHttpClient.js +12 -7
- package/dist/BrowserHttpClient.js.map +1 -1
- package/dist/BrowserKeyValueStore.d.ts.map +1 -1
- package/dist/BrowserKeyValueStore.js +38 -9
- package/dist/BrowserKeyValueStore.js.map +1 -1
- package/dist/BrowserPersistence.js.map +1 -1
- package/dist/BrowserRuntime.d.ts +3 -3
- package/dist/BrowserRuntime.js +1 -1
- package/dist/BrowserRuntime.js.map +1 -1
- package/dist/BrowserSocket.js.map +1 -1
- package/dist/BrowserStream.d.ts +2 -2
- package/dist/BrowserStream.js +2 -2
- package/dist/BrowserStream.js.map +1 -1
- package/dist/BrowserWorker.js.map +1 -1
- package/dist/BrowserWorkerRunner.d.ts.map +1 -1
- package/dist/BrowserWorkerRunner.js +2 -1
- package/dist/BrowserWorkerRunner.js.map +1 -1
- package/dist/Clipboard.d.ts +1 -1
- package/dist/Clipboard.js.map +1 -1
- package/dist/Geolocation.d.ts +1 -1
- package/dist/Geolocation.js.map +1 -1
- package/dist/IndexedDb.d.ts +3 -3
- package/dist/IndexedDb.d.ts.map +1 -1
- package/dist/IndexedDb.js +2 -2
- package/dist/IndexedDb.js.map +1 -1
- package/dist/IndexedDbDatabase.d.ts +3 -3
- package/dist/IndexedDbDatabase.d.ts.map +1 -1
- package/dist/IndexedDbDatabase.js +13 -7
- package/dist/IndexedDbDatabase.js.map +1 -1
- package/dist/IndexedDbQueryBuilder.d.ts +9 -9
- package/dist/IndexedDbQueryBuilder.d.ts.map +1 -1
- package/dist/IndexedDbQueryBuilder.js +38 -13
- package/dist/IndexedDbQueryBuilder.js.map +1 -1
- package/dist/IndexedDbTable.d.ts +9 -9
- package/dist/IndexedDbTable.js.map +1 -1
- package/dist/IndexedDbVersion.d.ts +4 -4
- package/dist/IndexedDbVersion.js.map +1 -1
- package/dist/Permissions.d.ts +1 -1
- package/dist/Permissions.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +10 -11
- package/src/BrowserCrypto.ts +4 -2
- package/src/BrowserHttpClient.ts +11 -7
- package/src/BrowserKeyValueStore.ts +50 -8
- package/src/BrowserRuntime.ts +3 -3
- package/src/BrowserStream.ts +2 -2
- package/src/BrowserWorkerRunner.ts +2 -1
- package/src/Clipboard.ts +1 -1
- package/src/Geolocation.ts +1 -1
- package/src/IndexedDb.ts +3 -3
- package/src/IndexedDbDatabase.ts +15 -9
- package/src/IndexedDbQueryBuilder.ts +64 -21
- package/src/IndexedDbTable.ts +9 -9
- package/src/IndexedDbVersion.ts +4 -4
- package/src/Permissions.ts +1 -1
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect/platform-browser",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "4.0.0-
|
|
4
|
+
"version": "4.0.0-rc.108",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Platform specific implementations for the browser",
|
|
7
7
|
"homepage": "https://effect.website",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "https://github.com/Effect-TS/effect.git",
|
|
11
|
-
"directory": "packages/platform
|
|
11
|
+
"directory": "packages/platform/browser"
|
|
12
12
|
},
|
|
13
13
|
"bugs": {
|
|
14
14
|
"url": "https://github.com/Effect-TS/effect/issues"
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
".": "./dist/index.js",
|
|
32
32
|
"./*": "./dist/*.js",
|
|
33
33
|
"./internal/*": null,
|
|
34
|
+
"./index": null,
|
|
34
35
|
"./*/index": null
|
|
35
36
|
},
|
|
36
37
|
"files": [
|
|
@@ -38,29 +39,27 @@
|
|
|
38
39
|
"dist/**/*.js",
|
|
39
40
|
"dist/**/*.js.map",
|
|
40
41
|
"dist/**/*.d.ts",
|
|
41
|
-
"dist/**/*.d.ts.map"
|
|
42
|
+
"dist/**/*.d.ts.map",
|
|
43
|
+
"AGENTS.md",
|
|
44
|
+
"CLAUDE.md",
|
|
45
|
+
"ai-docs/**/*"
|
|
42
46
|
],
|
|
43
47
|
"publishConfig": {
|
|
44
48
|
"access": "public",
|
|
45
49
|
"provenance": true
|
|
46
50
|
},
|
|
47
51
|
"peerDependencies": {
|
|
48
|
-
"effect": "^4.0.0-
|
|
52
|
+
"effect": "^4.0.0-rc.108"
|
|
49
53
|
},
|
|
50
54
|
"devDependencies": {
|
|
51
55
|
"fake-indexeddb": "^6.2.5",
|
|
52
56
|
"mock-xmlhttprequest": "^8.4.1",
|
|
53
|
-
"effect": "^4.0.0-
|
|
54
|
-
},
|
|
55
|
-
"dependencies": {
|
|
56
|
-
"multipasta": "^0.2.8"
|
|
57
|
+
"effect": "^4.0.0-rc.108"
|
|
57
58
|
},
|
|
58
59
|
"scripts": {
|
|
59
60
|
"codegen": "effect-utils codegen",
|
|
60
61
|
"build": "tsc -b tsconfig.json && pnpm babel",
|
|
61
62
|
"babel": "babel dist --plugins annotate-pure-calls --out-dir dist --source-maps",
|
|
62
|
-
"check": "tsc -b tsconfig.json"
|
|
63
|
-
"test": "vitest",
|
|
64
|
-
"coverage": "vitest --coverage"
|
|
63
|
+
"check": "tsc -b tsconfig.json"
|
|
65
64
|
}
|
|
66
65
|
}
|
package/src/BrowserCrypto.ts
CHANGED
|
@@ -22,7 +22,7 @@ import * as PlatformError from "effect/PlatformError"
|
|
|
22
22
|
* Use to override the browser `Crypto` object used by the platform crypto
|
|
23
23
|
* layer.
|
|
24
24
|
*
|
|
25
|
-
* @category
|
|
25
|
+
* @category services
|
|
26
26
|
* @since 1.0.0
|
|
27
27
|
*/
|
|
28
28
|
export const WebCrypto = Context.Reference<Crypto>("@effect/platform-browser/Crypto/WebCrypto", {
|
|
@@ -60,7 +60,9 @@ export const layer: Layer.Layer<EffectCrypto.Crypto> = Layer.effect(
|
|
|
60
60
|
}
|
|
61
61
|
const randomBytes = (size: number): Uint8Array => {
|
|
62
62
|
const bytes = new Uint8Array(size)
|
|
63
|
-
|
|
63
|
+
for (let i = 0; i < bytes.length; i += 65_536) {
|
|
64
|
+
crypto.getRandomValues(bytes.subarray(i, i + 65_536))
|
|
65
|
+
}
|
|
64
66
|
return bytes
|
|
65
67
|
}
|
|
66
68
|
|
package/src/BrowserHttpClient.ts
CHANGED
|
@@ -28,8 +28,8 @@ import * as HttpClientError from "effect/unstable/http/HttpClientError"
|
|
|
28
28
|
import type * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"
|
|
29
29
|
import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse"
|
|
30
30
|
import * as HttpIncomingMessage from "effect/unstable/http/HttpIncomingMessage"
|
|
31
|
+
import * as HeaderParser from "effect/unstable/http/MultipartParser/HeadersParser"
|
|
31
32
|
import * as UrlParams from "effect/unstable/http/UrlParams"
|
|
32
|
-
import * as HeaderParser from "multipasta/HeadersParser"
|
|
33
33
|
|
|
34
34
|
// =============================================================================
|
|
35
35
|
// Fetch
|
|
@@ -39,14 +39,14 @@ export {
|
|
|
39
39
|
/**
|
|
40
40
|
* Context reference for the `fetch` implementation used by the fetch-based HTTP client.
|
|
41
41
|
*
|
|
42
|
-
* @category
|
|
42
|
+
* @category services
|
|
43
43
|
* @since 4.0.0
|
|
44
44
|
*/
|
|
45
45
|
Fetch,
|
|
46
46
|
/**
|
|
47
47
|
* Layer that provides an `HttpClient` implementation backed by the configured `Fetch` function.
|
|
48
48
|
*
|
|
49
|
-
* @category
|
|
49
|
+
* @category layers
|
|
50
50
|
* @since 4.0.0
|
|
51
51
|
*/
|
|
52
52
|
layer as layerFetch,
|
|
@@ -58,7 +58,7 @@ export {
|
|
|
58
58
|
* Use to provide default credentials, cache, redirect, integrity, or other
|
|
59
59
|
* fetch options for browser HTTP requests.
|
|
60
60
|
*
|
|
61
|
-
* @category
|
|
61
|
+
* @category services
|
|
62
62
|
* @since 4.0.0
|
|
63
63
|
*/
|
|
64
64
|
RequestInit
|
|
@@ -87,7 +87,7 @@ export type XHRResponseType = "arraybuffer" | "text"
|
|
|
87
87
|
* @see {@link XHRResponseType} for the allowed response body modes
|
|
88
88
|
* @see {@link withXHRArrayBuffer} for scoping XHR response handling to `ArrayBuffer`
|
|
89
89
|
*
|
|
90
|
-
* @category
|
|
90
|
+
* @category services
|
|
91
91
|
* @since 4.0.0
|
|
92
92
|
*/
|
|
93
93
|
export const CurrentXHRResponseType: Context.Reference<XHRResponseType> = Context.Reference(
|
|
@@ -98,7 +98,7 @@ export const CurrentXHRResponseType: Context.Reference<XHRResponseType> = Contex
|
|
|
98
98
|
/**
|
|
99
99
|
* Runs an effect with `CurrentXHRResponseType` set to `"arraybuffer"` so the XHR HTTP client receives response bodies as `ArrayBuffer` values.
|
|
100
100
|
*
|
|
101
|
-
* @category
|
|
101
|
+
* @category providing services
|
|
102
102
|
* @since 4.0.0
|
|
103
103
|
*/
|
|
104
104
|
export const withXHRArrayBuffer = <A, E, R>(
|
|
@@ -399,7 +399,11 @@ class ClientResponseImpl extends IncomingMessageImpl<HttpClientError.HttpClientE
|
|
|
399
399
|
}
|
|
400
400
|
|
|
401
401
|
get formData(): Effect.Effect<FormData, HttpClientError.HttpClientError> {
|
|
402
|
-
return Effect.
|
|
402
|
+
return Effect.flatMap(this.arrayBuffer, (body) =>
|
|
403
|
+
Effect.tryPromise({
|
|
404
|
+
try: () => new globalThis.Response(body, { headers: this.headers }).formData(),
|
|
405
|
+
catch: this.onError
|
|
406
|
+
}))
|
|
403
407
|
}
|
|
404
408
|
|
|
405
409
|
override toString(): string {
|
|
@@ -74,8 +74,11 @@ export const layerIndexedDb = (options?: {
|
|
|
74
74
|
|
|
75
75
|
return KeyValueStore.make({
|
|
76
76
|
clear: Effect.suspend(() => {
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
return idbWriteRequest(
|
|
78
|
+
db,
|
|
79
|
+
{ method: "clear", message: "Failed to clear backing store" },
|
|
80
|
+
(store) => store.clear()
|
|
81
|
+
)
|
|
79
82
|
}),
|
|
80
83
|
get: (key: string) =>
|
|
81
84
|
Effect.map(
|
|
@@ -103,10 +106,10 @@ export const layerIndexedDb = (options?: {
|
|
|
103
106
|
),
|
|
104
107
|
set: (key: string, value: string | Uint8Array) =>
|
|
105
108
|
Effect.asVoid(Effect.suspend(() => {
|
|
106
|
-
|
|
107
|
-
|
|
109
|
+
return idbWriteRequest(
|
|
110
|
+
db,
|
|
108
111
|
{ method: "set", message: "Failed to set value in backing store", key },
|
|
109
|
-
() => store.put({ key, value })
|
|
112
|
+
(store) => store.put({ key, value })
|
|
110
113
|
)
|
|
111
114
|
})),
|
|
112
115
|
size: Effect.suspend(() => {
|
|
@@ -118,10 +121,10 @@ export const layerIndexedDb = (options?: {
|
|
|
118
121
|
}),
|
|
119
122
|
remove: (key: string) =>
|
|
120
123
|
Effect.asVoid(Effect.suspend(() => {
|
|
121
|
-
|
|
122
|
-
|
|
124
|
+
return idbWriteRequest(
|
|
125
|
+
db,
|
|
123
126
|
{ method: "remove", message: "Failed to remove value from backing store", key },
|
|
124
|
-
() => store.delete(key)
|
|
127
|
+
(store) => store.delete(key)
|
|
125
128
|
)
|
|
126
129
|
}))
|
|
127
130
|
})
|
|
@@ -171,6 +174,45 @@ const idbRequest = <A>(
|
|
|
171
174
|
))
|
|
172
175
|
})
|
|
173
176
|
|
|
177
|
+
const idbWriteRequest = <A>(
|
|
178
|
+
db: IDBDatabase,
|
|
179
|
+
failArgs: { method: string; message: string; key?: string },
|
|
180
|
+
evaluate: (store: IDBObjectStore) => IDBRequest<A>
|
|
181
|
+
): Effect.Effect<A, KeyValueStore.KeyValueStoreError> =>
|
|
182
|
+
Effect.callback<A, KeyValueStore.KeyValueStoreError>((resume) => {
|
|
183
|
+
const transaction = db.transaction(entriesStoreName, "readwrite")
|
|
184
|
+
const request = evaluate(transaction.objectStore(entriesStoreName))
|
|
185
|
+
let result: A
|
|
186
|
+
let done = false
|
|
187
|
+
|
|
188
|
+
const fail = (cause: unknown) => {
|
|
189
|
+
if (done) return
|
|
190
|
+
done = true
|
|
191
|
+
resume(Effect.fail(new KeyValueStore.KeyValueStoreError({ ...failArgs, cause })))
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (request.readyState === "done") {
|
|
195
|
+
result = request.result
|
|
196
|
+
} else {
|
|
197
|
+
request.onsuccess = () => {
|
|
198
|
+
result = request.result
|
|
199
|
+
}
|
|
200
|
+
request.onerror = () => fail(request.error)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
transaction.oncomplete = () => {
|
|
204
|
+
if (done) return
|
|
205
|
+
done = true
|
|
206
|
+
resume(Effect.succeed(result!))
|
|
207
|
+
}
|
|
208
|
+
transaction.onerror = () => fail(transaction.error)
|
|
209
|
+
transaction.onabort = () => fail(transaction.error)
|
|
210
|
+
|
|
211
|
+
return Effect.sync(() => {
|
|
212
|
+
if (!done) transaction.abort()
|
|
213
|
+
})
|
|
214
|
+
})
|
|
215
|
+
|
|
174
216
|
const getKvsEntriesStore = (db: IDBDatabase, mode: IDBTransactionMode) => {
|
|
175
217
|
const transaction = db.transaction(entriesStoreName, mode)
|
|
176
218
|
return transaction.objectStore(entriesStoreName)
|
package/src/BrowserRuntime.ts
CHANGED
|
@@ -29,7 +29,7 @@ import { makeRunMain, type Teardown } from "effect/Runtime"
|
|
|
29
29
|
* The `beforeunload` interruption is best-effort. Browser teardown may prevent
|
|
30
30
|
* asynchronous finalizers, network work, timers, or prompts from completing.
|
|
31
31
|
*
|
|
32
|
-
* @category
|
|
32
|
+
* @category running
|
|
33
33
|
* @since 4.0.0
|
|
34
34
|
*/
|
|
35
35
|
export const runMain: {
|
|
@@ -52,7 +52,7 @@ export const runMain: {
|
|
|
52
52
|
* The `beforeunload` interruption is best-effort. Browser teardown may prevent
|
|
53
53
|
* asynchronous finalizers, network work, timers, or prompts from completing.
|
|
54
54
|
*
|
|
55
|
-
* @category
|
|
55
|
+
* @category running
|
|
56
56
|
* @since 4.0.0
|
|
57
57
|
*/
|
|
58
58
|
(
|
|
@@ -80,7 +80,7 @@ export const runMain: {
|
|
|
80
80
|
* The `beforeunload` interruption is best-effort. Browser teardown may prevent
|
|
81
81
|
* asynchronous finalizers, network work, timers, or prompts from completing.
|
|
82
82
|
*
|
|
83
|
-
* @category
|
|
83
|
+
* @category running
|
|
84
84
|
* @since 4.0.0
|
|
85
85
|
*/
|
|
86
86
|
<E, A>(
|
package/src/BrowserStream.ts
CHANGED
|
@@ -19,7 +19,7 @@ import * as Stream from "effect/Stream"
|
|
|
19
19
|
* buffer size by passing an object as the second argument with the `bufferSize`
|
|
20
20
|
* field.
|
|
21
21
|
*
|
|
22
|
-
* @category
|
|
22
|
+
* @category constructors
|
|
23
23
|
* @since 4.0.0
|
|
24
24
|
*/
|
|
25
25
|
export const fromEventListenerWindow = <K extends keyof WindowEventMap>(
|
|
@@ -41,7 +41,7 @@ export const fromEventListenerWindow = <K extends keyof WindowEventMap>(
|
|
|
41
41
|
* buffer size by passing an object as the second argument with the `bufferSize`
|
|
42
42
|
* field.
|
|
43
43
|
*
|
|
44
|
-
* @category
|
|
44
|
+
* @category constructors
|
|
45
45
|
* @since 4.0.0
|
|
46
46
|
*/
|
|
47
47
|
export const fromEventListenerDocument = <K extends keyof DocumentEventMap>(
|
|
@@ -81,6 +81,7 @@ export const make = (self: MessagePort | Window): WorkerRunner.WorkerRunnerPlatf
|
|
|
81
81
|
return Deferred.doneUnsafe(closeLatch, Exit.void)
|
|
82
82
|
}
|
|
83
83
|
ports.delete(portId)
|
|
84
|
+
Queue.offerUnsafe(disconnects, portId)
|
|
84
85
|
Effect.runFork(Scope.close(port[1], Exit.void))
|
|
85
86
|
}
|
|
86
87
|
}
|
|
@@ -122,7 +123,7 @@ export const make = (self: MessagePort | Window): WorkerRunner.WorkerRunnerPlatf
|
|
|
122
123
|
portScope,
|
|
123
124
|
Effect.sync(() => {
|
|
124
125
|
port.removeEventListener("message", onMsg)
|
|
125
|
-
port.removeEventListener("messageerror",
|
|
126
|
+
port.removeEventListener("messageerror", onMessageError)
|
|
126
127
|
port.close()
|
|
127
128
|
})
|
|
128
129
|
))
|
package/src/Clipboard.ts
CHANGED
|
@@ -38,7 +38,7 @@ const ErrorTypeId = "~@effect/platform-browser/Clipboard/ClipboardError"
|
|
|
38
38
|
* MIME type support varies by browser. Failed browser operations are surfaced
|
|
39
39
|
* as `ClipboardError`.
|
|
40
40
|
*
|
|
41
|
-
* @category
|
|
41
|
+
* @category services
|
|
42
42
|
* @since 4.0.0
|
|
43
43
|
*/
|
|
44
44
|
export interface Clipboard {
|
package/src/Geolocation.ts
CHANGED
|
@@ -44,7 +44,7 @@ const ErrorTypeId = "~@effect/platform-browser/Geolocation/GeolocationError"
|
|
|
44
44
|
* @see {@link GeolocationError} for represented browser geolocation failures
|
|
45
45
|
* @see {@link layer} for the browser-backed service implementation
|
|
46
46
|
*
|
|
47
|
-
* @category
|
|
47
|
+
* @category services
|
|
48
48
|
* @since 4.0.0
|
|
49
49
|
*/
|
|
50
50
|
export interface Geolocation {
|
package/src/IndexedDb.ts
CHANGED
|
@@ -19,7 +19,7 @@ const TypeId = "~@effect/platform-browser/IndexedDb"
|
|
|
19
19
|
/**
|
|
20
20
|
* Service interface that provides the browser `indexedDB` factory and `IDBKeyRange` constructor.
|
|
21
21
|
*
|
|
22
|
-
* @category
|
|
22
|
+
* @category services
|
|
23
23
|
* @since 4.0.0
|
|
24
24
|
*/
|
|
25
25
|
export interface IndexedDb {
|
|
@@ -40,7 +40,7 @@ export const IndexedDb: Context.Service<IndexedDb, IndexedDb> = Context.Service<
|
|
|
40
40
|
const IDBFlatKey = Schema.Union([
|
|
41
41
|
Schema.String,
|
|
42
42
|
Schema.Number.check(Schema.makeFilter((input) => !Number.isNaN(input))),
|
|
43
|
-
Schema.
|
|
43
|
+
Schema.Date,
|
|
44
44
|
Schema.declare(
|
|
45
45
|
(input): input is BufferSource =>
|
|
46
46
|
input instanceof ArrayBuffer ||
|
|
@@ -93,7 +93,7 @@ export const make = (impl: Omit<IndexedDb, typeof TypeId>): IndexedDb => Indexed
|
|
|
93
93
|
/**
|
|
94
94
|
* Layer that provides `IndexedDb` from `window.indexedDB` and `window.IDBKeyRange`, failing with a config error when they are unavailable.
|
|
95
95
|
*
|
|
96
|
-
* @category
|
|
96
|
+
* @category layers
|
|
97
97
|
* @since 4.0.0
|
|
98
98
|
*/
|
|
99
99
|
export const layerWindow: Layer.Layer<IndexedDb> = Layer.effect(
|
package/src/IndexedDbDatabase.ts
CHANGED
|
@@ -31,12 +31,6 @@ const SchemaProto = {
|
|
|
31
31
|
[TypeId]: {
|
|
32
32
|
_A: (_: never) => _
|
|
33
33
|
},
|
|
34
|
-
...Effectable.Prototype<IndexedDbSchema<any, any, any>>({
|
|
35
|
-
label: "IndexedDbSchema",
|
|
36
|
-
evaluate() {
|
|
37
|
-
return this.getQueryBuilder
|
|
38
|
-
}
|
|
39
|
-
}),
|
|
40
34
|
get getQueryBuilder() {
|
|
41
35
|
const self = this as unknown as IndexedDbSchema<any, any, any>
|
|
42
36
|
return IndexedDbDatabase.useSync(({ database, IDBKeyRange, reactivity }) =>
|
|
@@ -48,6 +42,12 @@ const SchemaProto = {
|
|
|
48
42
|
})
|
|
49
43
|
)
|
|
50
44
|
},
|
|
45
|
+
...Effectable.Prototype<IndexedDbSchema<any, any, any>>({
|
|
46
|
+
label: "IndexedDbSchema",
|
|
47
|
+
evaluate() {
|
|
48
|
+
return this.getQueryBuilder
|
|
49
|
+
}
|
|
50
|
+
}),
|
|
51
51
|
add<Version extends IndexedDbVersion.AnyWithProps>(
|
|
52
52
|
this: IndexedDbSchema<any, any, any>,
|
|
53
53
|
version: Version,
|
|
@@ -126,7 +126,7 @@ export class IndexedDbDatabaseError extends Data.TaggedError(
|
|
|
126
126
|
* @see {@link IndexedDb.IndexedDb} for the lower-level browser IndexedDB primitives
|
|
127
127
|
* @see {@link make} for creating a schema that provides this service as a layer
|
|
128
128
|
*
|
|
129
|
-
* @category
|
|
129
|
+
* @category services
|
|
130
130
|
* @since 4.0.0
|
|
131
131
|
*/
|
|
132
132
|
export class IndexedDbDatabase extends Context.Service<
|
|
@@ -234,7 +234,7 @@ export interface Transaction<
|
|
|
234
234
|
/**
|
|
235
235
|
* Extracts the string-literal index names defined by an `IndexedDbTable`.
|
|
236
236
|
*
|
|
237
|
-
* @category
|
|
237
|
+
* @category utility types
|
|
238
238
|
* @since 4.0.0
|
|
239
239
|
*/
|
|
240
240
|
export type IndexFromTable<Table extends IndexedDbTable.AnyWithProps> = IsStringLiteral<
|
|
@@ -245,7 +245,7 @@ export type IndexFromTable<Table extends IndexedDbTable.AnyWithProps> = IsString
|
|
|
245
245
|
/**
|
|
246
246
|
* Extracts the valid index names for a table name within an IndexedDB version.
|
|
247
247
|
*
|
|
248
|
-
* @category
|
|
248
|
+
* @category utility types
|
|
249
249
|
* @since 4.0.0
|
|
250
250
|
*/
|
|
251
251
|
export type IndexFromTableName<
|
|
@@ -478,6 +478,12 @@ const layer = <DatabaseName extends string>(
|
|
|
478
478
|
Effect.provideService(IndexedDbQueryBuilder.IndexedDbTransaction, transaction)
|
|
479
479
|
)
|
|
480
480
|
fiber = runForkWith(effect)
|
|
481
|
+
fiber.addObserver((exit) => {
|
|
482
|
+
if (exit._tag === "Failure") {
|
|
483
|
+
transaction.abort()
|
|
484
|
+
resume(exit)
|
|
485
|
+
}
|
|
486
|
+
})
|
|
481
487
|
fiber.currentDispatcher.flush()
|
|
482
488
|
}
|
|
483
489
|
|
|
@@ -136,13 +136,17 @@ export interface IndexedDbQueryBuilder<
|
|
|
136
136
|
readonly tables: Tables
|
|
137
137
|
readonly mode: Mode
|
|
138
138
|
readonly durability?: IDBTransactionDurability
|
|
139
|
-
}) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<
|
|
139
|
+
}) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<
|
|
140
|
+
A,
|
|
141
|
+
E | IndexedDbQueryError,
|
|
142
|
+
Exclude<R, IndexedDbTransaction>
|
|
143
|
+
>
|
|
140
144
|
}
|
|
141
145
|
|
|
142
146
|
/**
|
|
143
147
|
* Valid key-path type for a table schema, using encoded fields whose values are IndexedDB-valid keys.
|
|
144
148
|
*
|
|
145
|
-
* @category
|
|
149
|
+
* @category utility types
|
|
146
150
|
* @since 4.0.0
|
|
147
151
|
*/
|
|
148
152
|
export type KeyPath<TableSchema extends IndexedDbTable.AnySchemaStruct> =
|
|
@@ -152,7 +156,7 @@ export type KeyPath<TableSchema extends IndexedDbTable.AnySchemaStruct> =
|
|
|
152
156
|
/**
|
|
153
157
|
* Valid numeric key-path type for a table schema, used for auto-increment key paths.
|
|
154
158
|
*
|
|
155
|
-
* @category
|
|
159
|
+
* @category utility types
|
|
156
160
|
* @since 4.0.0
|
|
157
161
|
*/
|
|
158
162
|
export type KeyPathNumber<TableSchema extends IndexedDbTable.AnySchemaStruct> =
|
|
@@ -168,7 +172,7 @@ export declare namespace IndexedDbQuery {
|
|
|
168
172
|
/**
|
|
169
173
|
* Decoded row type returned by select queries, adding a `key` field when the table does not define a key path.
|
|
170
174
|
*
|
|
171
|
-
* @category
|
|
175
|
+
* @category utility types
|
|
172
176
|
* @since 4.0.0
|
|
173
177
|
*/
|
|
174
178
|
export type SelectType<
|
|
@@ -181,7 +185,7 @@ export declare namespace IndexedDbQuery {
|
|
|
181
185
|
/**
|
|
182
186
|
* Input type for insert and upsert operations, adjusted for auto-increment keys and out-of-line keys.
|
|
183
187
|
*
|
|
184
|
-
* @category
|
|
188
|
+
* @category utility types
|
|
185
189
|
* @since 4.0.0
|
|
186
190
|
*/
|
|
187
191
|
export type ModifyType<
|
|
@@ -215,7 +219,7 @@ export declare namespace IndexedDbQuery {
|
|
|
215
219
|
/**
|
|
216
220
|
* Value type accepted by `equals` comparisons for a table key path or index.
|
|
217
221
|
*
|
|
218
|
-
* @category
|
|
222
|
+
* @category utility types
|
|
219
223
|
* @since 4.0.0
|
|
220
224
|
*/
|
|
221
225
|
export type EqualsType<
|
|
@@ -229,7 +233,7 @@ export declare namespace IndexedDbQuery {
|
|
|
229
233
|
/**
|
|
230
234
|
* Value type accepted by range comparisons for a table key path or index, including partial tuples for compound indexes.
|
|
231
235
|
*
|
|
232
|
-
* @category
|
|
236
|
+
* @category utility types
|
|
233
237
|
* @since 4.0.0
|
|
234
238
|
*/
|
|
235
239
|
export type ExtractIndexType<
|
|
@@ -248,7 +252,7 @@ export declare namespace IndexedDbQuery {
|
|
|
248
252
|
/**
|
|
249
253
|
* Mutation input type for insert and upsert operations, including any required key fields.
|
|
250
254
|
*
|
|
251
|
-
* @category
|
|
255
|
+
* @category utility types
|
|
252
256
|
* @since 4.0.0
|
|
253
257
|
*/
|
|
254
258
|
export type ModifyWithKey<Table extends IndexedDbTable.AnyWithProps> = ModifyType<Table>
|
|
@@ -719,7 +723,7 @@ export declare namespace IndexedDbQuery {
|
|
|
719
723
|
/**
|
|
720
724
|
* Service tag for the active `IDBTransaction` used to share a transaction across IndexedDB query effects.
|
|
721
725
|
*
|
|
722
|
-
* @category
|
|
726
|
+
* @category services
|
|
723
727
|
* @since 4.0.0
|
|
724
728
|
*/
|
|
725
729
|
export class IndexedDbTransaction extends Context.Service<IndexedDbTransaction, globalThis.IDBTransaction>()(
|
|
@@ -752,6 +756,7 @@ const applyDelete = (query: IndexedDbQuery.Delete<any, never>) =>
|
|
|
752
756
|
durability: query.delete.from.table.durability
|
|
753
757
|
})
|
|
754
758
|
const objectStore = transaction.objectStore(query.delete.from.table.tableName)
|
|
759
|
+
const store = query.delete.index === undefined ? objectStore : objectStore.index(query.delete.index)
|
|
755
760
|
const predicate = query.predicate
|
|
756
761
|
|
|
757
762
|
let keyRange: globalThis.IDBKeyRange | undefined = undefined
|
|
@@ -782,8 +787,8 @@ const applyDelete = (query: IndexedDbQuery.Delete<any, never>) =>
|
|
|
782
787
|
|
|
783
788
|
let request: globalThis.IDBRequest
|
|
784
789
|
|
|
785
|
-
if (query.limitValue !== undefined || predicate) {
|
|
786
|
-
const cursorRequest =
|
|
790
|
+
if (query.delete.index !== undefined || query.limitValue !== undefined || predicate) {
|
|
791
|
+
const cursorRequest = store.openCursor(keyRange)
|
|
787
792
|
let count = 0
|
|
788
793
|
|
|
789
794
|
cursorRequest.onerror = () => {
|
|
@@ -897,7 +902,7 @@ const applySelect = Effect.fnUntraced(function*(
|
|
|
897
902
|
const keyPath = query.from.table.keyPath
|
|
898
903
|
const predicate = query.predicate
|
|
899
904
|
|
|
900
|
-
const data = predicate || keyPath === undefined || query.offsetValue !== undefined ?
|
|
905
|
+
const data = predicate || keyPath === undefined || query.offsetValue !== undefined || query.reverseValue ?
|
|
901
906
|
yield* Effect.callback<Array<any>, IndexedDbQueryError>((resume) => {
|
|
902
907
|
const { keyRange, store } = getReadonlyObjectStore(query)
|
|
903
908
|
|
|
@@ -1001,7 +1006,13 @@ const applyFirst = Effect.fnUntraced(function*(
|
|
|
1001
1006
|
}
|
|
1002
1007
|
|
|
1003
1008
|
request.onsuccess = () => {
|
|
1004
|
-
|
|
1009
|
+
if (request.result === undefined) {
|
|
1010
|
+
resume(
|
|
1011
|
+
Effect.fail(new Cause.NoSuchElementError(`No such element in table ${query.select.from.table.tableName}`))
|
|
1012
|
+
)
|
|
1013
|
+
} else {
|
|
1014
|
+
resume(Effect.succeed(request.result))
|
|
1015
|
+
}
|
|
1005
1016
|
}
|
|
1006
1017
|
} else {
|
|
1007
1018
|
const request = store.openCursor()
|
|
@@ -1331,7 +1342,6 @@ const FromProto: Omit<
|
|
|
1331
1342
|
| "countCache"
|
|
1332
1343
|
| "deleteCache"
|
|
1333
1344
|
> = {
|
|
1334
|
-
...CommonProto,
|
|
1335
1345
|
select<Index extends IndexedDbDatabase.IndexFromTable<any>>(
|
|
1336
1346
|
this: IndexedDbQuery.From<any>,
|
|
1337
1347
|
index?: Index
|
|
@@ -1392,7 +1402,8 @@ const FromProto: Omit<
|
|
|
1392
1402
|
database: self.database.current,
|
|
1393
1403
|
table: self.table
|
|
1394
1404
|
})
|
|
1395
|
-
}
|
|
1405
|
+
},
|
|
1406
|
+
...CommonProto
|
|
1396
1407
|
}
|
|
1397
1408
|
|
|
1398
1409
|
const makeFrom = <
|
|
@@ -1516,7 +1527,7 @@ const DeleteProto: Omit<
|
|
|
1516
1527
|
filter(this: IndexedDbQuery.Delete<any, never>, filter: (value: IndexedDbTable.Encoded<any>) => boolean) {
|
|
1517
1528
|
const prev = this.predicate
|
|
1518
1529
|
return makeDelete({
|
|
1519
|
-
|
|
1530
|
+
...this,
|
|
1520
1531
|
predicate: prev ? (item) => prev(item) && filter(item) : filter
|
|
1521
1532
|
})
|
|
1522
1533
|
},
|
|
@@ -1760,18 +1771,22 @@ const SelectProto: Omit<
|
|
|
1760
1771
|
}) {
|
|
1761
1772
|
const limit = this.limitValue
|
|
1762
1773
|
const chunkSize = Math.min(options?.chunkSize ?? 100, limit ?? Number.MAX_SAFE_INTEGER)
|
|
1763
|
-
const
|
|
1774
|
+
const initialOffset = this.offsetValue ?? 0
|
|
1764
1775
|
return Stream.suspend(() => {
|
|
1765
1776
|
let total = 0
|
|
1777
|
+
const initial = this.limit(chunkSize)
|
|
1766
1778
|
return Stream.paginate(initial, (select) =>
|
|
1767
1779
|
Effect.map(
|
|
1768
1780
|
applySelect(select as any),
|
|
1769
1781
|
(data) => {
|
|
1770
1782
|
total += data.length
|
|
1771
|
-
;(select as any).offsetValue = total
|
|
1772
1783
|
const reachedLimit = limit && total >= limit
|
|
1773
1784
|
const isPartial = data.length < chunkSize
|
|
1774
|
-
|
|
1785
|
+
const next = makeSelect({
|
|
1786
|
+
...select,
|
|
1787
|
+
offsetValue: initialOffset + total
|
|
1788
|
+
})
|
|
1789
|
+
return [data, isPartial || reachedLimit ? Option.none() : Option.some(next)] as const
|
|
1775
1790
|
}
|
|
1776
1791
|
))
|
|
1777
1792
|
})
|
|
@@ -1951,7 +1966,6 @@ const QueryBuilderProto: Omit<
|
|
|
1951
1966
|
| "IDBTransaction"
|
|
1952
1967
|
| "reactivity"
|
|
1953
1968
|
> = {
|
|
1954
|
-
...CommonProto,
|
|
1955
1969
|
use(this: IndexedDbQueryBuilder<any>, f: (database: globalThis.IDBDatabase) => any) {
|
|
1956
1970
|
return Effect.try({
|
|
1957
1971
|
try: () => f(this.database.current),
|
|
@@ -1979,6 +1993,7 @@ const QueryBuilderProto: Omit<
|
|
|
1979
1993
|
const self = this as IndexedDbQueryBuilder<any>
|
|
1980
1994
|
return applyClearAll({ database: self.database.current })
|
|
1981
1995
|
},
|
|
1996
|
+
...CommonProto,
|
|
1982
1997
|
withTransaction(this: IndexedDbQueryBuilder<any>, options: {
|
|
1983
1998
|
readonly tables: NonEmptyReadonlyArray<any>
|
|
1984
1999
|
readonly mode: globalThis.IDBTransactionMode
|
|
@@ -1987,7 +2002,11 @@ const QueryBuilderProto: Omit<
|
|
|
1987
2002
|
return (effect) =>
|
|
1988
2003
|
Effect.suspend(() => {
|
|
1989
2004
|
const transaction = this.database.current.transaction(options.tables, options.mode, options)
|
|
1990
|
-
return Effect.provideService(effect, IndexedDbTransaction, transaction)
|
|
2005
|
+
return Effect.provideService(effect, IndexedDbTransaction, transaction).pipe(
|
|
2006
|
+
Effect.onExit((exit) =>
|
|
2007
|
+
exit._tag === "Success" ? awaitTransaction(transaction) : abortTransaction(transaction)
|
|
2008
|
+
)
|
|
2009
|
+
)
|
|
1991
2010
|
}).pipe(
|
|
1992
2011
|
// To prevent async gaps between transaction queries
|
|
1993
2012
|
Effect.provideService(References.PreventSchedulerYield, true)
|
|
@@ -1995,6 +2014,30 @@ const QueryBuilderProto: Omit<
|
|
|
1995
2014
|
}
|
|
1996
2015
|
}
|
|
1997
2016
|
|
|
2017
|
+
const abortTransaction = (transaction: globalThis.IDBTransaction) =>
|
|
2018
|
+
Effect.try({
|
|
2019
|
+
try: () => transaction.abort(),
|
|
2020
|
+
catch: () => undefined
|
|
2021
|
+
}).pipe(Effect.ignore)
|
|
2022
|
+
|
|
2023
|
+
const awaitTransaction = (transaction: globalThis.IDBTransaction) =>
|
|
2024
|
+
Effect.callback<void, IndexedDbQueryError>((resume) => {
|
|
2025
|
+
transaction.oncomplete = () => {
|
|
2026
|
+
resume(Effect.void)
|
|
2027
|
+
}
|
|
2028
|
+
transaction.onabort = () => {
|
|
2029
|
+
resume(
|
|
2030
|
+
Effect.fail(
|
|
2031
|
+
new IndexedDbQueryError({
|
|
2032
|
+
reason: "TransactionError",
|
|
2033
|
+
cause: transaction.error
|
|
2034
|
+
})
|
|
2035
|
+
)
|
|
2036
|
+
)
|
|
2037
|
+
}
|
|
2038
|
+
return abortTransaction(transaction)
|
|
2039
|
+
})
|
|
2040
|
+
|
|
1998
2041
|
/**
|
|
1999
2042
|
* Creates an `IndexedDbQueryBuilder` from an open database reference, key-range constructor, table map, and reactivity service.
|
|
2000
2043
|
*
|